Вы можете программно вызывать компилятор Scala, а также плагины с кодом, подобным следующему:
import scala.tools.nsc.{Settings, Global}
import scala.tools.nsc.io.VirtualDirectory
import scala.tools.nsc.reporters.ConsoleReporter
import scala.tools.nsc.util.BatchSourceFile
// prepare the code you want to compile
val code = "object Foo extends Application { println(42 / 0) }"
val sources = List(new BatchSourceFile("<test>", code))
val settings = new Settings
// save class files to a virtual directory in memory
settings.outputDirs.setSingleOutput(new VirtualDirectory("(memory)", None))
val compiler = new Global(settings, new ConsoleReporter(settings)) {
override protected def computeInternalPhases () {
super.computeInternalPhases
for (phase <- new DivByZero(this).components)
phasesSet += phase
}
}
new compiler.Run() compileSources(sources)
Обратите внимание, что этот код требует, чтобы scala-compiler.jar
и scala-library.jar
находились в пути к классам при выполнении кода. Если вы выполняете свои тесты из чего-то вроде SBT, к сожалению, это не так.
Чтобы запустить вещи из SBT, вам нужно сделать несколько прыжков с обручем:
val settings = new Settings
val loader = getClass.getClassLoader.asInstanceOf[URLClassLoader]
val entries = loader.getURLs map(_.getPath)
// annoyingly, the Scala library is not in our classpath, so we have to add it manually
val sclpath = entries find(_.endsWith("scala-compiler.jar")) map(
_.replaceAll("scala-compiler.jar", "scala-library.jar"))
settings.classpath.value = ClassPath.join((entries ++ sclpath) : _*)
Если вы работаете из какой-то другой среды сборки, вы можете обнаружить, что scala-library.jar
уже находится на пути к классам, или, если вам действительно повезет, тогда все, что вам нужно, находится на стандартном пути к классам Java, в этом случае можно заменить вышеприведенное на:
val settings = new Settings
settings.usejavacp.value = true
Вы можете распечатать значение пути к классам Java с помощью System.getProperty("java.class.path")
и, конечно, вы можете распечатать entries
из приведенного выше кода, чтобы увидеть путь к классу, используемый загрузчиком классов, загружающим ваш тестовый код.