2016-05-16 65 views
1

参数来StaticAnnotation宏,我想传递一个类作为参数传递给Scala中的一个StaticAnnotation宏,让我们说我需要一台DateTime实例检查宏:传递类如Scala中

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

经过一番调整后,我终于找到了一种方法来检索更复杂的参数,以在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并为其创建适当的案例。