Reputation: 25
I have simple Java annotation with one parameter:
public @interface Annot {
String value();
}
Also I have Java annotation that takes array of Annot as parameter:
public @interface Annotations {
Annot[] value();
}
I want to generate Annot with paramter "value" using Scala macro like this:
object MyAnnotations {
def MyAnnotation: Annot = macro myAnnotationMacro
def myAnnotationMacro(c: whitebox.Context): c.Expr[Annot] = {
import c.universe._
c.Expr(q"""new Annot("value")""")
}
}
While this works:
@Annotations(Array(
new Annot("value")
))
trait T
This doesn't work:
@Annotations(Array(
MyAnnotations.MyAnnotation
)) // too many arguments for constructor Annot: ()Annot
trait T
Why? And how can I generate Annot?
Upvotes: 1
Views: 146
Reputation: 13048
I'm afraid that you can't do what you want with macros.
Typechecking of Java annotations is implemented in a very weird way that is significantly different from the rest of the typechecker. While everything else is typechecked from Tree
to Tree
, arguments to Java annotations are typechecked from Tree
to ClassfileAnnotArg
(with the latter not being trees). Your macro expands into a Tree
, whereas the typechecker expects ClassfileAnnotArg
, so things don't work (and the error message is quite misleading).
I think that it would be possible to change the typechecker to work in your case, but that will require patching the compiler. No idea how to do that from within a macro.
Upvotes: 1