scala - Scala宏如何使用参数默认值将MethodSymbol转换为DefDef?
问题描述
我一直在编写的宏通常需要处理来自库等中其他对象/模块的所有定义,因此树不可用。在宏内部,我经常需要将从另一个对象获得的 MethodSymbol 转换为我的目标 trait 中的一个新 API 调用,该 API 调用复制包含默认参数的函数签名。
但是,我还没有找到一种方法来获取 MethodSymbol 中参数的默认参数值,因此当我构建结果时,我无法按照我的意愿“复制”一些方法签名。
有没有办法获得默认参数,比如从符号“类型”的“成员”属性获得的参数,对于 MethodSymbol 中的参数?
解决方案
您可以使用以下技术
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
def foo[A]: Unit = macro impl[A]
def impl[A: c.WeakTypeTag](c: blackbox.Context): c.Tree = {
import c.universe._
// just for testing, in actual use case methodSymbol is obtained from somewhere
val methodSymbol = weakTypeOf[A].decl(TermName("smth")).asMethod
val traverser = new Traverser {
override def traverse(tree: Tree): Unit = {
tree match {
case t @ q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" if t.symbol == methodSymbol =>
paramss.flatten.foreach {
case q"$mods1 val $tname1: $tpt1 = $expr1" =>
println(s"method $tname: default value of $tname1 is $expr1")
case _ =>
}
case _ =>
}
super.traverse(tree)
}
}
c.enclosingRun.units.foreach(unit =>
traverser.traverse(unit.body)
)
q"()"
}
object App {
class MyClass {
def smth(x: Int = 1): Unit = ()
}
foo[MyClass] //Warning:scalac: method smth: default value of x is 1
}
推荐阅读
- c# - 如何将泛型类型传递给泛型方法
- javascript - (类型错误):dayDataFiltered[0] 未定义
- android - 在 Flutter 中,如何将一个小部件中的任意点与另一个小部件中的任意点对齐?
- git - 从 GitLab 存储库获取分支时出现 Git GUI 错误(错误 503)
- c++ - 为什么 stl 使用仿函数实现 std::greater?
- install4j - 如何在 Install4j 的自定义代码和资源文件选项中使用 tar.gz
- sql - 更新多行的不同列
- c - How to strtok in C twice?
- javascript - 阅读多个内容的更多/更少按钮 - Javascript
- next.js - next-i18next deployed in AWS CloudFront traces error ENOENT: no such file or directory, scandir '/var/task/public/static/'