简体   繁体   中英

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?

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.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM