Note that there are some explanatory texts on larger screens.

plurals
  1. POCreating a method definition tree from a method symbol and a body
    primarykey
    data
    text
    <p>Is there a convenient way to turn a <a href="http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library/index.html#scala.reflect.api.Symbols$MethodSymbolApi" rel="nofollow noreferrer"><code>MethodSymbol</code></a> into the left-hand side of a method definition tree (i.e., a <a href="http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library/index.html#scala.reflect.api.Trees$DefDefApi" rel="nofollow noreferrer"><code>DefDef</code></a>) in Scala 2.10?</p> <p>For example, suppose I want to create a macro that will take an instance of a trait and wrap all of that trait's methods with some debugging functionality. I can write the following:</p> <pre><code>import scala.language.experimental.macros import scala.reflect.macros.Context object WrapperExample { def wrap[A](a: A): A = macro wrap_impl[A] def wrap_impl[A: c.WeakTypeTag](c: Context)(a: c.Expr[A]) = { import c.universe._ val wrapped = weakTypeOf[A] val f = Select(reify(Predef).tree, "println") val methods = wrapped.declarations.collect { case m: MethodSymbol if !m.isConstructor =&gt; DefDef( Modifiers(Flag.OVERRIDE), m.name, Nil, Nil, TypeTree(), Block( Apply(f, c.literal("Calling: " + m.name.decoded).tree :: Nil), Select(a.tree, m.name) ) ) }.toList //... } </code></pre> <p>I've elided the boring business of sticking these methods in a new anonymous class that implements the trait and then instantiating that class—you can find a complete working example <a href="https://gist.github.com/4234441" rel="nofollow noreferrer">here</a> if you're interested.</p> <p>Now I can write this, for example:</p> <pre><code>scala&gt; trait X { def foo = 1; def bar = 'a } defined trait X scala&gt; val x = new X {} x: X = $anon$1@15dd533 scala&gt; val w: X = WrapperExample.wrap[X](x) w: X = $1$$1@27c3a4a3 scala&gt; w.foo Calling: foo res0: Int = 1 scala&gt; w.bar Calling: bar res1: Symbol = 'a </code></pre> <p>So it works, but only in very simple cases—it won't if the trait has methods with parameter lists, with access modifiers, annotations, etc.</p> <p>What I really want is a function that will take a method symbol and a tree for the new body and return a <code>DefDef</code>. I've started writing one by hand, but it involves a lot of fiddly stuff like this:</p> <pre><code>List(if (method.isImplicit) Some(Flag.IMPLICIT) else None, ...) </code></pre> <p>Which is annoying, verbose, and error-prone. Am I missing some nicer way to do this in the new Reflection API?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload