我想测试我编写的转换一些scala源代码的工具,我想检查转换后的代码是否从sbt测试编译(使用scalatest(。
我想用我的源代码以编程方式在字符串上调用 scala 编译器(所有这些都在一个独立的文件中(。
自最初的问题以来,我取得了一些进展。此代码在我的 IDE (IntelliJ( 中有效,但不适用于sbt test
会话
import java.io.File
import scala.reflect.internal.util.BatchSourceFile
import scala.tools.nsc.{GenericRunnerSettings, Global}
object Compilation {
val settings = new GenericRunnerSettings(System.out.println _)
// val sbtClasspath = System.getProperty("sbt-classpath")
// val s = File.pathSeparator
// val classPath = s".${s}$sbtClasspath"
// settings.classpath.append(classPath)
settings.usejavacp.value = true
val global = new Global(settings)
def compiles(code: String): Boolean = {
val r = new global.Run
r.compileSources(List(new BatchSourceFile("<partest>", code)))
val errors = global.reporter.hasErrors
if (errors) r.reporting.summarizeErrors()
!errors
}
}
这是我的build.sbt
name := "CodinGame-Scala-Kit"
version := "0.1.0"
scalaVersion := "2.12.2"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test"
libraryDependencies += "org.scala-lang" % "scala-compiler" % "2.12.2" % "test"
enablePlugins(JmhPlugin)
//val sbtcp = taskKey[Unit]("sbt-classpath")
//
//sbtcp := {
// val files: Seq[File] = (fullClasspath in Compile).value.files
// val sbtClasspath: String = files.map(x => x.getAbsolutePath).mkString(java.io.File.pathSeparator)
// println("Set SBT classpath to 'sbt-classpath' environment variable")
// println(sbtClasspath)
// System.setProperty("sbt-classpath", sbtClasspath)
//}
//
//compile <<= (compile in Compile).dependsOn(sbtcp)
初始错误是
scala.reflect.internal.MissingRequirementError: object scala.annotation.Annotation in compiler mirror not found.
[info] at scala.reflect.internal.MissingRequirementError$.signal(MissingRequirementError.scala:17)
[info] at scala.reflect.internal.MissingRequirementError$.notFound(MissingRequirementError.scala:18)
[info] at scala.reflect.internal.Mirrors$RootsBase.$anonfun$getModuleOrClass$4(Mirrors.scala:54)
[info] at scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:54)
[info] at scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:45)
[info] at scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:66)
[info] at scala.reflect.internal.Mirrors$RootsBase.getClassByName(Mirrors.scala:101)
[info] at scala.reflect.internal.Mirrors$RootsBase.getRequiredClass(Mirrors.scala:104)
[info] at scala.reflect.internal.Mirrors$RootsBase.requiredClass(Mirrors.scala:107)
[info] at scala.reflect.internal.Definitions$DefinitionsClass.AnnotationClass$lzycompute(Definitions.scala:1141)
我在此答案之后添加了build.sbt
和Compilation
对象中注释的行。它不会更改 IDE 中的任何内容。
我现在在 sbt 测试上遇到此错误(编译正确打印类路径(:
scala.reflect.internal.FatalError: class StringContext does not have a member f
[info] at scala.reflect.internal.Definitions$DefinitionsClass.fatalMissingSymbol(Definitions.scala:1236)
[info] at scala.reflect.internal.Definitions$DefinitionsClass.$anonfun$getMember$1(Definitions.scala:1259)
[info] at scala.reflect.internal.Definitions$DefinitionsClass.getMember(Definitions.scala:1254)
[info] at scala.reflect.internal.Definitions$DefinitionsClass.getMemberMethod(Definitions.scala:1288)
[info] at scala.reflect.internal.Definitions$DefinitionsClass$RunDefinitions.StringContext_f$lzycompute(Definitions.scala:1477)
[info] at scala.reflect.internal.Definitions$DefinitionsClass$RunDefinitions.StringContext_f(Definitions.scala:1477)
[info] at scala.tools.reflect.FastTrack.$anonfun$fastTrackCache$1(FastTrack.scala:53)
[info] at scala.reflect.internal.SymbolTable$perRunCaches$$anon$1.apply(SymbolTable.scala:395)
[info] at scala.tools.reflect.FastTrack.contains(FastTrack.scala:20)
[info] at scala.tools.nsc.typechecker.Namers$Namer.methodSig(Namers.scala:1388)
第二种方法看起来与对我有用的方法相似,您显然在某处缺少依赖项。空的设置将不起作用。更改设置引导类路径
或简单地使用settings.usejavacp.value = true
我终于找到了一种编译任何字符串的可靠方法:
import scala.reflect.runtime.currentMirror
import scala.tools.reflect.ToolBox
object Compiler {
def compile[A](string: String): A = {
val toolbox = currentMirror.mkToolBox()
val tree = toolbox.parse(string)
toolbox.eval(tree).asInstanceOf[A]
}
}
跟
libraryDependencies += "org.scala-lang" % "scala-compiler" % "2.12.10"