【问题标题】:Passing class as a parameter to StaticAnnotation macro in scala将类作为参数传递给scala中的StaticAnnotation宏
【发布时间】:2016-09-12 03:44:12
【问题描述】:

我想将一个类作为参数传递给 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 实例?

【问题讨论】:

    标签: scala macros


    【解决方案1】:

    经过一番调整,我终于找到了一种在 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 并为其创建适当的案例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-22
      • 1970-01-01
      • 2016-08-07
      • 1970-01-01
      • 1970-01-01
      • 2019-07-23
      • 2018-05-16
      • 1970-01-01
      相关资源
      最近更新 更多