带准引号的模式匹配树的鲁棒性



我有一个宏,该宏的一部分包括用其他东西替换对某个方法的每次调用。为了实现这一点,我使用一个Transformer,并尝试将进入transform方法的每个Tree与一个拟引用相匹配。当我像下面这样写它时,它似乎有效。

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文档中取消引号符号的建议,但我也不能让它工作。

所以我的问题是:这段代码(与q"mypackage.myobject.mymethod[..$_]($value)")总是取代所有的mymethod调用,永远不会取代任何其他方法调用?如果不是,我怎样才能使它更健壮?

scala。reflect宏是非卫生的,因此,从理论上讲,q"mypackage.myobject.mymethod[..$_]($value)"可以由其他人匹配。

我建议将该方法与q"..$mods def $name[..$tparams](...$paramss): $tpeopt = $expr"匹配(假设这是定义,而不是声明)。您可以在name上添加检查。

另一种解决方案是用注释标记方法,并在宏阶段将其删除。

相关内容

  • 没有找到相关文章

最新更新