Надежность сопоставления образцов деревьев с квазицитатами

У меня есть макрос, и часть этого макроса состоит в замене каждого вызова определенного метода чем-то другим. Для этого я использую Transformer и стараться соответствовать каждому Tree который входит в transform метод против квазицитаты. Когда я пишу это, как показано ниже, это похоже на работу.

package mypackage

object myobject {
  implicit def mymethod[T](t: Option[T]): T = ???
}

object Macros {
  import scala.language.experimental.macros
  import scala.reflect.macros.blackbox.Context

  def myMacro(c: Context)(expr: c.Tree): c.Tree = {
    import c.universe._

    val transformer = new Transformer {
      private def doSomething(value: c.Tree): TermName = {
        ???
      }
      override def transform(tree: c.Tree) = tree match {
        case q"mypackage.myobject.mymethod[..$_]($value)" => 
          val result = doSomething(value)
          q"$result"
        case _ => super.transform(tree)
      }
    }
    val transformed = transformer.transform(expr)

    ???
  }
}

Но я думал, что вы всегда должны использовать полностью определенные имена в макросах, иначе у вас могут возникнуть проблемы. Так что я написал это как q"_root_.mypackage.myobject.mymethod[..$_]($value)", но тогда это больше не соответствует и призывы к mymethod больше не получил замену.
Я также посмотрел на предложение в scala docs о цитировании символов, но я не мог заставить это работать.

Поэтому мой вопрос: будет ли этот код (с q"mypackage.myobject.mymethod[..$_]($value)") всегда заменяйте все звонки на mymethod и никогда не заменять какие-либо другие вызовы методов? И если нет, как я могу сделать его более надежным?

1 ответ

Решение

Макросы scala.reflect не гигиеничны, поэтому теоретически q"mypackage.myobject.mymethod[..$_]($value)" мог быть подобран кем-то еще.

Я бы предложил сопоставить этот метод с q"..$mods def $name[..$tparams](...$paramss): $tpeopt = $expr" (при условии, что это определение, а не объявление). Вы можете добавить проверки на name,

Другое решение - пометить метод с аннотацией и удалить его в макро фазе.

Другие вопросы по тегам