Как получить `Symbol` члена, который доступен через неявное преобразование? - PullRequest
0 голосов
/ 01 февраля 2019

Я пишу макрос, который генерирует некоторый код, подобный этому:

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

, но я хочу сгенерировать этот код, только если определено $tagName и есть некоторый «маркер» (например, аннотация или некоторыеспециальный тип возврата).Как получить Symbol из $tagName для этого?

Это просто, если $tagName определен внутри TagsAndTags2 объекта:

object TagsAndTags2
{
    def dialog(caption: String): String = ???
}

, вы можете написать что-то вроде этогоget Symbol из 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 = ???
}

1 Ответ

0 голосов
/ 03 февраля 2019

Вот быстрый и грязный пример (я пробовал это в 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".

...