I would like to pass a class as a parameter to a StaticAnnotation
macro in Scala, let's say I need a macro that checks on DateTime instance:
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._
???
}
And implementation:
@CheckDate(new DateTime(...))
class Sth(...) {...}
How can I retrieve the DateTime instance from an AST?
After a bit of tweaking I finally found a way to retrieve more complex parameters for StaticAnnotation
macro in scala.
First of all I extracted all parameters through pattern matching on c.prefix.tree
, which actually refers to the annotation class, like so:
val params = c.prefix.tree match {
case q"""new CheckDate(...$paramss)""" => paramss
case _ => c.warning(NoPosition, "Oops, something went terribly wrong!")
}
I tried to inspect the tree for params by printing the tree with showRaw(params)
, and there are two possible patterns (with or without parameter name):
List(List(AssignOrNamedArg(
Ident(TermName("date")),
Apply(Select(New(Ident(TypeName("DateTime"))), termNames.CONSTRUCTOR),
List(Literal(Constant(2016)), Literal(Constant(5)), Literal(Constant(10)))))))
or
List(List(Apply(
Select(New(Ident(TypeName("DateTime"))), termNames.CONSTRUCTOR),
List(Literal(Constant(2016)), Literal(Constant(5)), Literal(Constant(11))))))
In order to use the DateTime
object we need to extract the appropriate fields and create new DateTime
instances:
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)
Lot's of boilerplate actually, but the way turns out quite efficient. The key is to inspect the AST of the structure to be parsed and create appropriate cases for it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.