Scala 宏:c.universe.Tree 到 c.universe.Name

Scala Macros: c.universe.Tree to c.universe.Name

我正在尝试使用宏和静态注释生成案例 类。

有什么方法可以将 c.universe.Tree 转换为另一种 c.universe 类型,尤其是 c.universe.Name

答案取决于您拥有哪种类型的树,但无论如何您都希望从树变为字符串,然后您可以创建 TypeNameTermNameTypeNameTermName 构造函数。

例如,这里我们的树是一个字符串文字:

import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context

def callFooImpl(c: Context)(name: c.Expr[String]): c.Expr[Unit] = {
  import c.universe._

  val termName: TermName = name.tree match {
    case Literal(Constant(s: String)) => TermName(s)
    case _ => c.abort(c.enclosingPosition, "Not a string literal")
  }

  c.Expr[Unit](q"$termName.foo()")
}

def callFoo(name: String): Unit = macro callFooImpl

case class Foo(i: Int) {
  def foo(): Unit = println(s"Called foo() on $this")
}

然后:

scala> :paste
// Entering paste mode (ctrl-D to finish)

val myFoo = Foo(10)
callFoo("myFoo")

// Exiting paste mode, now interpreting.

Called foo() on Foo(10)
myFoo: Foo = Foo(10)

这里我们用 LiteralConstant 解构了字符串文字树以获得编译时字符串,然后我们用它来创建一个 TermName,我们可以在我们生成的代码中使用。