如何获取可通过隐式转换获得的成员的“Symbol”?
How to get a `Symbol` of a member that is available via an implicit conversion?
我正在编写一个生成如下代码的宏:
q"_root_.ru.lmars.macropack.TagsAndTags2.$tagName(..$tagParams)"
但我只想在定义了 $tagName
并且有一些 "marker"(如注释或某些特殊的 return 类型)时生成此代码。如何为此获得 $tagName
的 Symbol
?
如果在 TagsAndTags2
对象中定义 $tagName
就很容易了:
object TagsAndTags2
{
def dialog(caption: String): String = ???
}
你可以写这样的东西来得到 Symbol
of dialog
:
val tagParentAccess = q"_root_.ru.lmars.macropack.TagsAndTags2"
val tagParent = c.typecheck(tagParentAccess, silent = true)
val tagSymbol = tagParent.tpe.member(tagName)
但是,如果 $tagName
可通过隐式转换获得,该怎么做呢?
implicit final class UserTags(x: TagsAndTags2.type)
{
def dialog(caption: String): String = ???
}
这里是一个简单粗暴的例子(我已经在 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
是你想要的吗?
===更新===
这是带参数的函数的快速演示:
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" 的方法符号。
我正在编写一个生成如下代码的宏:
q"_root_.ru.lmars.macropack.TagsAndTags2.$tagName(..$tagParams)"
但我只想在定义了 $tagName
并且有一些 "marker"(如注释或某些特殊的 return 类型)时生成此代码。如何为此获得 $tagName
的 Symbol
?
如果在 TagsAndTags2
对象中定义 $tagName
就很容易了:
object TagsAndTags2
{
def dialog(caption: String): String = ???
}
你可以写这样的东西来得到 Symbol
of dialog
:
val tagParentAccess = q"_root_.ru.lmars.macropack.TagsAndTags2"
val tagParent = c.typecheck(tagParentAccess, silent = true)
val tagSymbol = tagParent.tpe.member(tagName)
但是,如果 $tagName
可通过隐式转换获得,该怎么做呢?
implicit final class UserTags(x: TagsAndTags2.type)
{
def dialog(caption: String): String = ???
}
这里是一个简单粗暴的例子(我已经在 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
是你想要的吗?
===更新===
这是带参数的函数的快速演示:
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" 的方法符号。