使用scala.tools.nsc.Global解析Scala源代码

时间:2015-02-02 08:56:49

标签: scala

我可以使用Tree

从Scala代码字符串中获取scala.tools.nsc.interactive.Global
val scalaCode = ...
val settings = new Settings
settings.embeddedDefaults(getClass.getClassLoader)
settings.usejavacp.value = true
val reporter = new StoreReporter
val compiler: Global = new Global(settings, reporter)
val source = new BatchSourceFile("<no file>", scalaCode.toCharArray)
val tree = compiler.parseTree(source)

但是,如果我尝试使用scala.tools.nsc.Global,则没有parseTree方法,因为它不会扩展CompilerControl。在查看CompilerControl来源

之后
def parseTree(source: SourceFile): Tree = {
  new UnitParser(new CompilationUnit(source)).parse()
}

我试过了:

val parser = new compiler.syntaxAnalyzer.UnitParser(new compiler.CompilationUnit(source))
val tree = parser.parse()

但这会产生以下错误:

[info]   java.lang.AssertionError: assertion failed: TypeHistory(<no phase>:0,<?>,null)
[info]   at scala.reflect.internal.Symbols$TypeHistory.<init>(Symbols.scala:3353)
[info]   at scala.reflect.internal.Symbols$Symbol.info_$eq(Symbols.scala:1251)
[info]   at scala.reflect.internal.Symbols$TypeSymbol.info_$eq(Symbols.scala:2816)
[info]   at scala.reflect.internal.Symbols$Symbol.setInfo(Symbols.scala:1257)
[info]   at scala.reflect.internal.Mirrors$Roots$RootClass$.<init>(Mirrors.scala:280)
[info]   at scala.reflect.internal.Mirrors$Roots.RootClass$lzycompute(Mirrors.scala:279)
[info]   at scala.reflect.internal.Mirrors$Roots.RootClass(Mirrors.scala:279)
[info]   at scala.reflect.internal.Mirrors$Roots$EmptyPackageClass$.<init>(Mirrors.scala:290)
[info]   at scala.reflect.internal.Mirrors$Roots.EmptyPackageClass$lzycompute(Mirrors.scala:290)
[info]   at scala.reflect.internal.Mirrors$Roots.EmptyPackageClass(Mirrors.scala:290)
[info]   ...

我是否需要调用其他方法来设置scala.tools.nsc.Global

1 个答案:

答案 0 :(得分:2)

是的,你必须制作一个Run

import scala.tools.nsc.Global
import scala.tools.nsc.Settings
import scala.tools.nsc.reporters.ConsoleReporter
import scala.reflect.internal.util.BatchSourceFile
import scala.io.Source

object Main {
  val settings = new Settings
  val global = Global(settings, new ConsoleReporter(settings))
  import global._

  def main(args: Array[String]): Unit = {

    //val file = "/path/to/file"
    val file = args(0)
    val fileContent = Source.fromFile(file).mkString

    val run = new Run

    val parser = new syntaxAnalyzer.SourceFileParser(new BatchSourceFile(file, fileContent))
    val tree = parser.parse()
    println(tree)

    // or
    val res = global.newUnitParser("class C").parse()
    println(res)
  }
}