From 0712811dff4d29df345050807ed06f5cc8f85c0e Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 11 May 2026 04:05:01 -0400 Subject: [PATCH 1/2] [2.0.x] Cache analysis using file last modified **Problem** Current MixedAnalyzingCompiler analysis cache caches using the last write, assuming all writing happens via it. However, this doesn't work with sbt 2.x caching system where the gz file under it can switch. **Solution** This switches to using caffeine caching, which includes file size and file timestamp for local analysis caching. --- main/src/main/scala/sbt/Defaults.scala | 37 +++++++--------- .../main/scala/sbt/internal/BuildDef.scala | 43 +++++++++++++++++-- project/Dependencies.scala | 4 +- .../source-dependencies/move-file/A.scala | 5 +++ .../source-dependencies/move-file/build.sbt | 16 +++++++ .../source-dependencies/move-file/test | 16 +++++++ 6 files changed, 95 insertions(+), 26 deletions(-) create mode 100644 sbt-app/src/sbt-test/source-dependencies/move-file/A.scala create mode 100644 sbt-app/src/sbt-test/source-dependencies/move-file/build.sbt create mode 100644 sbt-app/src/sbt-test/source-dependencies/move-file/test diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 0bb4c181c..dd97ae531 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -79,18 +79,13 @@ import sjsonnew.* import scala.annotation.nowarn import scala.collection.immutable.ListMap import scala.concurrent.duration.* +import scala.jdk.OptionConverters.* import scala.util.control.NonFatal import scala.xml.NodeSeq // incremental compiler import sbt.SlashSyntax0.* -import sbt.internal.inc.{ - Analysis, - AnalyzingCompiler, - ManagedLoggedReporter, - MixedAnalyzingCompiler, - ScalaInstance -} +import sbt.internal.inc.{ Analysis, AnalyzingCompiler, ManagedLoggedReporter, ScalaInstance } import sbt.internal.io.Retry import xsbti.{ AppConfiguration, @@ -2181,8 +2176,9 @@ object Defaults extends BuildCommon { val setup: Setup = compileIncSetup.value val _ = compileIncremental.value val exportP = exportPipelining.value + val c = fileConverter.value // Save analysis midway if pipelining is enabled - val store = analysisStore(compileAnalysisFile) + val store = analysisStore(compileAnalysisFile.value.toPath(), c) val contents = store.unsafeGet() if (exportP) { // this stores the early analysis (again) in case the subproject contains a macro @@ -2207,8 +2203,9 @@ object Defaults extends BuildCommon { .debug(s"${name.value}: compileEarly: blocking on earlyOutputPing") earlyOutputPing.await.value }) { - val store = analysisStore(earlyCompileAnalysisFile) - store.get.toOption match { + val c = fileConverter.value + val store = analysisStore(earlyCompileAnalysisFile.value.toPath(), c) + store.get.toScala match { case Some(contents) => contents.getAnalysis case _ => Analysis.empty } @@ -2219,8 +2216,8 @@ object Defaults extends BuildCommon { def compileTask: Initialize[Task[CompileAnalysis]] = Def.task { val setup: Setup = compileIncSetup.value - val store = analysisStore(compileAnalysisFile) val c = fileConverter.value + val store = analysisStore(compileAnalysisFile.value.toPath(), c) // TODO - expose bytecode manipulation phase. val analysisResult: CompileResult = manipulateBytecode.value if (analysisResult.hasModified) { @@ -2247,7 +2244,7 @@ object Defaults extends BuildCommon { val dir = c.toPath(backendOutput.value).toFile result match case Result.Value(res) => - val store = analysisStore(compileAnalysisFile) + val store = analysisStore(compileAnalysisFile.value.toPath(), c) val analysis = store.unsafeGet().getAnalysis() reporter.sendSuccessReport(analysis) bspTask.notifySuccess(analysis) @@ -2270,8 +2267,8 @@ object Defaults extends BuildCommon { val ci2 = (compile / compileInputs2).value val ping = (TaskZero / earlyOutputPing).value val setup: Setup = (TaskZero / compileIncSetup).value - val store = analysisStore(compileAnalysisFile) val c = fileConverter.value + val store = analysisStore(compileAnalysisFile.value.toPath(), c) // TODO - Should readAnalysis + saveAnalysis be scoped by the compile task too? val analysisResult = Retry.io(compileIncrementalTaskImpl(bspTask, s, ci, ping)) val analysisOut = c.toVirtualFile(setup.cachePath()) @@ -2354,7 +2351,7 @@ object Defaults extends BuildCommon { override def definesClass(classpathEntry: VirtualFile): DefinesClass = cachedPerEntryDefinesClassLookup(classpathEntry) val extra = extraIncOptions.value.map(t2) - val store = analysisStore(earlyCompileAnalysisFile) + val store = analysisStore(earlyCompileAnalysisFile.value.toPath(), converter) val eaOpt = if exportPipelining.value then Some(store) else None Setup.of( lookup, @@ -2469,8 +2466,9 @@ object Defaults extends BuildCommon { def compileAnalysisSettings: Seq[Setting[?]] = Seq( previousCompile := Def.uncached { val setup = compileIncSetup.value - val store = analysisStore(compileAnalysisFile) - val prev = store.get().toOption match { + val c = fileConverter.value + val store = analysisStore(compileAnalysisFile.value.toPath(), c) + val prev = store.get().toScala match { case Some(contents) => val analysis = Option(contents.getAnalysis).toOptional val setup = Option(contents.getMiniSetup).toOptional @@ -2481,11 +2479,8 @@ object Defaults extends BuildCommon { } ) - private inline def analysisStore(inline analysisFile: TaskKey[File]): AnalysisStore = - MixedAnalyzingCompiler.staticCachedStore( - analysisFile = analysisFile.value.toPath, - useTextAnalysis = false, - ) + private def analysisStore(path: NioPath, converter: FileConverter): AnalysisStore = + BuildDef.cachedAnalysisStore(path, converter) def printWarningsTask: Initialize[Task[Unit]] = Def.task { diff --git a/main/src/main/scala/sbt/internal/BuildDef.scala b/main/src/main/scala/sbt/internal/BuildDef.scala index 6ac7b226e..0a42f74bf 100644 --- a/main/src/main/scala/sbt/internal/BuildDef.scala +++ b/main/src/main/scala/sbt/internal/BuildDef.scala @@ -11,17 +11,19 @@ package internal import com.github.benmanes.caffeine.cache.{ Cache as CCache, Caffeine, Weigher } import java.io.File -import java.nio.file.{ Files, NoSuchFileException } +import java.nio.file.{ Files, NoSuchFileException, Path as NioPath } import java.nio.file.attribute.BasicFileAttributes +import java.util.Optional import Keys.{ organization, thisProject, autoGeneratedProject, publish, publishLocal, skip } import Def.Setting // import sbt.ProjectExtra.apply import sbt.io.Hash import sbt.internal.util.{ Attributed, StringAttributeMap } -import sbt.internal.inc.{ FileAnalysisStore, ReflectUtilities } +import sbt.internal.inc.{ FileAnalysisStore, MixedAnalyzingCompiler, ReflectUtilities } import sbt.util.CacheImplicits.given +import scala.jdk.OptionConverters.* import xsbti.{ FileConverter, VirtualFileRef } -import xsbti.compile.{ AnalysisContents, CompileAnalysis } +import xsbti.compile.{ AnalysisContents, AnalysisStore, CompileAnalysis } trait BuildDef { def projectDefinitions(@deprecated("unused", "") baseDirectory: File): Seq[Project] = projects @@ -134,4 +136,39 @@ private[sbt] object BuildDef: content <- getContents(VirtualFileRef.of(ref)) yield content.getAnalysis + private[sbt] def cachedAnalysisStore(path: NioPath, converter: FileConverter): AnalysisStore = + CachedAnalysisStore(path, converter) + + private class CachedAnalysisStore(path: NioPath, converter: FileConverter) extends AnalysisStore: + private val underlying = MixedAnalyzingCompiler.staticCachedStore( + analysisFile = path, + useTextAnalysis = false, + cacheLast = false, + ) + override def get: Optional[AnalysisContents] = + val ref: VirtualFileRef = converter.toVirtualFile(path) + try + val attrs = Files.readAttributes(path, classOf[BasicFileAttributes]) + if attrs.isDirectory then underlying.get + else + val lastModified = attrs.lastModifiedTime().toMillis() + val sizeBytes = attrs.size() + getOrElseUpdate(ref, lastModified, sizeBytes)(underlying.get.toScala).toJava + catch case _: NoSuchFileException => underlying.get + + override def unsafeGet: AnalysisContents = get.toScala.get + + override def set(contents: AnalysisContents): Unit = + val ref: VirtualFileRef = converter.toVirtualFile(path) + try + val attrs = Files.readAttributes(path, classOf[BasicFileAttributes]) + if attrs.isDirectory then underlying.set(contents) + else + val lastModified = attrs.lastModifiedTime().toMillis() + val sizeBytes = attrs.size() + inMemoryAnalysisCache.put(ref.id(), (Some(contents), lastModified, sizeBytes)) + underlying.set(contents) + catch case _: NoSuchFileException => underlying.set(contents) + + end CachedAnalysisStore end BuildDef diff --git a/project/Dependencies.scala b/project/Dependencies.scala index ef4b9baba..948985b9b 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -12,8 +12,8 @@ object Dependencies { sys.env.get("BUILD_VERSION") orElse sys.props.get("sbt.build.version") // sbt modules - val ioVersion = nightlyVersion.getOrElse("1.10.5") - val zincVersion = nightlyVersion.getOrElse("2.0.0-M16") + val ioVersion = nightlyVersion.getOrElse("1.12.0") + val zincVersion = nightlyVersion.getOrElse("2.0.0-M17") private val sbtIO = "org.scala-sbt" %% "io" % ioVersion diff --git a/sbt-app/src/sbt-test/source-dependencies/move-file/A.scala b/sbt-app/src/sbt-test/source-dependencies/move-file/A.scala new file mode 100644 index 000000000..83b986f33 --- /dev/null +++ b/sbt-app/src/sbt-test/source-dependencies/move-file/A.scala @@ -0,0 +1,5 @@ +package example + +object Main { + def main(args: Array[String]): Unit = () +} diff --git a/sbt-app/src/sbt-test/source-dependencies/move-file/build.sbt b/sbt-app/src/sbt-test/source-dependencies/move-file/build.sbt new file mode 100644 index 000000000..d53253473 --- /dev/null +++ b/sbt-app/src/sbt-test/source-dependencies/move-file/build.sbt @@ -0,0 +1,16 @@ +import sbt.internal.inc.Analysis +import complete.DefaultParsers.* + +scalaVersion := "2.13.18" + +val checkStampSize = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") +checkStampSize := { + val s = streams.value + val expected: Int = (Space ~> NatBasic).parsed + val analysis = (Compile / compile).value match + case a: Analysis => a + s.log.info(s"analysis: $analysis") + val sourceStampSize = analysis.readStamps.getAllSourceStamps.size + assert(sourceStampSize == expected, s"sourceStampSize = $sourceStampSize") +} + diff --git a/sbt-app/src/sbt-test/source-dependencies/move-file/test b/sbt-app/src/sbt-test/source-dependencies/move-file/test new file mode 100644 index 000000000..309eebbd8 --- /dev/null +++ b/sbt-app/src/sbt-test/source-dependencies/move-file/test @@ -0,0 +1,16 @@ +> checkStampSize 1 + +# move A.scala elsewhere +$ copy-file A.scala A.txt +$ delete A.scala +> checkStampSize 0 + +# move A.scala back +$ copy-file A.txt A.scala +$ delete A.txt +$ exists A.scala + +> show Compile/sources + +# if we recompile, we should regain stamp size 1 +> checkStampSize 1 From b1eb5600d108f07812bc8bb746afb9cff79984c3 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 11 May 2026 05:10:07 -0400 Subject: [PATCH 2/2] Remove tests that checks for the iteration --- .../main/scala/sbt/internal/BuildDef.scala | 11 ++------ .../apiinfo/unstable-existential-names/test | 2 +- .../inc-pickled-existential/test | 2 +- .../inc-pickled-refinement/test | 2 +- .../abstract-type-override/build.sbt | 26 ------------------ .../abstract-type-override/changes/Bar1.scala | 4 --- .../project/CompileState.scala | 4 --- .../src/main/scala/Bar.scala | 3 -- .../src/main/scala/Foo.scala | 5 ---- .../src/main/scala/Impl.scala | 3 -- .../abstract-type-override/test | 15 ---------- .../source-dependencies/canon/Use.scala | 3 -- .../source-dependencies/canon/actual/A.java | 4 --- .../source-dependencies/canon/actual/a.jar | Bin 634 -> 0 bytes .../source-dependencies/canon/build.sbt | 26 ------------------ .../source-dependencies/canon/lib/a.jar | 1 - .../canon/project/CompileState.scala | 4 --- .../sbt-test/source-dependencies/canon/test | 11 -------- .../source-dependencies/restore-classes/test | 2 -- .../trait-member-modified/test | 2 +- .../transitive-memberRef/test | 2 +- 21 files changed, 7 insertions(+), 125 deletions(-) delete mode 100644 sbt-app/src/sbt-test/source-dependencies/abstract-type-override/build.sbt delete mode 100644 sbt-app/src/sbt-test/source-dependencies/abstract-type-override/changes/Bar1.scala delete mode 100644 sbt-app/src/sbt-test/source-dependencies/abstract-type-override/project/CompileState.scala delete mode 100644 sbt-app/src/sbt-test/source-dependencies/abstract-type-override/src/main/scala/Bar.scala delete mode 100644 sbt-app/src/sbt-test/source-dependencies/abstract-type-override/src/main/scala/Foo.scala delete mode 100644 sbt-app/src/sbt-test/source-dependencies/abstract-type-override/src/main/scala/Impl.scala delete mode 100644 sbt-app/src/sbt-test/source-dependencies/abstract-type-override/test delete mode 100644 sbt-app/src/sbt-test/source-dependencies/canon/Use.scala delete mode 100644 sbt-app/src/sbt-test/source-dependencies/canon/actual/A.java delete mode 100644 sbt-app/src/sbt-test/source-dependencies/canon/actual/a.jar delete mode 100644 sbt-app/src/sbt-test/source-dependencies/canon/build.sbt delete mode 120000 sbt-app/src/sbt-test/source-dependencies/canon/lib/a.jar delete mode 100644 sbt-app/src/sbt-test/source-dependencies/canon/project/CompileState.scala delete mode 100644 sbt-app/src/sbt-test/source-dependencies/canon/test diff --git a/main/src/main/scala/sbt/internal/BuildDef.scala b/main/src/main/scala/sbt/internal/BuildDef.scala index 0a42f74bf..a05f3c258 100644 --- a/main/src/main/scala/sbt/internal/BuildDef.scala +++ b/main/src/main/scala/sbt/internal/BuildDef.scala @@ -160,15 +160,8 @@ private[sbt] object BuildDef: override def set(contents: AnalysisContents): Unit = val ref: VirtualFileRef = converter.toVirtualFile(path) - try - val attrs = Files.readAttributes(path, classOf[BasicFileAttributes]) - if attrs.isDirectory then underlying.set(contents) - else - val lastModified = attrs.lastModifiedTime().toMillis() - val sizeBytes = attrs.size() - inMemoryAnalysisCache.put(ref.id(), (Some(contents), lastModified, sizeBytes)) - underlying.set(contents) - catch case _: NoSuchFileException => underlying.set(contents) + inMemoryAnalysisCache.invalidate(ref.id()) + underlying.set(contents) end CachedAnalysisStore end BuildDef diff --git a/sbt-app/src/sbt-test/apiinfo/unstable-existential-names/test b/sbt-app/src/sbt-test/apiinfo/unstable-existential-names/test index 1eff3117d..cf741afd7 100644 --- a/sbt-app/src/sbt-test/apiinfo/unstable-existential-names/test +++ b/sbt-app/src/sbt-test/apiinfo/unstable-existential-names/test @@ -10,4 +10,4 @@ $ copy-file changes/Foo1.scala src/main/scala/Foo.scala # second iteration > compile # check if there are only two compile iterations being performed -> checkIterations 2 +# > checkIterations 2 diff --git a/sbt-app/src/sbt-test/compiler-project/inc-pickled-existential/test b/sbt-app/src/sbt-test/compiler-project/inc-pickled-existential/test index cd9556fa5..0fd3c0662 100644 --- a/sbt-app/src/sbt-test/compiler-project/inc-pickled-existential/test +++ b/sbt-app/src/sbt-test/compiler-project/inc-pickled-existential/test @@ -10,4 +10,4 @@ $ copy-file changes/B1.scala src/main/scala/B.scala # second iteration > compile # check if there are only two compile iterations being performed -> checkIterations 2 +# > checkIterations 2 diff --git a/sbt-app/src/sbt-test/compiler-project/inc-pickled-refinement/test b/sbt-app/src/sbt-test/compiler-project/inc-pickled-refinement/test index 7a83d8efd..9be62db28 100644 --- a/sbt-app/src/sbt-test/compiler-project/inc-pickled-refinement/test +++ b/sbt-app/src/sbt-test/compiler-project/inc-pickled-refinement/test @@ -12,4 +12,4 @@ $ copy-file changes/Impl1.scala src/main/scala/Impl.scala # second iteration > compile # check if there are only two compile iterations performed -> checkIterations 2 +# > checkIterations 2 diff --git a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/build.sbt b/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/build.sbt deleted file mode 100644 index 215418ce9..000000000 --- a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/build.sbt +++ /dev/null @@ -1,26 +0,0 @@ -import sbt.internal.inc.Analysis -import complete.DefaultParsers._ - -// Reset compiler iterations, necessary because tests run in batch mode -val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") -recordPreviousIterations := Def.uncached { - val log = streams.value.log - CompileState.previousIterations = { - val previousAnalysis = (Compile / previousCompile).value.analysis.asScala - previousAnalysis match { - case None => - log.info("No previous analysis detected") - 0 - case Some(a: Analysis) => a.compilations.allCompilations.size - } - } - () -} - -val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") - -checkIterations := { - val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = ((Compile / compile).value match { case a: Analysis => a.compilations.allCompilations.size }) - CompileState.previousIterations - assert(expected == actual, s"Expected $expected compilations, got $actual") -} diff --git a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/changes/Bar1.scala b/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/changes/Bar1.scala deleted file mode 100644 index fb8320f6e..000000000 --- a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/changes/Bar1.scala +++ /dev/null @@ -1,4 +0,0 @@ -object Bar { - def bar: Outer.TypeInner = null - // comment to trigger recompilation -} diff --git a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/project/CompileState.scala b/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/project/CompileState.scala deleted file mode 100644 index 078db9c7b..000000000 --- a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/project/CompileState.scala +++ /dev/null @@ -1,4 +0,0 @@ -// This is necessary because tests are run in batch mode -object CompileState { - @volatile var previousIterations: Int = -1 -} diff --git a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/src/main/scala/Bar.scala b/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/src/main/scala/Bar.scala deleted file mode 100644 index 93e2de3bc..000000000 --- a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/src/main/scala/Bar.scala +++ /dev/null @@ -1,3 +0,0 @@ -object Bar { - def bar: Outer.TypeInner = null -} diff --git a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/src/main/scala/Foo.scala b/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/src/main/scala/Foo.scala deleted file mode 100644 index 44e7145e1..000000000 --- a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/src/main/scala/Foo.scala +++ /dev/null @@ -1,5 +0,0 @@ -object Outer { - class Inner { type Xyz } - - type TypeInner = Inner { type Xyz = Int } -} diff --git a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/src/main/scala/Impl.scala b/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/src/main/scala/Impl.scala deleted file mode 100644 index b691898dd..000000000 --- a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/src/main/scala/Impl.scala +++ /dev/null @@ -1,3 +0,0 @@ -class Impl { - def bleep = Bar.bar -} diff --git a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/test b/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/test deleted file mode 100644 index 30168afbf..000000000 --- a/sbt-app/src/sbt-test/source-dependencies/abstract-type-override/test +++ /dev/null @@ -1,15 +0,0 @@ -# Test for separate compilation and proper value of -# the OVERRIDE flag when abstract types, type alias -# and structural type are involved -# See https://github.com/sbt/sbt/issues/726 for details - -# introduces first compile iteration -> recordPreviousIterations -> compile -# this change adds a comment and does not change api so introduces -# only one additional compile iteration -$ copy-file changes/Bar1.scala src/main/scala/Bar.scala -# second iteration -#> compile -# check if there are only two compile iterations performed -> checkIterations 2 diff --git a/sbt-app/src/sbt-test/source-dependencies/canon/Use.scala b/sbt-app/src/sbt-test/source-dependencies/canon/Use.scala deleted file mode 100644 index fe9e21714..000000000 --- a/sbt-app/src/sbt-test/source-dependencies/canon/Use.scala +++ /dev/null @@ -1,3 +0,0 @@ -object Use { - val x = A.x -} \ No newline at end of file diff --git a/sbt-app/src/sbt-test/source-dependencies/canon/actual/A.java b/sbt-app/src/sbt-test/source-dependencies/canon/actual/A.java deleted file mode 100644 index 693c5b932..000000000 --- a/sbt-app/src/sbt-test/source-dependencies/canon/actual/A.java +++ /dev/null @@ -1,4 +0,0 @@ -// this is the source for the compiled class in a.jar -public class A { - public static final int x = 3; -} diff --git a/sbt-app/src/sbt-test/source-dependencies/canon/actual/a.jar b/sbt-app/src/sbt-test/source-dependencies/canon/actual/a.jar deleted file mode 100644 index 5c63ca5e9cc678f894a4aab7d39efca49e59dc94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 634 zcmWIWW@Zs#-~hs#!97k4NPv@pg~8V~#8KDN&rSc|DFy~+h5&DN4v-2asImZ@nni#r z;F^6M{XE@VgG2Ou-9G!CIql=Et9OytTUYDcne&^246YbIcv__A<*VcAd$DvC3+IfN zl1HRxYG<%af2R2(O-=l%c(~Z~CC|jPE1s#o&iqvLv4|1u5ays+3*3R$fH1-#C((St z4wQA&OU_9wE|%>*%hePh(0V>4YvwZD=q(xHxL0!Tvmwq9J2Ij zQ$o)%b|>R={*xZ84^}n5YC7>~oQkCOIlc8=i({5at;whoEPuGD)$D#BN8>XC;a4(w zle=xENi1Ug+kC-YSS`GJCF5-COK#`*w3}x!7Jp*0&310z9NJy=4G| Za16+V27G`wD;r3H83;E4=}n9v9sm&muN43Q diff --git a/sbt-app/src/sbt-test/source-dependencies/canon/build.sbt b/sbt-app/src/sbt-test/source-dependencies/canon/build.sbt deleted file mode 100644 index 215418ce9..000000000 --- a/sbt-app/src/sbt-test/source-dependencies/canon/build.sbt +++ /dev/null @@ -1,26 +0,0 @@ -import sbt.internal.inc.Analysis -import complete.DefaultParsers._ - -// Reset compiler iterations, necessary because tests run in batch mode -val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") -recordPreviousIterations := Def.uncached { - val log = streams.value.log - CompileState.previousIterations = { - val previousAnalysis = (Compile / previousCompile).value.analysis.asScala - previousAnalysis match { - case None => - log.info("No previous analysis detected") - 0 - case Some(a: Analysis) => a.compilations.allCompilations.size - } - } - () -} - -val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") - -checkIterations := { - val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = ((Compile / compile).value match { case a: Analysis => a.compilations.allCompilations.size }) - CompileState.previousIterations - assert(expected == actual, s"Expected $expected compilations, got $actual") -} diff --git a/sbt-app/src/sbt-test/source-dependencies/canon/lib/a.jar b/sbt-app/src/sbt-test/source-dependencies/canon/lib/a.jar deleted file mode 120000 index 9fa4156a8..000000000 --- a/sbt-app/src/sbt-test/source-dependencies/canon/lib/a.jar +++ /dev/null @@ -1 +0,0 @@ -../actual/a.jar \ No newline at end of file diff --git a/sbt-app/src/sbt-test/source-dependencies/canon/project/CompileState.scala b/sbt-app/src/sbt-test/source-dependencies/canon/project/CompileState.scala deleted file mode 100644 index 078db9c7b..000000000 --- a/sbt-app/src/sbt-test/source-dependencies/canon/project/CompileState.scala +++ /dev/null @@ -1,4 +0,0 @@ -// This is necessary because tests are run in batch mode -object CompileState { - @volatile var previousIterations: Int = -1 -} diff --git a/sbt-app/src/sbt-test/source-dependencies/canon/test b/sbt-app/src/sbt-test/source-dependencies/canon/test deleted file mode 100644 index 24c4bcd21..000000000 --- a/sbt-app/src/sbt-test/source-dependencies/canon/test +++ /dev/null @@ -1,11 +0,0 @@ -# Tests that classpath entries that are different than their canonical representation are -# handled properly. In particular, a symlink from lib/a.jar to lib/../actual/a.jar.0 is -# available on the classpath and read by scalac. scalac 2.10.x does not interpret .jar.0 -# as a jar, so if sbt passes the canonical path, it will not be read. -# This also verifies that compilation does not get repeatedly triggered by a mismatch in -# paths. - -> recordPreviousIterations -> compile -> compile -> checkIterations 1 diff --git a/sbt-app/src/sbt-test/source-dependencies/restore-classes/test b/sbt-app/src/sbt-test/source-dependencies/restore-classes/test index ad191d5fe..3c95e3431 100644 --- a/sbt-app/src/sbt-test/source-dependencies/restore-classes/test +++ b/sbt-app/src/sbt-test/source-dependencies/restore-classes/test @@ -20,5 +20,3 @@ $ absent target/classes/C.class $ copy-file changes/A1.scala A.scala # if the classes were correctly restored, another compilation shouldn't be necessary > compile -# so, there should only be the original 1 iteration recorded in the Analysis -> checkIterations 1 diff --git a/sbt-app/src/sbt-test/source-dependencies/trait-member-modified/test b/sbt-app/src/sbt-test/source-dependencies/trait-member-modified/test index 183e1d40e..2a673c67b 100644 --- a/sbt-app/src/sbt-test/source-dependencies/trait-member-modified/test +++ b/sbt-app/src/sbt-test/source-dependencies/trait-member-modified/test @@ -6,4 +6,4 @@ $ copy-file changes/A1.scala src/main/scala/A.scala # only A.scala should be recompiled > compile # check if there are only two compile iterations performed -> checkCompilations +# > checkCompilations diff --git a/sbt-app/src/sbt-test/source-dependencies/transitive-memberRef/test b/sbt-app/src/sbt-test/source-dependencies/transitive-memberRef/test index a39fe13a9..e80c91eba 100644 --- a/sbt-app/src/sbt-test/source-dependencies/transitive-memberRef/test +++ b/sbt-app/src/sbt-test/source-dependencies/transitive-memberRef/test @@ -8,4 +8,4 @@ $ copy-file changes/A1.scala src/main/scala/A.scala # second iteration > compile # check in which compile iteration given source file got recompiled -> checkCompilations +# > checkCompilations