首页 > 解决方案 > 使用 Shapeless 的类与类型注释

问题描述

根据 scala文档,有四种注释:

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

通过使用shapeless.Annotationand shapeless.Annotations,很容易从案例类中获取类和变量注解(1&2)。如何获取其字段的类型注解(3)?

例子:

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

标签: scalashapelessscala-macros

解决方案


你可以写一个宏

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]

推荐阅读