Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access Annotation defined on case class field at Runtime

I've the following java Annotation defined

   @Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.FIELD})
   @Retention(RetentionPolicy.RUNTIME)
   public @interface MyAnnotation { 
     String value() default "";
   }

And I've the following scala case class defined:

@Prefer("xyz")
case class TestAnno(arg1 : String, @Prefer("abc") agr2 : String)

I'm able see the annotation defined at case class level using reflection but I'm not able to access the annotation defined for arg2 member of case class TestAnno. De-compiling the code I see that neither the variable declaration or it's scala accessor seem to have the annotation. Only the constructor definition and copy method seem to retain the annotation for the parameters as defined in case class declaration.

Is there some other way to force the scala compiler to generate annotations for the fields declared in case class or I have to read the constructor and use a library such as ASM ByteCode Library or ParaNamer to find which parameters have which annotations? Need a solution which will work primarily for Scala case classes.

like image 712
cracked_all Avatar asked Jul 13 '12 10:07

cracked_all


2 Answers

You just need to do the following :

case class TestAnno(arg1 : String, @(Prefer @field)("abc") agr2 : String)

More info here http://www.scala-lang.org/api/current/#scala.annotation.meta.package

like image 125
Quentin Avatar answered Oct 06 '22 01:10

Quentin


Quentin's solution worked, but IMHO it's too much boilerplate for the user.

You can read annotations on the constructor arguments with the standard reflection API. I needed this for a macro implementation.

scala> :paste
// Entering paste mode (ctrl-D to finish)

import scala.annotation.StaticAnnotation
final class min(i: Long) extends StaticAnnotation

case class Foo(@min(1) c: String)
import scala.reflect.runtime.universe._
symbolOf[Foo].asClass.primaryConstructor.typeSignature.paramLists.head.head.annotations

// Exiting paste mode, now interpreting.

import scala.annotation.StaticAnnotation
defined class min
defined class Foo
import scala.reflect.runtime.universe._
res0: List[reflect.runtime.universe.Annotation] = List(min(1L))
like image 26
Dimitri Avatar answered Oct 06 '22 01:10

Dimitri