简体   繁体   中英

Scala presentation compiler locateTree method

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM