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
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…