0

The macros I’ve been writing typically need to process all the defs from other objects/modules that live in libraries etc so the trees are not available. Inside the macro, I often need to transform a MethodSymbol obtained from the other object, into a new API call in my target trait that replicates the function signature including default parameters.

However, I’ve not figured out a way to obtain default parameter values for the parameters in the MethodSymbol so when I build up the result, I cannot “replicate” some of the method signature as I would like.

Is there a way to obtain the default parameters, say for parameters obtained from the “members” property of the symbol’s “type”, for the parameters in the MethodSymbol?

Pᴇʜ
  • 56,719
  • 10
  • 49
  • 73
user1763729
  • 167
  • 1
  • 11

1 Answers1

1

You can use the following technique

import scala.language.experimental.macros
import scala.reflect.macros.blackbox

def foo[A]: Unit = macro impl[A]

def impl[A: c.WeakTypeTag](c: blackbox.Context): c.Tree = {
  import c.universe._

  // just for testing, in actual use case methodSymbol is obtained from somewhere 
  val methodSymbol = weakTypeOf[A].decl(TermName("smth")).asMethod

  val traverser = new Traverser {
    override def traverse(tree: Tree): Unit = {
      tree match {
        case t @ q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" if t.symbol == methodSymbol =>
          paramss.flatten.foreach {
            case q"$mods1 val $tname1: $tpt1 = $expr1" =>
              println(s"method $tname: default value of $tname1 is $expr1")
            case _ =>
          }
        case _ =>
      }
      super.traverse(tree)
    }
  }

  c.enclosingRun.units.foreach(unit =>
    traverser.traverse(unit.body)
  )

  q"()"
}

object App {

  class MyClass {
    def smth(x: Int = 1): Unit = ()
  }

  foo[MyClass] //Warning:scalac: method smth: default value of x is 1
}
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • 1
    Let me give that a try. I would not have guessed that at all, but it looks like you traverse over everything up the chain to find the one that matches your symbol. Thanks, may take me awhile to confirm. – user1763729 Apr 08 '20 at 22:26