Macro to access source code text at runtime

前端 未结 2 506
离开以前
离开以前 2020-12-16 21:48

Is there already or is it possible to have a Scala macro that gives me access to the text of the source? For instance I would like to write code like this:

v         


        
2条回答
  •  被撕碎了的回忆
    2020-12-16 22:11

    Do you really want a source code or Tree is enough?

    For Tree you could use prefix of Context like this:

    import scala.language.experimental.macros
    import reflect.macros.Context
    
    implicit class WithSourceHelper[T](source: T) {
      def withSource[R](f: (String, T) => R): R = macro withSourceImpl[T, R]
    }
    
    def withSourceImpl[T, R](c: Context)(f: c.Expr[(String, T) => R]): c.Expr[R] = {
      import c.universe.{reify, Apply}
    
      val source = c.prefix.tree match {
        case Apply(_, List(s)) => s
        case _ => c.abort(c.enclosingPosition, "can't find source")
      }
    
      reify{ f.splice.apply(c.literal(source.toString).splice, c.Expr[T](source).splice) }
    }
    

    Usage:

    scala> val (x, y) = (1, 2)
    x: Int = 1
    y: Int = 2
    
    scala> {x + y}.withSource{ (s, r) => s"$s = $r" }
    res15: String = x.+(y) = 3
    
    scala> val list = List(1, 2, 3)
    list: List[Int] = List(1, 2, 3)
    
    scala> val (text, sum) = (list.sum).withSource{(source, sum) => (source, sum)}
    text: String = list.sum[Int](math.this.Numeric.IntIsIntegral)
    sum: Int = 6
    
    scala> (list.sum).withSource{(source, sum) => println(s"$source: $sum")}
    $line38.$read.$iw.$iw.$iw.list.sum[Int](math.this.Numeric.IntIsIntegral): 6
    

提交回复
热议问题