有没有方便的方法来转MethodSymbol http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library/index.html#scala.reflect.api.Symbols%24MethodSymbolApi进入方法定义树的左侧(即DefDef http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library/index.html#scala.reflect.api.Trees%24DefDefApi)在 Scala 2.10 中?
例如,假设我想创建一个宏,它将采用一个特征的实例,并使用一些调试功能包装该特征的所有方法。我可以写以下内容:
import scala.language.experimental.macros
import scala.reflect.macros.Context
object WrapperExample {
def wrap[A](a: A): A = macro wrap_impl[A]
def wrap_impl[A: c.WeakTypeTag](c: Context)(a: c.Expr[A]) = {
import c.universe._
val wrapped = weakTypeOf[A]
val f = Select(reify(Predef).tree, "println")
val methods = wrapped.declarations.collect {
case m: MethodSymbol if !m.isConstructor => DefDef(
Modifiers(Flag.OVERRIDE),
m.name,
Nil, Nil,
TypeTree(),
Block(
Apply(f, c.literal("Calling: " + m.name.decoded).tree :: Nil),
Select(a.tree, m.name)
)
)
}.toList
//...
}
我已经省略了将这些方法粘贴到一个实现该特征的新匿名类中,然后实例化该类的无聊业务 - 您可以找到一个完整的工作示例here https://gist.github.com/4234441如果你有兴趣的话。
现在我可以这样写,例如:
scala> trait X { def foo = 1; def bar = 'a }
defined trait X
scala> val x = new X {}
x: X = $anon$1@15dd533
scala> val w: X = WrapperExample.wrap[X](x)
w: X = $1$$1@27c3a4a3
scala> w.foo
Calling: foo
res0: Int = 1
scala> w.bar
Calling: bar
res1: Symbol = 'a
所以它可以工作,但仅在非常简单的情况下 - 如果特征具有带有参数列表、访问修饰符、注释等的方法,则它不会工作。
我真正想要的是一个函数,它将采用方法符号和新主体的树并返回DefDef
。我已经开始手写一个,但它涉及很多繁琐的事情,比如:
List(if (method.isImplicit) Some(Flag.IMPLICIT) else None, ...)
这很烦人、冗长且容易出错。我是否缺少一些更好的方法来在新的 Reflection API 中执行此操作?