diff options
author | Guillaume Martres <smarter@ubuntu.com> | 2016-02-24 23:53:35 +0100 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2016-02-28 20:08:59 +0100 |
commit | 7e7ee820df7647680d9aaf1ca991fe9718159097 (patch) | |
tree | 26095cec3a83fc12984e745e459dcb3d0996d045 /test | |
parent | 94b41d5c491878543288af1bedb4daf57226ca07 (diff) | |
download | dotty-7e7ee820df7647680d9aaf1ca991fe9718159097.tar.gz dotty-7e7ee820df7647680d9aaf1ca991fe9718159097.tar.bz2 dotty-7e7ee820df7647680d9aaf1ca991fe9718159097.zip |
Add a `dotty-interfaces` package
We introduce a new entry point for the compiler in
`dotty.tools.dotc.Driver`:
```
def process(args: Array[String], simple: interfaces.SimpleReporter,
callback: interfaces.CompilerCallback): interfaces.ReporterResult
```
Except for `args` which is just an array, the argument types and return
type of this method are Java interfaces defined in a new package called
`dotty-interfaces` which has a stable ABI. This means that you can
programmatically run a compiler with a custom reporter and callbacks
without having to recompile it against every version of dotty: you only
need to have `dotty-interfaces` present at compile-time and call the
`process` method using Java reflection.
See `test/test/InterfaceEntryPointTest.scala` for a concrete example.
This design is based on discussions with the IntelliJ IDEA Scala plugin
team. Thanks to Nikolay Tropin for the discussions and his PR
proposal (see #1011).
Diffstat (limited to 'test')
-rw-r--r-- | test/test/InterfaceEntryPointTest.scala | 61 | ||||
-rw-r--r-- | test/test/OtherEntryPointsTest.scala | 66 |
2 files changed, 127 insertions, 0 deletions
diff --git a/test/test/InterfaceEntryPointTest.scala b/test/test/InterfaceEntryPointTest.scala new file mode 100644 index 000000000..b193b5f64 --- /dev/null +++ b/test/test/InterfaceEntryPointTest.scala @@ -0,0 +1,61 @@ +package test + +import org.junit.Test +import org.junit.Assert._ +import dotty.tools.dotc.interfaces._ +import scala.collection.mutable.ListBuffer + +/** Test that demonstrates how to use dotty-interfaces + * + * This test requires: + * - dotty-interfaces to be present at compile-time + * - dotty-interfaces and dotty to be present at run-time + * + * Since the ABI of dotty-interfaces is stable, this means that users can write + * code that works with multiple versions of dotty without recompilation. + * + * @see [[OtherEntryPointsTest]] + */ +class InterfaceEntryPointTest { + @Test def runCompilerFromInterface = { + val sources = List("./tests/pos/HelloWorld.scala") + val args = sources ++ List("-d", "./out/") + + val mainClass = Class.forName("dotty.tools.dotc.Main") + val process = mainClass.getMethod("process", + classOf[Array[String]], classOf[SimpleReporter], classOf[CompilerCallback]) + + val reporter = new CustomSimpleReporter + val callback = new CustomCompilerCallback + + // Run the compiler by calling dotty.tools.dotc.Main.process + process.invoke(null, args.toArray, reporter, callback) + + assertEquals("Number of errors", 0, reporter.errorCount) + assertEquals("Number of warnings", 0, reporter.warningCount) + assertEquals("Compiled sources", sources, callback.paths) + } + + private class CustomSimpleReporter extends SimpleReporter { + var errorCount = 0 + var warningCount = 0 + + def report(diag: Diagnostic): Unit = { + if (diag.level == Diagnostic.ERROR) + errorCount += 1 + if (diag.level == Diagnostic.WARNING) + warningCount += 1 + } + } + + private class CustomCompilerCallback extends CompilerCallback { + private val pathsBuffer = new ListBuffer[String] + def paths = pathsBuffer.toList + + override def onSourceCompiled(source: SourceFile): Unit = { + if (source.jfile.isPresent) + pathsBuffer += source.jfile.get.getPath + } + } +} + diff --git a/test/test/OtherEntryPointsTest.scala b/test/test/OtherEntryPointsTest.scala new file mode 100644 index 000000000..0186b357b --- /dev/null +++ b/test/test/OtherEntryPointsTest.scala @@ -0,0 +1,66 @@ +package test + +import org.junit.Test +import org.junit.Assert._ +import dotty.tools.dotc.Main +import dotty.tools.dotc.interfaces.{CompilerCallback, SourceFile} +import dotty.tools.dotc.reporting._ +import dotty.tools.dotc.core.Contexts._ +import java.io.File +import scala.collection.mutable.ListBuffer + +/** Test the compiler entry points that depend on dotty + * + * This file also serve as an example for using [[dotty.tools.dotc.Driver#process]]. + * + * @see [[InterfaceEntryPointTest]] + */ +class OtherEntryPointsTest { + @Test def runCompiler = { + val sources = List("./tests/pos/HelloWorld.scala") + val args = sources ++ List("-d", "./out/") + + val reporter = new CustomReporter + val callback = new CustomCompilerCallback + + Main.process(args.toArray, reporter, callback) + + assertEquals("Number of errors", false, reporter.hasErrors) + assertEquals("Number of warnings", false, reporter.hasWarnings) + assertEquals("Compiled sources", sources, callback.paths) + } + + @Test def runCompilerWithContext = { + val sources = List("./tests/pos/HelloWorld.scala") + val args = sources ++ List("-d", "./out/") + + val reporter = new CustomReporter + val callback = new CustomCompilerCallback + val context = (new ContextBase).initialCtx.fresh + .setReporter(reporter) + .setCompilerCallback(callback) + + Main.process(args.toArray, context) + + assertEquals("Number of errors", false, reporter.hasErrors) + assertEquals("Number of warnings", false, reporter.hasWarnings) + assertEquals("Compiled sources", sources, callback.paths) + } + + private class CustomReporter extends Reporter + with UniqueMessagePositions + with HideNonSensicalMessages { + def doReport(d: Diagnostic)(implicit ctx: Context): Unit = { + } + } + + private class CustomCompilerCallback extends CompilerCallback { + private val pathsBuffer = new ListBuffer[String] + def paths = pathsBuffer.toList + + override def onSourceCompiled(source: SourceFile): Unit = { + if (source.jfile.isPresent) + pathsBuffer += source.jfile.get.getPath + } + } +} |