Skip to content

Commit da76644

Browse files
committed
Fix fancy uses of analysis
Port of sbt/sbt@dc04892 needed because sbt 1.4 uses batch mode for scripted tests.
1 parent 440f51c commit da76644

File tree

4 files changed

+92
-29
lines changed

4 files changed

+92
-29
lines changed
Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,46 @@
1+
import xsbti.VirtualFileRef
2+
import sbt.internal.inc.Analysis
3+
import xsbti.compile.{PreviousResult, CompileAnalysis, MiniSetup}
4+
import xsbti.compile.analysis.{ Compilation => XCompilation }
5+
6+
previousCompile in Compile := {
7+
val previous = (previousCompile in Compile).value
8+
if (!CompileState.isNew) {
9+
val res = PreviousResult.of(none[CompileAnalysis].asJava, none[MiniSetup].asJava)
10+
CompileState.isNew = true
11+
res
12+
} else previous
13+
}
14+
115
/* Performs checks related to compilations:
216
* a) checks in which compilation given set of files was recompiled
317
* b) checks overall number of compilations performed
418
*/
5-
TaskKey[Unit]("check-compilations") := {
6-
val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis]
19+
TaskKey[Unit]("checkCompilations") := {
20+
val analysis = (compile in Compile).value match { case a: Analysis => a }
21+
val srcDir = (scalaSource in Compile).value
22+
def findFile(className: String): VirtualFileRef = {
23+
analysis.relations.definesClass(className).head
24+
}
725
val allCompilations = analysis.compilations.allCompilations
8-
val recompiledClasses: Seq[Set[String]] = allCompilations map { c =>
9-
val recompiledClasses = analysis.apis.internal.collect {
10-
case (clazz, api) if api.compilationTimestamp() == c.getStartTime() => clazz
26+
val recompiledFiles: Seq[Set[VirtualFileRef]] = allCompilations map { c: XCompilation =>
27+
val recompiledFiles = analysis.apis.internal.collect {
28+
case (cn, api) if api.compilationTimestamp == c.getStartTime => findFile(cn)
1129
}
12-
recompiledClasses.toSet
30+
recompiledFiles.toSet
1331
}
14-
def recompiledFilesInIteration(iteration: Int, classNames: Set[String]): Unit = {
15-
assert(recompiledClasses(iteration) == classNames, "%s != %s".format(recompiledClasses(iteration), classNames))
32+
def recompiledFilesInIteration(iteration: Int, fileNames: Set[String]) = {
33+
assert(recompiledFiles(iteration).map(_.name) == fileNames,
34+
s"""${recompiledFiles(iteration).map(_.name)} != $fileNames
35+
|
36+
|allCompilations = $allCompilations
37+
|""".stripMargin)
1638
}
17-
assert(allCompilations.size == 2)
39+
assert(allCompilations.size == 2, s"All compilations is ${allCompilations.size}")
1840
// B.scala is just compiled at the beginning
19-
recompiledFilesInIteration(0, Set("B"))
41+
recompiledFilesInIteration(0, Set("B.scala"))
2042
// A.scala is changed and recompiled
21-
recompiledFilesInIteration(1, Set("A"))
43+
recompiledFilesInIteration(1, Set("A.scala"))
2244
}
2345

2446
logLevel := Level.Debug
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// This is necessary because tests are run in batch mode
2+
object CompileState {
3+
@volatile var isNew: Boolean = false
4+
}
Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,69 @@
1+
import sbt.internal.inc.Analysis
2+
import xsbti.VirtualFileRef
3+
import xsbti.api.AnalyzedClass
4+
import xsbti.compile.{PreviousResult, CompileAnalysis, MiniSetup}
5+
import xsbti.compile.analysis.{ Compilation => XCompilation }
6+
17
logLevel := Level.Debug
28

9+
// Reset compile status because scripted tests are run in batch mode
10+
previousCompile in Compile := {
11+
val previous = (previousCompile in Compile).value
12+
if (!CompileState.isNew) {
13+
val res = PreviousResult.of(none[CompileAnalysis].asJava, none[MiniSetup].asJava)
14+
CompileState.isNew = true
15+
res
16+
} else previous
17+
}
18+
319
// disable sbt's heuristic which recompiles everything in case
420
// some fraction (e.g. 50%) of files is scheduled to be recompiled
521
// in this test we want precise information about recompiled files
622
// which that heuristic would distort
723
incOptions := incOptions.value.withRecompileAllFraction(1.0)
824

25+
Global / allowMachinePath := false
26+
927
/* Performs checks related to compilations:
1028
* a) checks in which compilation given set of files was recompiled
1129
* b) checks overall number of compilations performed
1230
*/
13-
TaskKey[Unit]("check-compilations") := {
14-
val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis]
31+
TaskKey[Unit]("checkCompilations") := {
32+
val log = streams.value.log
33+
val c = fileConverter.value
34+
val vs = (Compile / sources).value.toVector map { x =>
35+
c.toVirtualFile(x.toPath)
36+
}
37+
// log.info(vs.mkString(","))
38+
39+
val analysis = (compile in Compile).value match { case a: Analysis => a }
1540
val srcDir = (scalaSource in Compile).value
16-
val allCompilations = analysis.compilations.allCompilations
17-
val recompiledClasses: Seq[Set[String]] = allCompilations map { c =>
18-
val recompiledClasses = analysis.apis.internal.collect {
19-
case (clazz, api) if api.compilationTimestamp() == c.getStartTime() => clazz
41+
def findFile(className: String): VirtualFileRef = {
42+
analysis.relations.definesClass(className).head
43+
}
44+
val allCompilations: Seq[XCompilation] = analysis.compilations.allCompilations
45+
log.info(s"allCompilations: $allCompilations")
46+
val recompiledFiles: Seq[Set[VirtualFileRef]] = allCompilations map { c: XCompilation =>
47+
val recompiledFiles = analysis.apis.internal.collect {
48+
case (cn, api) if api.compilationTimestamp == c.getStartTime => findFile(cn)
2049
}
21-
recompiledClasses.toSet
50+
recompiledFiles.toSet
2251
}
23-
def recompiledClassesInIteration(iteration: Int, classNames: Set[String]): Unit = {
24-
assert(recompiledClasses(iteration) == classNames, "%s != %s".format(recompiledClasses(iteration), classNames))
52+
def recompiledFilesInIteration(iteration: Int, fileNames: Set[String]) = {
53+
assert(recompiledFiles(iteration).map(_.name) == fileNames,
54+
s"""${recompiledFiles(iteration).map(_.name)} != $fileNames
55+
|
56+
|allCompilations = $allCompilations
57+
|""".stripMargin)
2558
}
26-
// test.Y is compiled only at the beginning as changes to test.A do not affect it
27-
recompiledClassesInIteration(0, Set("test.X", "test.Y"))
28-
// test.A is changed and recompiled
29-
recompiledClassesInIteration(1, Set("test.A"))
30-
// change in test.A causes recompilation of test.B, test.C, test.D which depend on transitively
31-
// and by inheritance on test.A
32-
// test.X is also recompiled because it depends by member reference on test.B
33-
// Note that test.Y is not recompiled because it depends just on X through member reference dependency
34-
recompiledClassesInIteration(2, Set("test.B", "test.C", "test.D"))
59+
// Y.scala is compiled only at the beginning as changes to A.scala do not affect it
60+
recompiledFilesInIteration(0, Set("X.scala", "Y.scala"))
61+
// A.scala is changed and recompiled
62+
recompiledFilesInIteration(1, Set("A.scala"))
63+
// change in A.scala causes recompilation of B.scala, C.scala, D.scala which depend on transitively
64+
// and by inheritance on A.scala
65+
// X.scala is also recompiled because it depends by member reference on B.scala
66+
// Note that Y.scala is not recompiled because it depends just on X through member reference dependency
67+
recompiledFilesInIteration(2, Set("B.scala", "C.scala", "D.scala"))
3568
assert(allCompilations.size == 3)
3669
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// This is necessary because tests are run in batch mode
2+
object CompileState {
3+
@volatile var isNew: Boolean = false
4+
}

0 commit comments

Comments
 (0)