From 7e7ee820df7647680d9aaf1ca991fe9718159097 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Wed, 24 Feb 2016 23:53:35 +0100 Subject: 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). --- src/dotty/tools/backend/jvm/GenBCode.scala | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src/dotty/tools/backend/jvm/GenBCode.scala') diff --git a/src/dotty/tools/backend/jvm/GenBCode.scala b/src/dotty/tools/backend/jvm/GenBCode.scala index 2d444d3be..8cec93977 100644 --- a/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/src/dotty/tools/backend/jvm/GenBCode.scala @@ -13,6 +13,9 @@ import dotty.tools.dotc import dotty.tools.dotc.backend.jvm.DottyPrimitives import dotty.tools.dotc.transform.Erasure +import dotty.tools.dotc.interfaces +import java.util.Optional + import scala.reflect.ClassTag import dotty.tools.dotc.core._ import Periods._ @@ -51,7 +54,17 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter var tree: Tree = _ - val sourceJFile: JFile = ctx.compilationUnit.source.file.file + val sourceFile = ctx.compilationUnit.source + + /** Convert a `scala.reflect.io.AbstractFile` into a + * `dotty.tools.dotc.interfaces.AbstractFile`. + */ + private[this] def convertAbstractFile(absfile: scala.reflect.io.AbstractFile): interfaces.AbstractFile = + new interfaces.AbstractFile { + override def name = absfile.name + override def path = absfile.path + override def jfile = Optional.ofNullable(absfile.file) + } final class PlainClassBuilder(cunit: CompilationUnit) extends SyncAndTryBuilder(cunit) @@ -307,7 +320,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter // Statistics.stopTimer(BackendStats.bcodeTimer, bcodeStart) if (ctx.compilerCallback != null) - ctx.compilerCallback.onSourceCompiled(sourceJFile) + ctx.compilerCallback.onSourceCompiled(sourceFile) /* TODO Bytecode can be verified (now that all classfiles have been written to disk) * @@ -373,10 +386,9 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter else getFileForClassfile(outFolder, jclassName, ".class") bytecodeWriter.writeClass(jclassName, jclassName, jclassBytes, outFile) - val outJFile = outFile.file val className = jclassName.replace('/', '.') if (ctx.compilerCallback != null) - ctx.compilerCallback.onClassGenerated(sourceJFile, outJFile, className) + ctx.compilerCallback.onClassGenerated(sourceFile, convertAbstractFile(outFile), className) } catch { case e: FileConflictException => -- cgit v1.2.3