Scala Макросы: проверка определенной аннотации

Благодаря ответам на мой предыдущий вопрос я смог создать макрос функции таким образом, чтобы он возвращал 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

Аннотация будет указана только на 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, но вы можете указать ее, добавив аргумент Universe Повторяю это в нескольких макросах.