semkagtn
semkagtn

Reputation: 25

Scala: generate Java annotation with parameter using Scala macros

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

Answers (1)

Eugene Burmako
Eugene Burmako

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

Related Questions