Get case class annotations with reflection?

2019-07-24 23:49发布

I have a case class like:

case class Foo (@Annotation bar: String)

I'd like to be able to get access to that annotation and any of its information that is stored

I can get the case accessors using scala reflection (using 2.11.8) with

val caseAccessors = 
  universe.typeTag[T].
    tpe.
    decls.
    filter(_.isMethod).
    map(_.asMethod).
    filter(_.isCaseAccessor)

But when I try and access .annotations on them there is nothing. I realize that the annotation is technically on the constructor parameter, but how do I get to it?

1条回答
Lonely孤独者°
2楼-- · 2019-07-25 00:22

Your @Annotation will be on both constructor parameter and companion object apply method, and you can find those by name. I don't think there exist specific methods to filter out constructor / primary constructor / companion object factory method. Both these should work:

universe.typeTag[Foo]
  .tpe
  .declarations
  .find(_.name.toString == "<init>")
  .get
  .asMethod
  .paramss
  .flatten
  .flatMap(_.annotations)

universe.typeTag[Foo.type]
  .tpe
  .declarations
  .find(_.name.toString == "apply")
  .get
  .asMethod
  .paramss
  .flatten
  .flatMap(_.annotations)

(although I'm on Scala 2.11.8 and there's no decls but there's declarations)

If you want to put your annotations on fields or getters, use scala.annotation.meta package:

import scala.annotation.meta
case class Foo (@(Annotation @meta.getter) bar: String)

In this case your code will work (if you change T to Foo in typeTag[T])

See the doc for scala.annotation.meta

查看更多
登录 后发表回答