Scala Macros:检查某个注释

时间:2013-06-21 13:09:05

标签: scala annotations scala-macros

感谢my previous question的答案,我能够创建一个函数宏,使其返回一个Map,将每个字段名称映射到一个类的值,例如。

...

trait Model

case class User (name: String, age: Int, posts: List[String]) extends Model {
  val numPosts: Int = posts.length

  ...

  def foo = "bar"

  ...
}

所以这个命令

val myUser = User("Foo", 25, List("Lorem", "Ipsum"))

myUser.asMap

返回

Map("name" -> "Foo", "age" -> 25, "posts" -> List("Lorem", "Ipsum"), "numPosts" -> 2)

这是生成Tuple Map的地方(见Travis Brown的answer):

...

val pairs = weakTypeOf[T].declarations.collect {
  case m: MethodSymbol if m.isAccessor =>
    val name = c.literal(m.name.decoded)
    val value = c.Expr(Select(model, m.name))
    reify(name.splice -> value.splice).tree
}

...

现在我想忽略具有@transient注释的字段。如何检查方法是否具有@transient注释?

我正在考虑将上面的代码段修改为

val pairs = weakTypeOf[T].declarations.collect {
   case m: MethodSymbol if m.isAccessor && !m.annotations.exists(???) =>
      val name = c.literal(m.name.decoded)
      val value = c.Expr(Select(model, m.name))
      reify(name.splice -> value.splice).tree
}

但我无法在exists部分找到我需要写的内容。我如何将@transient作为Annotation,以便将其传递给那里?

提前致谢!

1 个答案:

答案 0 :(得分:11)

注释将在val本身,而不在访问者身上。访问val的最简单方法是通过accessed上的MethodSymbol方法:

def isTransient(m: MethodSymbol) = m.accessed.annotations.exists(
  _.tpe =:= typeOf[scala.transient]
)

现在,您可以在collect

中撰写以下内容
case m: MethodSymbol if m.isAccessor && !isTransient(m) =>

请注意,我在此处提供的isTransient版本必须在您的宏中定义,因为它需要从c.universe导入,但您可以通过添加{如果您在多个宏中执行此类操作,请参加{1}}论证。