我想将一个类作为参数传递给Scala中的StaticAnnotation
宏,让我们说我需要一个检查DateTime实例的宏:
class CheckDate(date: DateTime) extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro CheckDate.impl
}
object CheckDate {
def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
???
}
并实施:
@CheckDate(new DateTime(...))
class Sth(...) {...}
如何从AST中检索DateTime实例?
答案 0 :(得分:0)
经过一些调整后,我终于找到了一种方法来为scala中的StaticAnnotation
宏检索更复杂的参数。
首先,我通过c.prefix.tree
上的模式匹配提取了所有参数,实际上是指注释类,如下所示:
val params = c.prefix.tree match {
case q"""new CheckDate(...$paramss)""" => paramss
case _ => c.warning(NoPosition, "Oops, something went terribly wrong!")
}
我尝试通过使用showRaw(params)
打印树来检查树的参数,并且有两种可能的模式(带或不带参数名称):
List(List(AssignOrNamedArg(
Ident(TermName("date")),
Apply(Select(New(Ident(TypeName("DateTime"))), termNames.CONSTRUCTOR),
List(Literal(Constant(2016)), Literal(Constant(5)), Literal(Constant(10)))))))
或
List(List(Apply(
Select(New(Ident(TypeName("DateTime"))), termNames.CONSTRUCTOR),
List(Literal(Constant(2016)), Literal(Constant(5)), Literal(Constant(11))))))
为了使用DateTime
对象,我们需要提取相应的字段并创建新的DateTime
个实例:
val d: DateTime = params match {
case List(List(AssignOrNamedArg(
_, Apply(_, List(Literal(Constant(y)), Literal(Constant(m)), Literal(Constant(d))))))) =>
new DateTime(y.asInstanceOf[Int], m.asInstanceOf[Int], d.asInstanceOf[Int], 0, 0)
case List(List(Apply(_, List(Literal(Constant(y)),
Literal(Constant(m)), Literal(Constant(d)))))) =>
new DateTime(y.asInstanceOf[Int], m.asInstanceOf[Int], d.asInstanceOf[Int], 0, 0)
实际上很多样板,但结果非常有效。关键是要检查要解析的结构的AST并为其创建适当的案例。