0

I have Sample class with Size annotation

case class Sample(
  attr: SomeTypeA
  @Size(value = 50)
  name: SomeTypeB)

This Size annotation is a class that implements AnnotationInterface

trait AnnotationInterface[T] {
  def getValue: T
}

class Size(value: Int) extends StaticAnnotation with AnnotationInterface[Int] {
    override def getValue: Int = value
}

And I have Extractor which is responsible for extracting class members using reflection

class Extractor[A](implicit
    tt: TypeTag[A],
    ct: ClassTag[A]
) { ...extract class members using reflection... } 

Then I would instantiate the extractor like:

val extractor: Extractor[Sample] =
      new Extractor 

Question : How can I call the method getValue: T inside the class Extractor ?

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
yuntres
  • 47
  • 1
  • 1
  • 6

1 Answers1

1

If you annotate like

@Size(50) name: String

rather than with meta-annotations like

@(Size @getter @setter @field)(50) name: String

then @Size remains only on constructor parameter, not field, getter or setter. So you need to use constructor of A.

Try

class Extractor[A](implicit
                   tt: TypeTag[A],
                   ct: ClassTag[A]
                  ) {
  val annotationTree = typeOf[A]
    .decl(termNames.CONSTRUCTOR).asMethod
    .paramLists.flatten
    .flatMap(_.annotations)
    .map(_.tree)
    .filter(_.tpe =:= typeOf[Size])
    .head 

  annotationTree match {
    case q"new $_($value)" => println(value) //50
  }
}

if you need the value or

import scala.tools.reflect.ToolBox
val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()

tb.eval(tb.untypecheck(annotationTree)).asInstanceOf[Size].getValue //50

if you really want to call getValue.

By the way, if you have access to Size and can make it a case class (or case-class-like) then you can do the same mostly at compile time

import shapeless.Annotations

Annotations[Size, Sample].apply() // None :: Some(Size(50)) :: HNil
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • Thank you for the answer. Can you suggest me readings on reflection? I find this quite complicated – yuntres Jun 15 '20 at 08:48
  • @yeonhoo There is tutorial https://docs.scala-lang.org/overviews/reflection/overview.html Runtime-reflection API is intentionally similar to compile-time reflection (macros) API so you can read also https://docs.scala-lang.org/overviews/macros/usecases.html Also there is Eugene Burmako's thesis https://infoscience.epfl.ch/record/226166/files/EPFL_TH7159.pdf – Dmytro Mitin Jun 15 '20 at 11:19