2016-09-01 5 views
1

私はマクロを持っており、そのマクロの一部は、あるメソッドへのすべての呼び出しを何か他のものに置き換えるものです。これを達成するために、私はTransformerを使用し、transformメソッドを入力したすべてのTreeをクォンコネートと照合しようとします。私はそれを以下のように書くと、うまくいくようです。パターンマッチングの頑健性Quasiquoteを持つツリー

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の呼び出しはもはや置き換えられなくなった。
私はthe scala docsの提案を見てシンボルを引用符で囲まないようにしましたが、それを動作させることができませんでした。

私の質問です:このコード(q"mypackage.myobject.mymethod[..$_]($value)")は常にmymethodへのすべての呼び出しを置き換え、他のメソッド呼び出しを置き換えることはありませんか?そうでない場合は、どうすればより堅牢にすることができますか?

答えて

2

scala.reflectマクロは非衛生的であるため、理論的にはq"mypackage.myobject.mymethod[..$_]($value)"を他の人と照合することができます。

私はその方法をq"..$mods def $name[..$tparams](...$paramss): $tpeopt = $expr"と一致させることをお勧めします(定義ではなく、宣言であると仮定します)。 nameに小切手を追加することができます。

別の解決策は、アノテーションを付けてメソッドをマークし、マクロフェーズでメソッドを削除することです。

+0

「Tree」でメソッド呼び出しを見つけたら、呼び出されたメソッドに特定の注釈があることを確認するにはどうすればよいですか? –

+1

'mods'はそれを含みます。 http://docs.scala-lang.org/overviews/quasiquotes/definition-detailsが役立つかもしれません。 – dveim

+1

これは私にとってはうまくいく選択肢です: 'methodCallFromTree.symbol.asMethod.annotations'。 –

関連する問題