Class 与 Shapeless 类型注释对比

Class vs Type annotations with Shapeless

根据 scala documentation,有四种注解:

  1. Class注解:@ClassAnnotation case class Foo(...)
  2. Variable/Value注解:@ValAnnotation val field: String
  3. 类型注释:field: String @TypeAnnotation
  4. 表达式注释

通过使用shapeless.Annotationshapeless.Annotations,很容易从一个案例class中得到class和变量注释(1&2)。如何获取其字段的类型注解(三)?

示例:

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

你可以写一个宏

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]