In Scala 3 there is no c.macroApplication. Only Position.ofMacroExpansion instead of a tree. But we can analyze Symbol.spliceOwner.maybeOwner. I presume that scalacOptions += "-Yretain-trees" is switched on.
import scala.annotation.experimental
import scala.quoted.*
object Macro {
inline def makeCallWithName[T](inline methodName: String): T =
${makeCallWithNameImpl[T]('methodName)}
@experimental
def makeCallWithNameImpl[T](methodName: Expr[String])(using Quotes, Type[T]): Expr[T] = {
import quotes.reflect.*
println(Position.ofMacroExpansion.sourceCode)//Some(twoargs(1, "one"))
val methodNameStr = methodName.valueOrAbort
val strs = methodNameStr.split('.')
val moduleName = strs.init.mkString(".")
val moduleSymbol = Symbol.requiredModule(moduleName)
val shortMethodName = strs.last
val ident = Ident(TermRef(moduleSymbol.termRef, shortMethodName))
val (ownerName, ownerRhs) = Symbol.spliceOwner.maybeOwner.tree match {
case ValDef(name, tpt, Some(rhs)) => (name, rhs)
case DefDef(name, paramss, tpt, Some(rhs)) => (name, rhs)
case t => report.errorAndAbort(s"can't find RHS of ${t.show}")
}
val treeAccumulator = new TreeAccumulator[Option[Tree]] {
override def foldTree(acc: Option[Tree], tree: Tree)(owner: Symbol): Option[Tree] = tree match {
case Apply(fun, args) if fun.symbol.fullName == "App$.twoargs" =>
Some(Apply(ident, Literal(StringConstant(ownerName)) :: args))
case _ => foldOverTree(acc, tree)(owner)
}
}
treeAccumulator.foldTree(None, ownerRhs)(ownerRhs.symbol)
.getOrElse(report.errorAndAbort(s"can't find twoargs in RHS: ${ownerRhs.show}"))
.asExprOf[T]
}
}
Usage:
package mypackage
case class TwoArgs(name : String, i : Int, s : String)
import mypackage.TwoArgs
object App {
inline def twoargs(i: Int, s: String) =
Macro.makeCallWithName[TwoArgs]("mypackage.TwoArgs.apply")
def x() = twoargs(1, "one") // TwoArgs("x", 1, "one")
def aMethod() = {
val y = twoargs(2, "two") // TwoArgs("y", 2, "two")
}
val z = Some(twoargs(3, "three")) // Some(TwoArgs("z", 3, "three"))
}
dsinfo also handles the name twoargs at call site (as template $macro) but I didn't implement this. I guess the name (if necessary) can be obtained from Position.ofMacroExpansion.sourceCode.