Skip to content
This repository was archived by the owner on Sep 1, 2020. It is now read-only.

Commit b17a291

Browse files
committed
GenBCode: fix incrementatal compilation by mimicing GenASM
The incremental compiler in SBT uses an implementation detail of the compiler backend to enumerate the classes that are actually written to disk. This commit mimics this in GenBCode by populating `Run#icode` with an `IClass` for each `ClassDef` processed. We should revisit this by creating a dedicated API for this purpose and migrating SBT to use that. We should also revisit this code as we implement closure elimination in the GenBCode; this commit assumes that all `ClassDef`s that enter the backend will generate classfile products. The enclosed test is extracted from the incrementatl compiler. I've also manually integration tested this with SBT: https://gist.github.com/retronym/fabf6f92787ea9c1ce67
1 parent 950bb26 commit b17a291

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ abstract class GenBCode extends BCodeSyncAndTry {
167167
)
168168
}
169169

170+
// shim for SBT, see https://github.com/sbt/sbt/issues/2076
171+
// TODO put this closer to classfile writing once we have closure elimination
172+
// TODO create a nicer public API to find out the correspondence between sourcefile and ultimate classfiles
173+
currentUnit.icode += new icodes.IClass(cd.symbol)
174+
170175
// -------------- mirror class, if needed --------------
171176
val mirrorC =
172177
if (isTopLevelModuleClass(claszSymbol)) {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import scala.tools.partest._
2+
import scala.tools.nsc._
3+
4+
object Test extends DirectTest {
5+
6+
def code = """
7+
class C { class D }
8+
object O
9+
""".trim
10+
11+
def show() {
12+
for (b <- List("GenASM", "GenBCode")) {
13+
val global = newCompiler("-usejavacp", s"-Ybackend:$b")
14+
import global._
15+
val r = new Run
16+
r.compileSources(newSourceFile(code) :: Nil)
17+
18+
val results = collection.mutable.Buffer[(Boolean, String)]()
19+
20+
// Nailing down defacto compiler API from SBT's usage
21+
// https://github.com/sbt/sbt/blob/adb41611cf73260938274915d8462d924df200c8/compile/interface/src/main/scala/xsbt/Analyzer.scala#L29-L41
22+
def isTopLevelModule(sym: Symbol) = sym.isTopLevel && sym.isModule
23+
for (unit <- currentRun.units if !unit.isJava) {
24+
val sourceFile = unit.source.file.file
25+
for (iclass <- unit.icode) {
26+
val sym = iclass.symbol
27+
def addGenerated(separatorRequired: Boolean) {
28+
results += (separatorRequired -> sym.fullName)
29+
}
30+
if (sym.isModuleClass && !sym.isImplClass) {
31+
if (isTopLevelModule(sym) && sym.companionClass == NoSymbol)
32+
addGenerated(false)
33+
addGenerated(true)
34+
} else
35+
addGenerated(false)
36+
}
37+
}
38+
val expected = List((false, "C"), (true, "O"), (false, "C$D"))
39+
assert(results.toList == expected, b + ": " + results.toList)
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)