So I have an annotation on a function (DefDef). This annotation has parameters. However, I am confused on how to get the parameters from the constructor.
Usage example:
class TestMacro {
@Foo(true)
def foo(): String = ""
foo
}
Here's the code for the annotation:
class Foo(b: Boolean) extends StaticAnnotation {
def macroTransform(annottees: Any*) = macro Foo.impl
}
object Foo {
def impl(c: whitebox.Context)(annottees: c.Tree*): c.Expr[Any] = {
import c.universe._
//how do I get value of `b` here???
c.abort(c.enclosingPosition, "message")
}
}
What about this:
For sake of completeness this is the full source:
This is an answer that shows a variation on Federico's technique, if you want to use a static annotation that has optional named arguments. In that case, you need to consider the possible invocation expressions in the case matching statement. An optional argument might be explicitly named, it might be given without a name, or it might be not present. Each of these shows up at compile time as a separate pattern in
c.prefix.tree
, as shown below.Here is an example invocation that names
arg2
, and so it will match the first pattern -case q"new noop($arg1, arg2 = $arg2)"
- above:Note also that because of the way these patterns work, you have to explicitly supply the default argument value inside the macro code, which is unfortunately a bit hacky, but the final evaluated class is not available to you.
As an experiment, I tried actually creating the class by calling
evalTree[scope.of.class.noop](c.prefix.tree)
, but the Scala compiler throws an error because it considered that a reference to the annotation inside the annotation macro code, which is illegal.