访问案例类注释

时间:2017-03-09 15:15:51

标签: scala scala-reflect

case class FieldName(field: String) extends scala.annotation.StaticAnnotation
@FieldName("foo") trait Foo
import scala.reflect.runtime.universe._

symbolOf[Foo].annotations.head
// ann: Annotation = FieldName("type")

如何以FieldName对象的形式访问注释?该文件提到tree.children.tail,但没有类型可供选择。

1 个答案:

答案 0 :(得分:3)

如果你真的想要FieldName的实例我能想到的最好的是使用ToolBox

scala> case class FieldName(field: String) extends scala.annotation.StaticAnnotation
defined class FieldName

scala> @FieldName("foo") trait Foo
defined trait Foo

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> val annotation = symbolOf[Foo].annotations.head
annotation: reflect.runtime.universe.Annotation = FieldName("foo")

scala> import scala.tools.reflect.ToolBox
import scala.tools.reflect.ToolBox

scala> val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@1b26a499

scala> tb.eval(tb.untypecheck(annotation.tree)).asInstanceOf[FieldName]
res10: FieldName = FieldName(foo)

使用.tree.children.tail,您可以访问传递给FieldName的参数,而无需创建实际实例。

scala> annotation.tree.children.tail.map{ case Literal(Constant(field)) => field } 
res11: List[Any] = List(foo)

如果您只想要所有FieldName注释并提取其值,则可以执行以下操作:

scala> val fields = symbolOf[Foo].annotations.withFilter( 
     |   a => a.tree.tpe <:< typeOf[FieldName] 
     | ).flatMap( 
     |   a => a.tree.children.tail.map{ case Literal(Constant(field)) => field } 
     | )
fields: List[Any] = List(foo)