Class vs Type annotations with Shapeless

时间:2019-04-16 22:54:11

标签: scala shapeless

As per the scala documentation, there are four kinds of annotations:

  1. Class annotations: @ClassAnnotation case class Foo(...)
  2. Variable/Value annotations: @ValAnnotation val field: String
  3. Type annotations: field: String @TypeAnnotation
  4. Expression annotations

By using shapeless.Annotation and shapeless.Annotations, it is easy to get class and variable annotations (1&2) from a case class. How to get type annotations of its fields (3)?

Example:

@ClassAnnotation
case class Foo(
  @ValAnnotation field: String @TypeAnnotation
)

1 个答案:

答案 0 :(得分:2)

您可以编写宏

import scala.language.experimental.macros
import scala.reflect.macros.blackbox

def getAnnotation[A]: Any = macro impl[A]

def impl[A: c.WeakTypeTag](c: blackbox.Context): c.Tree = {
  import c.universe._

  println(weakTypeOf[A].typeSymbol.annotations) // List(ClassAnnotation)

  println(weakTypeOf[A]
    .member(termNames.CONSTRUCTOR)
    .asMethod
    .paramLists
    .map(_.map(_.annotations))
  ) // List(List(List(ValAnnotation)))

  println(weakTypeOf[A]
    .member(termNames.CONSTRUCTOR)
    .asMethod
    .paramLists
    .map(_.map(_.typeSignature match {
      case AnnotatedType(annots, _) => annots
      case _ => List()
    })) // List(List(List(TypeAnnotation)))
  )

  q""
}

import scala.annotation.StaticAnnotation

case class ClassAnnotation() extends StaticAnnotation
case class ValAnnotation() extends StaticAnnotation
case class TypeAnnotation() extends StaticAnnotation

@ClassAnnotation
case class Foo(
                @ValAnnotation field: String @TypeAnnotation
              )

getAnnotation[Foo]