scala – 从方法符号和正文创建方法定义树
发布时间:2020-12-16 08:56:29 所属栏目:安全 来源:网络整理
导读:有没有一种方便的方法可以将 MethodSymbol 转换为Scala 2.10中方法定义树(即 DefDef )的左侧? 例如,假设我想创建一个宏来获取特征的实例,并用一些调试功能包装所有特征的方法.我可以写下面的内容: import scala.language.experimental.macrosimport scala.
有没有一种方便的方法可以将
MethodSymbol 转换为Scala 2.10中方法定义树(即
DefDef )的左侧?
例如,假设我想创建一个宏来获取特征的实例,并用一些调试功能包装所有特征的方法.我可以写下面的内容: 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,TypeTree(),Block( Apply(f,c.literal("Calling: " + m.name.decoded).tree :: Nil),Select(a.tree,m.name) ) ) }.toList //... } 我已经省去了无聊的业务,将这些方法粘贴在一个新的匿名类中,该类实现了特性,然后实例化了该类 – 如果你感兴趣的话,你可以找到一个完整的工作示例here. 现在我可以写这个,例如: 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中错过了一些更好的方法吗? 解决方法
据我所知,从符号到定义树没有标准的方法.
你最好的选择可能是迭代c.enclosingRun.units,然后逐步递归到每个unit.body树中.如果您看到一个DefDef,其符号等于您的符号,那么您已到达目的地. UPD.在重用之前不要忘记复制定义树! 这种技术远非世界上最方便的东西,但它应该有效. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |