Компилятор презентаций Scala метод locateTree

Я использовал API-интерфейс компилятора презентаций scala, или, точнее, метод locateTree, чтобы получить AST некоторого фрагмента исходного кода, а затем получить его необработанное представление с помощью вызова showRaw(ast), но результат, похоже, отличается от того, что я ожидал . Например

val tree = q"final def x = 1"
println(showRaw(tree))

Выводит DefDef(Modifiers(FINAL), TermName("x"), List(), List(), TypeTree(), Literal(Constant(1))), в то время как вызов компилятора представления в том же источнике дает DefDef(Modifiers(32, , List()), x, List(), List(), TypeTree(), Literal(Constant(1))) (обратите внимание, что x не заключен в TermName и разница в списке параметров Modifiers). Почему это происходит и как я могу обеспечить подобное поведение компилятора презентации?

Изменить: версия scala – 2.11.8.


person sugakandrey    schedule 19.03.2016    source источник


Ответы (1)


Деревья набираются по-разному, поэтому вы должны использовать правильный show:

$ scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60).
Type in expressions for evaluation. Or try :help.

scala> import scala.tools.nsc._
import scala.tools.nsc._

scala> val ss = new Settings(println)
ss: scala.tools.nsc.Settings =
Settings {
  -d = .
}

scala> val g = new interactive.Global(ss, new reporters.ConsoleReporter(ss), "testing")
g: scala.tools.nsc.interactive.Global = scala.tools.nsc.interactive.Global@4c6007fb

scala> val tt = g.newUnitParser("final def x = 1").parseStats
tt: List[g.syntaxAnalyzer.global.Tree] = List(final def x = 1)

scala> reflect.runtime.universe.show(tt.head)
res0: String = final def x = 1

scala> reflect.runtime.universe.showRaw(tt.head)
res1: String = DefDef(Modifiers(32, , List()), x, List(), List(), TypeTree(), Literal(Constant(1)))

scala> g.showRaw(tt)
res2: String = List(DefDef(Modifiers(FINAL), TermName("x"), List(), List(), TypeTree(), Literal(Constant(1))))

В res1 нет безопасности типов, поэтому вы не понимаете, что это дерево из другой вселенной.

Деревья немного отличаются модификаторами из-за аннотаций позиции:

$ scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60).
Type in expressions for evaluation. Or try :help.

scala> import scala.tools.nsc._
import scala.tools.nsc._

scala> val ss = new Settings(println)
ss: scala.tools.nsc.Settings =
Settings {
  -d = .
}

scala> new interactive.Global(ss, new reporters.ConsoleReporter(ss), "testing")
res0: scala.tools.nsc.interactive.Global = scala.tools.nsc.interactive.Global@4c6007fb

scala> val cc = res0
cc: scala.tools.nsc.interactive.Global = scala.tools.nsc.interactive.Global@4c6007fb

scala> val tt = cc.newUnitParser("final def x = 1").parseStats
tt: List[cc.syntaxAnalyzer.global.Tree] = List(final def x = 1)

scala> val cc.DefDef(mods, nam, ps, vs, tpt, rhs) = tt.head
mods: cc.Modifiers = Modifiers(final, , Map(32 -> RangePosition(<console>, 0, 0, 4), 72 -> RangePosition(<console>, 6, 6, 8)))
nam: cc.TermName = x
ps: List[cc.TypeDef] = List()
vs: List[List[cc.ValDef]] = List()
tpt: cc.Tree = <type ?>
rhs: cc.Tree = 1

в отличие от:

scala> import reflect.runtime._, universe._
import reflect.runtime._
import universe._

scala> val DefDef(mods, nam, ps, vs, tpt, rhs) = q"final def x = 1"
mods: reflect.runtime.universe.Modifiers = Modifiers(final, , Map())
nam: reflect.runtime.universe.TermName = x
ps: List[reflect.runtime.universe.TypeDef] = List()
vs: List[List[reflect.runtime.universe.ValDef]] = List()
tpt: reflect.runtime.universe.Tree = <type ?>
rhs: reflect.runtime.universe.Tree = 1

Получается, что annotations показывает только явные:

scala> mods.annotations
res13: List[reflect.runtime.universe.Tree] = List()

Стоит отметить, что документ говорит, что showRaw предназначен для осмотра, а не строительства.

person som-snytt    schedule 20.03.2016
comment
Спасибо за разъяснения! - person sugakandrey; 20.03.2016