Skip to content

Commit ccf7f8a

Browse files
committed
Add initial CompilerCallback implementation for IntelliJ
This adds some simple callbacks to Dotty that should be enough to get basic integration from IntelliJ.
1 parent 47da632 commit ccf7f8a

File tree

4 files changed

+76
-1
lines changed

4 files changed

+76
-1
lines changed

src/dotty/tools/backend/jvm/GenBCode.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import Symbols._
2323
import Denotations._
2424
import Phases._
2525
import java.lang.AssertionError
26+
import java.io.{ File => JFile }
2627
import scala.tools.asm
2728
import scala.tools.asm.tree._
2829
import dotty.tools.dotc.util.{Positions, DotClass}
@@ -47,6 +48,8 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
4748

4849
var tree: Tree = _
4950

51+
val sourceJFile: JFile = ctx.compilationUnit.source.file.file
52+
5053
final class PlainClassBuilder(cunit: CompilationUnit) extends SyncAndTryBuilder(cunit)
5154

5255

@@ -300,6 +303,9 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
300303
bytecodeWriter.close()
301304
// Statistics.stopTimer(BackendStats.bcodeTimer, bcodeStart)
302305

306+
if (ctx.compilerCallback != null)
307+
ctx.compilerCallback.onSourceCompiled(sourceJFile)
308+
303309
/* TODO Bytecode can be verified (now that all classfiles have been written to disk)
304310
*
305311
* (1) asm.util.CheckAdapter.verify()
@@ -363,6 +369,11 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
363369
if (outFolder == null) null
364370
else getFileForClassfile(outFolder, jclassName, ".class")
365371
bytecodeWriter.writeClass(jclassName, jclassName, jclassBytes, outFile)
372+
373+
val outJFile = outFile.file
374+
val className = jclassName.replace('/', '.')
375+
if (ctx.compilerCallback != null)
376+
ctx.compilerCallback.onClassGenerated(sourceJFile, outJFile, className)
366377
}
367378
catch {
368379
case e: FileConflictException =>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package dotty.tools.dotc
2+
3+
import java.io.File
4+
5+
/** This trait contains methods that can be overriden to execute code during the
6+
* compilation process.
7+
*
8+
* NOTE: This trait is experimental and may be subject to arbitrary changes.
9+
*
10+
* Example usage:
11+
* {{{
12+
* val args: Array[String] = ...
13+
* val callback = new CompilerCallback {
14+
* override def onClassGenerated(source: File, generatedClass: File, className: String) =
15+
* println(s"onClassGenerated($source, $generatedClass, $className)")
16+
* override def onSourceCompiled(source: File) =
17+
* println(s"onSourceCompiled($source)")
18+
* }
19+
* dotty.tools.dotc.process(args, callback)
20+
* // Or, if you have a custom root context `rootCtx`:
21+
* dotty.tools.dotc.process(args, rootCtx.setCompilerCallback(callback))
22+
* }}}
23+
*/
24+
trait CompilerCallback {
25+
/** Called when a class has been generated.
26+
*
27+
* @param source The source file corresponding to this class.
28+
* Example: ./src/library/scala/collection/Seq.scala
29+
* @param generatedClass The generated classfile for this class.
30+
* Example: ./scala/collection/Seq$.class
31+
* @param className The name of this class.
32+
* Example: scala.collection.Seq$
33+
*/
34+
def onClassGenerated(source: File, generatedClass: File, className: String): Unit = {}
35+
36+
/** Called when every class for this file has been generated.
37+
*
38+
* @param source The source file.
39+
* Example: ./src/library/scala/collection/Seq.scala
40+
*/
41+
def onSourceCompiled(source: File): Unit = {}
42+
}

src/dotty/tools/dotc/Driver.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ abstract class Driver extends DotClass {
3434

3535
def setup(args: Array[String], rootCtx: Context): (List[String], Context) = {
3636
val summary = CompilerCommand.distill(args)(rootCtx)
37-
implicit val ctx: Context = initCtx.fresh.setSettings(summary.sstate)
37+
// FIXME: We should reuse rootCtx instead of creating newCtx, but this
38+
// makes some tests fail with "denotation module _root_ invalid in run 2."
39+
val newCtx = initCtx.setCompilerCallback(rootCtx.compilerCallback)
40+
implicit val ctx: Context = newCtx.fresh.setSettings(summary.sstate)
3841
val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)
3942
(fileNames, ctx)
4043
}
@@ -44,6 +47,10 @@ abstract class Driver extends DotClass {
4447
doCompile(newCompiler(), fileNames)(ctx)
4548
}
4649

50+
def process(args: Array[String], callback: CompilerCallback): Reporter = {
51+
process(args, initCtx.setCompilerCallback(callback))
52+
}
53+
4754
// We overload `process` instead of using a default argument so that we
4855
// can easily call this method using reflection from `RawCompiler` in sbt.
4956
def process(args: Array[String]): Reporter = {

src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,23 @@ object Contexts {
7272
def next = { val c = current; current = current.outer; c }
7373
}
7474

75+
/** Set the compiler callback, shared by all contexts with the same `base` */
76+
def setCompilerCallback(callback: CompilerCallback): this.type = {
77+
base.compilerCallback = callback; this
78+
}
79+
7580
/** The outer context */
7681
private[this] var _outer: Context = _
7782
protected def outer_=(outer: Context) = _outer = outer
7883
def outer: Context = _outer
7984

85+
// protected def compilerCallback_=(callback: CompilerCallback) =
86+
// _compilerCallback = callback
87+
// def compilerCallback: CompilerCallback = _compilerCallback
88+
// def setCompilerCallback(callback: CompilerCallback): this.type = {
89+
// this.compilerCallback = callback; this
90+
// }
91+
8092
/** The current context */
8193
private[this] var _period: Period = _
8294
protected def period_=(period: Period) = {
@@ -525,6 +537,9 @@ object Contexts {
525537
/** The essential mutable state of a context base, collected into a common class */
526538
class ContextState {
527539

540+
/** The compiler callback implementation, or null if unset */
541+
var compilerCallback: CompilerCallback = _
542+
528543
// Symbols state
529544

530545
/** A counter for unique ids */

0 commit comments

Comments
 (0)