如何获得通过隐式转换可用的成员的“符号”?

时间:2019-02-01 10:01:20

标签: scala scala-macros

我正在编写一个宏,该宏会生成如下代码:

q"_root_.ru.lmars.macropack.TagsAndTags2.$tagName(..$tagParams)"

但是我只想在定义$tagName并有一些“标记”(例如注释或某些特殊返回类型)的情况下生成此代码。如何为此获得Symbol的{​​{1}}?

如果在$tagName对象中定义$tagName会很容易:

TagsAndTags2

您可以编写如下内容以获取object TagsAndTags2 { def dialog(caption: String): String = ??? } 中的Symbol

dialog

但是如果val tagParentAccess = q"_root_.ru.lmars.macropack.TagsAndTags2" val tagParent = c.typecheck(tagParentAccess, silent = true) val tagSymbol = tagParent.tpe.member(tagName) 通过隐式转换可用,该怎么做?

$tagName

1 个答案:

答案 0 :(得分:1)

这是一个快速且肮脏的示例(我在Scala 2.11中已经尝试过):

temp / Foo.scala:

package temp

import scala.language.experimental.macros

object Foo {
  def printSymbol(name: String): Unit = macro FooMacro.printSymbol
}

object FooTarget

private class FooMacro(val c: scala.reflect.macros.blackbox.Context) {

  import c.universe._

  def printSymbol(name: Tree): Tree = {
    name match {
      case Literal(Constant(lv)) =>
        val a = q"_root_.temp.FooTarget.${TermName(lv.toString)}"
        val ca = c.typecheck(a)
        println("checked apply symbol", ca.symbol)
    }

    q"()"
  }

}

temp / Bar.scala:

package temp

object Implicits {

  implicit class BarObjContainer(f: FooTarget.type) {

    object bar

  }

}

object UseMacro {

  import Implicits._

  val v = Foo.printSymbol("bar")

}

ca.symbol是您想要的吗?

===更新===

这是带有param功能的快速且肮脏的演示:

temp / Foo.scala:

package temp

import scala.language.experimental.macros

object Foo {
  def printSymbol(name: String): Unit = macro FooMacro.printSymbol
}

object FooTarget

private class FooMacro(val c: scala.reflect.macros.blackbox.Context) {

  import c.universe._

  def printSymbol(name: Tree): Tree = {
    name match {
      case Literal(Constant(lv)) =>
        val nameStr = lv.toString
        val f = q"_root_.temp.FooTarget.${TermName(nameStr)}(_)"
        c.typecheck(f) match {
          case Function(_, Apply(s@Select(_, TermName(`nameStr`)), _)) =>
            println(s.symbol)
        }
    }

    q"()"
  }

}

temp / Bar.scala:

package temp

object Implicits {

  implicit class BarObjContainer(f: FooTarget.type) {

    def bar(baz: String): Unit = ()

  }

}

object UseMacro {

  import Implicits._

  val v = Foo.printSymbol("bar")

}

s是“ bar”的方法符号。