在scala宏中获取完全限定的方法名

在scala宏中获取完全限定的方法名,scala,scala-macros,scala-reflect,Scala,Scala Macros,Scala Reflect,我使用Scala宏和matchApply,我希望得到被调用函数的完全限定名 示例: println("") -> scala.Predef.println scala.Predef.println("") -> scala.Predef.println class Abc { def met(): Unit = ??? } case class X { def met(): Unit = ??? def abc(): Abc = ??? } val a = new Ab

我使用Scala宏和match
Apply
,我希望得到被调用函数的完全限定名

示例:

println("") -> scala.Predef.println
scala.Predef.println("") -> scala.Predef.println
class Abc {
  def met(): Unit = ???
}
case class X { 
  def met(): Unit = ???
  def abc(): Abc = ???
}
val a = new Abc()
val x = new Abc()
a.met() -> Abc.met
new Abc().met() -> Abc.met
X() -> X.apply
X().met() -> X.met
x.met() -> X.met
x.abc.met() -> Abc.met
左边是我的代码,右边是我想要的。可能吗?如何操作?

以下是宏:

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

object ExampleMacro {

  final val useFullyQualifiedName = false

  def methodName(param: Any): String = macro debugParameters_Impl

  def debugParameters_Impl(c: blackbox.Context)(param: c.Expr[Any]): c.Expr[String] = {
    import c.universe._

    param.tree match {
      case Apply(Select(t, TermName(methodName)), _) =>
        val baseClass = t.tpe.resultType.baseClasses.head // there may be a better way than this line
        val className = if (useFullyQualifiedName) baseClass.fullName else baseClass.name
        c.Expr[String](Literal(Constant(className + "." + methodName)))
      case _ => sys.error("Not a method call: " + show(param.tree))
    }
  }
}
object Main {

  def main(args: Array[String]): Unit = {

    class Abc {
      def met(): Unit = ???
    }
    case class X() {
      def met(): Unit = ???

      def abc(): Abc = ???
    }
    val a = new Abc()
    val x = X()

    import sk.ygor.stackoverflow.q53326545.macros.ExampleMacro.methodName

    println(methodName(Main.main(Array("foo", "bar"))))
    println(methodName(a.met()))
    println(methodName(new Abc().met()))
    println(methodName(X()))
    println(methodName(X().met()))
    println(methodName(x.met()))
    println(methodName(x.abc().met()))
    println(methodName("a".getClass))
  }

}
宏的用法:

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

object ExampleMacro {

  final val useFullyQualifiedName = false

  def methodName(param: Any): String = macro debugParameters_Impl

  def debugParameters_Impl(c: blackbox.Context)(param: c.Expr[Any]): c.Expr[String] = {
    import c.universe._

    param.tree match {
      case Apply(Select(t, TermName(methodName)), _) =>
        val baseClass = t.tpe.resultType.baseClasses.head // there may be a better way than this line
        val className = if (useFullyQualifiedName) baseClass.fullName else baseClass.name
        c.Expr[String](Literal(Constant(className + "." + methodName)))
      case _ => sys.error("Not a method call: " + show(param.tree))
    }
  }
}
object Main {

  def main(args: Array[String]): Unit = {

    class Abc {
      def met(): Unit = ???
    }
    case class X() {
      def met(): Unit = ???

      def abc(): Abc = ???
    }
    val a = new Abc()
    val x = X()

    import sk.ygor.stackoverflow.q53326545.macros.ExampleMacro.methodName

    println(methodName(Main.main(Array("foo", "bar"))))
    println(methodName(a.met()))
    println(methodName(new Abc().met()))
    println(methodName(X()))
    println(methodName(X().met()))
    println(methodName(x.met()))
    println(methodName(x.abc().met()))
    println(methodName("a".getClass))
  }

}
此示例包含以下内容:

  • 这是一个多模块SBT项目,因为宏必须位于与使用宏的类不同的编译单元中
  • 宏模块显式依赖于
    libraryDependencies+=“org.scala lang”%”scala reflect“%scalaVersion.value,

我犯了一个错误,在
scala中硬编码scala版本反映了
依赖关系。现在编辑答案。