I've been using scala presentation compiler API, or to be more exact it's locateTree
method to get AST of some piece of source code, and then get its raw representation via showRaw(ast)
call, but the result seems to be different compared to what I expected. For instance
val tree = q"final def x = 1"
println(showRaw(tree))
Outputs DefDef(Modifiers(FINAL), TermName("x"), List(), List(), TypeTree(), Literal(Constant(1)))
, while a call to presentation compiler on the same source produces DefDef(Modifiers(32, , List()), x, List(), List(), TypeTree(), Literal(Constant(1)))
(notice that x is not wrapped in TermName
and difference in Modifiers
parameter list). Why does this happen and how can I enforce similar behaviour on presentation compiler?
Edit: scala version is 2.11.8
The trees are typed differently, so you have to use the correct 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))))
There is no type safety at res1
, so you don't realize the tree is from a different universe.
The trees are slightly different in modifiers because of position annotations:
$ 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
as opposed to:
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
It turns out that annotations
shows only explicit ones:
scala> mods.annotations
res13: List[reflect.runtime.universe.Tree] = List()
Worth mentioning that the doc says that showRaw
is for inspection rather than construction.