Jasper-M Jasper-M - 1 year ago 73
Scala Question

Robustness of pattern matching Trees with quasiquotes

I have a macro and part of that macro consists of replacing every call to a certain method with something else. To accomplish this I use a

and try to match every
that enters the
method against a quasiquote. When I write it like below, it seems to work.

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)
case _ => super.transform(tree)
val transformed = transformer.transform(expr)


But I thought you should always use fully qualified names in macros or you could get into trouble. So I wrote it like
, but then it no longer matched and the calls to
no longer got replaced.

I also looked at the suggestion in the scala docs to unquote symbols, but I couldn't get that to work either.

So my question is: will this code (with
) always replace all the calls to
and never replace any other method calls? And if not, how can I make it more robust?

Answer Source

scala.reflect macros are non hygienic, so, theoretically, q"mypackage.myobject.mymethod[..$_]($value)" could be matched by someone else.

I'd suggest match that method with q"..$mods def $name[..$tparams](...$paramss): $tpeopt = $expr" (assuming that is definition, not declaration). You can add checks on name.

Another solution is to mark method with annotation, and remove it in macro phase.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download