aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
authorGuillaume Martres <smarter@ubuntu.com>2015-12-02 16:26:12 +0100
committerGuillaume Martres <smarter@ubuntu.com>2015-12-03 14:58:12 +0100
commitccf7f8ae4e09c1e5cbbc52d64ff0358203d29d5c (patch)
tree079ef70f2596fd65798164ce527fd8c204d34791 /src/dotty
parent47da63278147634c75ecd3d0b5f3709a8de2a2db (diff)
downloaddotty-ccf7f8ae4e09c1e5cbbc52d64ff0358203d29d5c.tar.gz
dotty-ccf7f8ae4e09c1e5cbbc52d64ff0358203d29d5c.tar.bz2
dotty-ccf7f8ae4e09c1e5cbbc52d64ff0358203d29d5c.zip
Add initial CompilerCallback implementation for IntelliJ
This adds some simple callbacks to Dotty that should be enough to get basic integration from IntelliJ.
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/backend/jvm/GenBCode.scala11
-rw-r--r--src/dotty/tools/dotc/CompilerCallback.scala42
-rw-r--r--src/dotty/tools/dotc/Driver.scala9
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala15
4 files changed, 76 insertions, 1 deletions
diff --git a/src/dotty/tools/backend/jvm/GenBCode.scala b/src/dotty/tools/backend/jvm/GenBCode.scala
index feaae036b..e8d196ce7 100644
--- a/src/dotty/tools/backend/jvm/GenBCode.scala
+++ b/src/dotty/tools/backend/jvm/GenBCode.scala
@@ -23,6 +23,7 @@ import Symbols._
import Denotations._
import Phases._
import java.lang.AssertionError
+import java.io.{ File => JFile }
import scala.tools.asm
import scala.tools.asm.tree._
import dotty.tools.dotc.util.{Positions, DotClass}
@@ -47,6 +48,8 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
var tree: Tree = _
+ val sourceJFile: JFile = ctx.compilationUnit.source.file.file
+
final class PlainClassBuilder(cunit: CompilationUnit) extends SyncAndTryBuilder(cunit)
@@ -300,6 +303,9 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
bytecodeWriter.close()
// Statistics.stopTimer(BackendStats.bcodeTimer, bcodeStart)
+ if (ctx.compilerCallback != null)
+ ctx.compilerCallback.onSourceCompiled(sourceJFile)
+
/* TODO Bytecode can be verified (now that all classfiles have been written to disk)
*
* (1) asm.util.CheckAdapter.verify()
@@ -363,6 +369,11 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
if (outFolder == null) null
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)
}
catch {
case e: FileConflictException =>
diff --git a/src/dotty/tools/dotc/CompilerCallback.scala b/src/dotty/tools/dotc/CompilerCallback.scala
new file mode 100644
index 000000000..98e8e2713
--- /dev/null
+++ b/src/dotty/tools/dotc/CompilerCallback.scala
@@ -0,0 +1,42 @@
+package dotty.tools.dotc
+
+import java.io.File
+
+/** This trait contains methods that can be overriden to execute code during the
+ * compilation process.
+ *
+ * NOTE: This trait is experimental and may be subject to arbitrary changes.
+ *
+ * Example usage:
+ * {{{
+ * val args: Array[String] = ...
+ * val callback = new CompilerCallback {
+ * override def onClassGenerated(source: File, generatedClass: File, className: String) =
+ * println(s"onClassGenerated($source, $generatedClass, $className)")
+ * override def onSourceCompiled(source: File) =
+ * println(s"onSourceCompiled($source)")
+ * }
+ * dotty.tools.dotc.process(args, callback)
+ * // Or, if you have a custom root context `rootCtx`:
+ * dotty.tools.dotc.process(args, rootCtx.setCompilerCallback(callback))
+ * }}}
+ */
+trait CompilerCallback {
+ /** Called when a class has been generated.
+ *
+ * @param source The source file corresponding to this class.
+ * Example: ./src/library/scala/collection/Seq.scala
+ * @param generatedClass The generated classfile for this class.
+ * Example: ./scala/collection/Seq$.class
+ * @param className The name of this class.
+ * Example: scala.collection.Seq$
+ */
+ def onClassGenerated(source: File, generatedClass: File, className: String): Unit = {}
+
+ /** Called when every class for this file has been generated.
+ *
+ * @param source The source file.
+ * Example: ./src/library/scala/collection/Seq.scala
+ */
+ def onSourceCompiled(source: File): Unit = {}
+}
diff --git a/src/dotty/tools/dotc/Driver.scala b/src/dotty/tools/dotc/Driver.scala
index 22170a478..1627b6e48 100644
--- a/src/dotty/tools/dotc/Driver.scala
+++ b/src/dotty/tools/dotc/Driver.scala
@@ -34,7 +34,10 @@ abstract class Driver extends DotClass {
def setup(args: Array[String], rootCtx: Context): (List[String], Context) = {
val summary = CompilerCommand.distill(args)(rootCtx)
- implicit val ctx: Context = initCtx.fresh.setSettings(summary.sstate)
+ // FIXME: We should reuse rootCtx instead of creating newCtx, but this
+ // makes some tests fail with "denotation module _root_ invalid in run 2."
+ val newCtx = initCtx.setCompilerCallback(rootCtx.compilerCallback)
+ implicit val ctx: Context = newCtx.fresh.setSettings(summary.sstate)
val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)
(fileNames, ctx)
}
@@ -44,6 +47,10 @@ abstract class Driver extends DotClass {
doCompile(newCompiler(), fileNames)(ctx)
}
+ def process(args: Array[String], callback: CompilerCallback): Reporter = {
+ process(args, initCtx.setCompilerCallback(callback))
+ }
+
// We overload `process` instead of using a default argument so that we
// can easily call this method using reflection from `RawCompiler` in sbt.
def process(args: Array[String]): Reporter = {
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index 522240b0f..1a471537e 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -72,11 +72,23 @@ object Contexts {
def next = { val c = current; current = current.outer; c }
}
+ /** Set the compiler callback, shared by all contexts with the same `base` */
+ def setCompilerCallback(callback: CompilerCallback): this.type = {
+ base.compilerCallback = callback; this
+ }
+
/** The outer context */
private[this] var _outer: Context = _
protected def outer_=(outer: Context) = _outer = outer
def outer: Context = _outer
+ // protected def compilerCallback_=(callback: CompilerCallback) =
+ // _compilerCallback = callback
+ // def compilerCallback: CompilerCallback = _compilerCallback
+ // def setCompilerCallback(callback: CompilerCallback): this.type = {
+ // this.compilerCallback = callback; this
+ // }
+
/** The current context */
private[this] var _period: Period = _
protected def period_=(period: Period) = {
@@ -525,6 +537,9 @@ object Contexts {
/** The essential mutable state of a context base, collected into a common class */
class ContextState {
+ /** The compiler callback implementation, or null if unset */
+ var compilerCallback: CompilerCallback = _
+
// Symbols state
/** A counter for unique ids */