Scala 宏:检查某个注释 [英] Scala Macros: Checking for a certain annotation
问题描述
感谢对我之前的问题的回答,我能够创建一个函数宏,使其返回一个 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)
这是生成 Map
的 Tuple
的地方(参见 Travis Brown 的 回答):
This is where Tuple
s 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屋!