Scala 宏:检查某个注释 [英] Scala Macros: Checking for a certain annotation

查看:36
本文介绍了Scala 宏:检查某个注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

感谢对我之前的问题的回答,我能够创建一个函数宏,使其返回一个 Map 将每个字段名称映射到它的类值,例如

Thanks to the answers to my previous question, I was able to create a function macro such that it returns a Map that maps each field name to its value of a class, e.g.

...

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)

这是生成 MapTuple 的地方(参见 Travis Brown 的 回答):

This is where Tuples for the Map are generated (see Travis Brown's 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 注释?

Now I want to ignore fields that have @transient annotation. How would I check if a method has a @transient annotation?

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

I'm thinking of modifying the snippet above as

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 获取以便我可以将其传递到那里?

but I can't find what I need to write in exists part. How would I get @transient as an Annotation so I could pass it there?

提前致谢!

推荐答案

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

The annotation will be on the val itself, not on the accessor. The easiest way to access the val is through the accessed method on MethodSymbol:

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

现在您可以在 collect 中写入以下内容:

Now you can just write the following in your collect:

case m: MethodSymbol if m.isAccessor && !isTransient(m) =>

请注意,我在此处给出的 isTransient 版本必须在您的宏中定义,因为它需要从 c.universe 导入,但您可以考虑如果您在多个宏中执行此类操作,则可以通过添加 Universe 参数来解决此问题.

Note that the version of isTransient I've given here has to be defined in your macro, since it needs the imports from c.universe, but you could factor it out by adding a Universe argument if you're doing this kind of thing in several macros.

这篇关于Scala 宏:检查某个注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆