diff --git a/.gitmodules b/.gitmodules index 70558849ecab..6abb70444e77 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,12 +13,6 @@ [submodule "community-build/community-projects/scalatest"] path = community-build/community-projects/scalatest url = https://github.com/dotty-staging/scalatest -[submodule "community-build/community-projects/scopt"] - path = community-build/community-projects/scopt - url = https://github.com/dotty-staging/scopt -[submodule "community-build/community-projects/squants"] - path = community-build/community-projects/squants - url = https://github.com/dotty-staging/squants [submodule "community-build/community-projects/scalap"] path = community-build/community-projects/scalap url = https://github.com/dotty-staging/scala diff --git a/community-build/community-projects/minitest b/community-build/community-projects/minitest index 97df5c7997a4..746b6aa16432 160000 --- a/community-build/community-projects/minitest +++ b/community-build/community-projects/minitest @@ -1 +1 @@ -Subproject commit 97df5c7997a4ccfb0fe4a32800cb79b19a3d2a52 +Subproject commit 746b6aa1643254786549ebe2785c80693359acd1 diff --git a/community-build/community-projects/scalacheck b/community-build/community-projects/scalacheck index b980c99ed96c..a847e3f81fdb 160000 --- a/community-build/community-projects/scalacheck +++ b/community-build/community-projects/scalacheck @@ -1 +1 @@ -Subproject commit b980c99ed96c1b93483bb4a72a2e36548b7bbe12 +Subproject commit a847e3f81fdb9fae520ffba25a4804b4b7205ddd diff --git a/community-build/community-projects/scopt b/community-build/community-projects/scopt deleted file mode 160000 index 36ab213e6a5b..000000000000 --- a/community-build/community-projects/scopt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 36ab213e6a5bcece10c1cadebf73b490718ab91a diff --git a/community-build/community-projects/squants b/community-build/community-projects/squants deleted file mode 160000 index bbbb64791b2b..000000000000 --- a/community-build/community-projects/squants +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bbbb64791b2be3ebc53943cdfa94871ce2b79e7a diff --git a/community-build/community-projects/stdLib213 b/community-build/community-projects/stdLib213 index 09b05334175c..21cb41941e39 160000 --- a/community-build/community-projects/stdLib213 +++ b/community-build/community-projects/stdLib213 @@ -1 +1 @@ -Subproject commit 09b05334175ce5019f5169f3a3e5d4bbb341ea99 +Subproject commit 21cb41941e399b0b06c4ea80abbc6e2084f2e415 diff --git a/community-build/src/scala/dotty/communitybuild/projects.scala b/community-build/src/scala/dotty/communitybuild/projects.scala index f2c0c6e91b5e..964909deedab 100644 --- a/community-build/src/scala/dotty/communitybuild/projects.scala +++ b/community-build/src/scala/dotty/communitybuild/projects.scala @@ -72,7 +72,18 @@ final case class SbtCommunityProject( dependencies: List[CommunityProject] = Nil, sbtPublishCommand: String = null) extends CommunityProject: override val binaryName: String = "sbt" - private val baseCommand = s";clean ;set logLevel in Global := Level.Error ;set updateOptions in Global ~= (_.withLatestSnapshots(false)) ;++$compilerVersion! " + + val dependencyOverrides = List( + // dependencyOverrides doesn't seem to understand `%%%` + """"org.scalacheck" %% "scalacheck" % "1.15.2-SNAPSHOT"""", + """"org.scalacheck" %% "scalacheck_sjs1" % "1.15.2-SNAPSHOT"""" + ) + + private val baseCommand = + "clean; set logLevel in Global := Level.Error; set updateOptions in Global ~= (_.withLatestSnapshots(false)); " + ++ s"""set dependencyOverrides in ThisBuild ++= ${dependencyOverrides.mkString("Seq(", ", ", ")")}; """ + ++ s"++$compilerVersion!; " + override val testCommand = s"$baseCommand$sbtTestCommand" override val publishCommand = s"$baseCommand$sbtPublishCommand" @@ -85,7 +96,7 @@ final case class SbtCommunityProject( if (forceUpgradeSbtScalajsPlugin) List(s"--addPluginSbtFile=$sbtScalaJSPluginFilePath") else Nil extraSbtArgs ++ sbtProps ++ List( - "-sbt-version", "1.3.8", + "-sbt-version", "1.4.4", "-Dsbt.supershell=false", s"--addPluginSbtFile=$sbtPluginFilePath" ) ++ scalaJSPluginArgs @@ -172,14 +183,14 @@ object projects: lazy val scalacheck = SbtCommunityProject( project = "scalacheck", - sbtTestCommand = "jvm/test", - sbtPublishCommand = ";set jvm/publishArtifact in (Compile, packageDoc) := false ;jvm/publishLocal" + sbtTestCommand = "jvm/test;js/test", + sbtPublishCommand = "jvm/publishLocal;js/publishLocal" ) lazy val scalatest = SbtCommunityProject( project = "scalatest", - sbtTestCommand = ";scalacticDotty/clean;scalacticTestDotty/test;scalatestTestDotty/test", - sbtPublishCommand = ";scalacticDotty/publishLocal; scalatestDotty/publishLocal" + sbtTestCommand = "scalacticDotty/clean;scalacticTestDotty/test; scalatestTestDotty/test", + sbtPublishCommand = "scalacticDotty/publishLocal; scalatestDotty/publishLocal" ) lazy val scalatestplusScalacheck = SbtCommunityProject( @@ -194,21 +205,11 @@ object projects: sbtTestCommand = "xml/test", ) - lazy val scopt = SbtCommunityProject( - project = "scopt", - sbtTestCommand = "scoptJVM/compile", - ) - lazy val scalap = SbtCommunityProject( project = "scalap", sbtTestCommand = "scalap/compile", ) - lazy val squants = SbtCommunityProject( - project = "squants", - sbtTestCommand = "squantsJVM/compile", - ) - lazy val betterfiles = SbtCommunityProject( project = "betterfiles", sbtTestCommand = "dotty-community-build/compile", @@ -221,7 +222,8 @@ object projects: lazy val minitest = SbtCommunityProject( project = "minitest", - sbtTestCommand = "dotty-community-build/compile", + sbtTestCommand = "test", + dependencies = List(scalacheck) ) lazy val fastparse = SbtCommunityProject( @@ -233,7 +235,7 @@ object projects: project = "stdLib213", extraSbtArgs = List("-Dscala.build.compileWithDotty=true"), sbtTestCommand = """library/compile""", - sbtPublishCommand = """;set publishArtifact in (library, Compile, packageDoc) := false ;library/publishLocal""", + sbtPublishCommand = """set publishArtifact in (library, Compile, packageDoc) := false ;library/publishLocal""", ) lazy val shapeless = SbtCommunityProject( @@ -256,9 +258,9 @@ object projects: // has not been updated since 2018, so no 2.13 compat. Some akka tests are dropped due to MutableBehaviour being // dropped in the 2.13 compatible release - // sbtTestCommand = ";set ThisBuild / useEffpiPlugin := false; effpi/test:compile; plugin/test:compile; benchmarks/test:compile; examples/test:compile; pluginBenchmarks/test:compile", + // sbtTestCommand = "set ThisBuild / useEffpiPlugin := false; effpi/test:compile; plugin/test:compile; benchmarks/test:compile; examples/test:compile; pluginBenchmarks/test:compile", - sbtTestCommand = ";set ThisBuild / useEffpiPlugin := false; effpi/test:compile; benchmarks/test:compile; examples/test:compile; pluginBenchmarks/test:compile", + sbtTestCommand = "set ThisBuild / useEffpiPlugin := false; effpi/test:compile; benchmarks/test:compile; examples/test:compile; pluginBenchmarks/test:compile", ) // TODO @odersky? It got broken by #5458 @@ -313,7 +315,7 @@ object projects: lazy val endpoints4s = SbtCommunityProject( project = "endpoints4s", - sbtTestCommand = ";json-schemaJVM/compile;algebraJVM/compile;openapiJVM/compile;http4s-server/compile;http4s-client/compile;play-server/compile;play-client/compile;akka-http-server/compile;akka-http-client/compile" + sbtTestCommand = "json-schemaJVM/compile;algebraJVM/compile;openapiJVM/compile;http4s-server/compile;http4s-client/compile;play-server/compile;play-client/compile;akka-http-server/compile;akka-http-client/compile" ) lazy val catsEffect2 = SbtCommunityProject( diff --git a/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala b/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala index cd874874062a..747893264b43 100644 --- a/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala +++ b/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala @@ -123,9 +123,7 @@ class CommunityBuildTestB extends CommunityBuildTest: @Test def scalaz = projects.scalaz.run() @Test def scas = projects.scas.run() @Test def sconfig = projects.sconfig.run() - @Test def scopt = projects.scopt.run() @Test def shapeless = projects.shapeless.run() - @Test def squants = projects.squants.run() @Test def stdLib213 = projects.stdLib213.run() @Test def xmlInterpolator = projects.xmlInterpolator.run() @Test def zio = projects.zio.run() diff --git a/project/Build.scala b/project/Build.scala index 91741b458723..031a496a4b90 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -211,7 +211,14 @@ object Build { } // Do not cut off the bottom of large stack traces (default is 1024) "-XX:MaxJavaStackTraceDepth=1000000" :: agentOptions ::: ciOptions - } + }, + + excludeLintKeys ++= Set( + // We set these settings in `commonSettings`, if a project + // uses `commonSettings` but overrides `unmanagedSourceDirectories`, + // sbt will complain if we don't exclude them here. + Keys.scalaSource, Keys.javaSource + ), ) lazy val disableDocSetting = @@ -1197,6 +1204,12 @@ object Build { unmanagedSourceDirectories in Compile += baseDirectory.value / "../language-server/src/dotty/tools/languageserver/config", sbtTestDirectory := baseDirectory.value / "sbt-test", + + // The batch mode accidentally became the default with no way to disable + // it in sbt 1.4 (https://github.com/sbt/sbt/issues/5913#issuecomment-716003195). + // We enable it explicitly here to make it clear that we're using it. + scriptedBatchExecution := true, + scriptedLaunchOpts ++= Seq( "-Dplugin.version=" + version.value, "-Dplugin.scalaVersion=" + dottyVersion, diff --git a/project/build.properties b/project/build.properties index 654fe70c42c7..7de0a9382f10 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.12 +sbt.version=1.4.4 diff --git a/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/build.sbt b/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/build.sbt index 6c2c11e0926a..1036709ccfc1 100644 --- a/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/build.sbt @@ -1,9 +1,25 @@ +import sbt.internal.inc.Analysis import complete.DefaultParsers._ -InputKey[Unit]("check-number-of-compiler-iterations") := { - val args = spaceDelimited("").parsed - val a = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] - assert(args.size == 1) - val expectedIterationsNumber = args(0).toInt - assert(a.compilations.allCompilations.size == expectedIterationsNumber, "a.compilations.allCompilations.size = %d (expected %d)".format(a.compilations.allCompilations.size, expectedIterationsNumber)) +// Reset compiler iterations, necessary because tests run in batch mode +val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") +recordPreviousIterations := { + val log = streams.value.log + CompileState.previousIterations = { + val previousAnalysis = (previousCompile in Compile).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 in 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-dotty/sbt-test/source-dependencies/abstract-type-override/project/CompileState.scala b/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/project/CompileState.scala new file mode 100644 index 000000000000..078db9c7bf56 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/project/CompileState.scala @@ -0,0 +1,4 @@ +// This is necessary because tests are run in batch mode +object CompileState { + @volatile var previousIterations: Int = -1 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/test b/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/test index 9ffa4fb17ccd..aa5e9b5c09a1 100644 --- a/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/test +++ b/sbt-dotty/sbt-test/source-dependencies/abstract-type-override/test @@ -1,3 +1,4 @@ +> recordPreviousIterations # Test for separate compilation and proper value of # the OVERRIDE flag when abstract types, type alias # and structural type are involved @@ -11,4 +12,4 @@ $ copy-file changes/Bar1.scala src/main/scala/Bar.scala # second iteration #> compile # check if there are only two compile iterations performed -> checkNumberOfCompilerIterations 2 +> checkIterations 2 diff --git a/sbt-dotty/sbt-test/source-dependencies/canon/build.sbt b/sbt-dotty/sbt-test/source-dependencies/canon/build.sbt index d7524d433978..1036709ccfc1 100644 --- a/sbt-dotty/sbt-test/source-dependencies/canon/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/canon/build.sbt @@ -1,12 +1,25 @@ +import sbt.internal.inc.Analysis import complete.DefaultParsers._ -val checkIterations = inputKey[Unit]("Verifies the accumlated number of iterations of incremental compilation.") +// Reset compiler iterations, necessary because tests run in batch mode +val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") +recordPreviousIterations := { + val log = streams.value.log + CompileState.previousIterations = { + val previousAnalysis = (previousCompile in Compile).value.analysis.asScala + previousAnalysis match { + case None => + log.info("No previous analysis detected") + 0 + case Some(a: Analysis) => a.compilations.allCompilations.size + } + } +} -checkIterations := { - val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] +val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") +checkIterations := { val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = analysis.compilations.allCompilations.size + val actual: Int = ((compile in 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-dotty/sbt-test/source-dependencies/canon/project/CompileState.scala b/sbt-dotty/sbt-test/source-dependencies/canon/project/CompileState.scala new file mode 100644 index 000000000000..078db9c7bf56 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/canon/project/CompileState.scala @@ -0,0 +1,4 @@ +// This is necessary because tests are run in batch mode +object CompileState { + @volatile var previousIterations: Int = -1 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/canon/test b/sbt-dotty/sbt-test/source-dependencies/canon/test index 13caf4871420..b861bea7c18e 100644 --- a/sbt-dotty/sbt-test/source-dependencies/canon/test +++ b/sbt-dotty/sbt-test/source-dependencies/canon/test @@ -1,3 +1,4 @@ +> recordPreviousIterations # 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 diff --git a/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/build.sbt b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/build.sbt index d7524d433978..1036709ccfc1 100644 --- a/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/build.sbt @@ -1,12 +1,25 @@ +import sbt.internal.inc.Analysis import complete.DefaultParsers._ -val checkIterations = inputKey[Unit]("Verifies the accumlated number of iterations of incremental compilation.") +// Reset compiler iterations, necessary because tests run in batch mode +val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") +recordPreviousIterations := { + val log = streams.value.log + CompileState.previousIterations = { + val previousAnalysis = (previousCompile in Compile).value.analysis.asScala + previousAnalysis match { + case None => + log.info("No previous analysis detected") + 0 + case Some(a: Analysis) => a.compilations.allCompilations.size + } + } +} -checkIterations := { - val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] +val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") +checkIterations := { val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = analysis.compilations.allCompilations.size + val actual: Int = ((compile in 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-dotty/sbt-test/source-dependencies/constructors-unrelated/project/CompileState.scala b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/project/CompileState.scala new file mode 100644 index 000000000000..078db9c7bf56 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/project/CompileState.scala @@ -0,0 +1,4 @@ +// This is necessary because tests are run in batch mode +object CompileState { + @volatile var previousIterations: Int = -1 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/test b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/test index efd4edd50098..fcfd944e1000 100644 --- a/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/test +++ b/sbt-dotty/sbt-test/source-dependencies/constructors-unrelated/test @@ -1,3 +1,4 @@ +> recordPreviousIterations > compile $ copy-file changes/A2.scala A.scala # Second compilation round, there should be no third round (we don't need to recompile B.scala) diff --git a/sbt-dotty/sbt-test/source-dependencies/inline-inherited/build.sbt b/sbt-dotty/sbt-test/source-dependencies/inline-inherited/build.sbt index d7524d433978..1036709ccfc1 100644 --- a/sbt-dotty/sbt-test/source-dependencies/inline-inherited/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/inline-inherited/build.sbt @@ -1,12 +1,25 @@ +import sbt.internal.inc.Analysis import complete.DefaultParsers._ -val checkIterations = inputKey[Unit]("Verifies the accumlated number of iterations of incremental compilation.") +// Reset compiler iterations, necessary because tests run in batch mode +val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") +recordPreviousIterations := { + val log = streams.value.log + CompileState.previousIterations = { + val previousAnalysis = (previousCompile in Compile).value.analysis.asScala + previousAnalysis match { + case None => + log.info("No previous analysis detected") + 0 + case Some(a: Analysis) => a.compilations.allCompilations.size + } + } +} -checkIterations := { - val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] +val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") +checkIterations := { val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = analysis.compilations.allCompilations.size + val actual: Int = ((compile in 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-dotty/sbt-test/source-dependencies/inline-inherited/project/CompileState.scala b/sbt-dotty/sbt-test/source-dependencies/inline-inherited/project/CompileState.scala new file mode 100644 index 000000000000..078db9c7bf56 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/inline-inherited/project/CompileState.scala @@ -0,0 +1,4 @@ +// This is necessary because tests are run in batch mode +object CompileState { + @volatile var previousIterations: Int = -1 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/inline-inherited/test b/sbt-dotty/sbt-test/source-dependencies/inline-inherited/test index ce63d72d4b74..02ab72cb1877 100644 --- a/sbt-dotty/sbt-test/source-dependencies/inline-inherited/test +++ b/sbt-dotty/sbt-test/source-dependencies/inline-inherited/test @@ -1,3 +1,4 @@ +> recordPreviousIterations > compile # Force recompilation of B, B.getInline hasn't changed so C shouldn't be recompiled. $ copy-file changes/B1.scala B.scala diff --git a/sbt-dotty/sbt-test/source-dependencies/inner-class/build.sbt b/sbt-dotty/sbt-test/source-dependencies/inner-class/build.sbt index d7524d433978..1036709ccfc1 100644 --- a/sbt-dotty/sbt-test/source-dependencies/inner-class/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/inner-class/build.sbt @@ -1,12 +1,25 @@ +import sbt.internal.inc.Analysis import complete.DefaultParsers._ -val checkIterations = inputKey[Unit]("Verifies the accumlated number of iterations of incremental compilation.") +// Reset compiler iterations, necessary because tests run in batch mode +val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") +recordPreviousIterations := { + val log = streams.value.log + CompileState.previousIterations = { + val previousAnalysis = (previousCompile in Compile).value.analysis.asScala + previousAnalysis match { + case None => + log.info("No previous analysis detected") + 0 + case Some(a: Analysis) => a.compilations.allCompilations.size + } + } +} -checkIterations := { - val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] +val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") +checkIterations := { val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = analysis.compilations.allCompilations.size + val actual: Int = ((compile in 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-dotty/sbt-test/source-dependencies/inner-class/project/CompileState.scala b/sbt-dotty/sbt-test/source-dependencies/inner-class/project/CompileState.scala new file mode 100644 index 000000000000..078db9c7bf56 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/inner-class/project/CompileState.scala @@ -0,0 +1,4 @@ +// This is necessary because tests are run in batch mode +object CompileState { + @volatile var previousIterations: Int = -1 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/inner-class/test b/sbt-dotty/sbt-test/source-dependencies/inner-class/test index e13b5ba1160f..7bc854bb0f52 100644 --- a/sbt-dotty/sbt-test/source-dependencies/inner-class/test +++ b/sbt-dotty/sbt-test/source-dependencies/inner-class/test @@ -1,3 +1,4 @@ +> recordPreviousIterations > run # Recompile B (no meaningful change, this is just so that the dependencies on A.InnerClass are diff --git a/sbt-dotty/sbt-test/source-dependencies/inner-object/build.sbt b/sbt-dotty/sbt-test/source-dependencies/inner-object/build.sbt index d7524d433978..1036709ccfc1 100644 --- a/sbt-dotty/sbt-test/source-dependencies/inner-object/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/inner-object/build.sbt @@ -1,12 +1,25 @@ +import sbt.internal.inc.Analysis import complete.DefaultParsers._ -val checkIterations = inputKey[Unit]("Verifies the accumlated number of iterations of incremental compilation.") +// Reset compiler iterations, necessary because tests run in batch mode +val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") +recordPreviousIterations := { + val log = streams.value.log + CompileState.previousIterations = { + val previousAnalysis = (previousCompile in Compile).value.analysis.asScala + previousAnalysis match { + case None => + log.info("No previous analysis detected") + 0 + case Some(a: Analysis) => a.compilations.allCompilations.size + } + } +} -checkIterations := { - val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] +val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") +checkIterations := { val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = analysis.compilations.allCompilations.size + val actual: Int = ((compile in 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-dotty/sbt-test/source-dependencies/inner-object/project/CompileState.scala b/sbt-dotty/sbt-test/source-dependencies/inner-object/project/CompileState.scala new file mode 100644 index 000000000000..078db9c7bf56 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/inner-object/project/CompileState.scala @@ -0,0 +1,4 @@ +// This is necessary because tests are run in batch mode +object CompileState { + @volatile var previousIterations: Int = -1 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/inner-object/test b/sbt-dotty/sbt-test/source-dependencies/inner-object/test index dee41f3bfccb..5adf4a7a5906 100644 --- a/sbt-dotty/sbt-test/source-dependencies/inner-object/test +++ b/sbt-dotty/sbt-test/source-dependencies/inner-object/test @@ -1,3 +1,4 @@ +> recordPreviousIterations > run # Recompile B (no meaningful change, this is just so that the dependency on A.InnerObject are diff --git a/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/build.sbt b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/build.sbt index d7524d433978..1036709ccfc1 100644 --- a/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/build.sbt @@ -1,12 +1,25 @@ +import sbt.internal.inc.Analysis import complete.DefaultParsers._ -val checkIterations = inputKey[Unit]("Verifies the accumlated number of iterations of incremental compilation.") +// Reset compiler iterations, necessary because tests run in batch mode +val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") +recordPreviousIterations := { + val log = streams.value.log + CompileState.previousIterations = { + val previousAnalysis = (previousCompile in Compile).value.analysis.asScala + previousAnalysis match { + case None => + log.info("No previous analysis detected") + 0 + case Some(a: Analysis) => a.compilations.allCompilations.size + } + } +} -checkIterations := { - val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] +val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") +checkIterations := { val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = analysis.compilations.allCompilations.size + val actual: Int = ((compile in 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-dotty/sbt-test/source-dependencies/less-inter-inv-java/project/CompileState.scala b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/project/CompileState.scala new file mode 100644 index 000000000000..078db9c7bf56 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/project/CompileState.scala @@ -0,0 +1,4 @@ +// This is necessary because tests are run in batch mode +object CompileState { + @volatile var previousIterations: Int = -1 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/test b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/test index 85a7c97e97f3..4f53f2541964 100644 --- a/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/test +++ b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv-java/test @@ -1,3 +1,4 @@ +> recordPreviousIterations # 1 iteration from initial full compile > run $ copy-file changes/A2.java A.java diff --git a/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/build.sbt b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/build.sbt index d7524d433978..1036709ccfc1 100644 --- a/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/build.sbt @@ -1,12 +1,25 @@ +import sbt.internal.inc.Analysis import complete.DefaultParsers._ -val checkIterations = inputKey[Unit]("Verifies the accumlated number of iterations of incremental compilation.") +// Reset compiler iterations, necessary because tests run in batch mode +val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") +recordPreviousIterations := { + val log = streams.value.log + CompileState.previousIterations = { + val previousAnalysis = (previousCompile in Compile).value.analysis.asScala + previousAnalysis match { + case None => + log.info("No previous analysis detected") + 0 + case Some(a: Analysis) => a.compilations.allCompilations.size + } + } +} -checkIterations := { - val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] +val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") +checkIterations := { val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = analysis.compilations.allCompilations.size + val actual: Int = ((compile in 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-dotty/sbt-test/source-dependencies/less-inter-inv/project/CompileState.scala b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/project/CompileState.scala new file mode 100644 index 000000000000..078db9c7bf56 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/project/CompileState.scala @@ -0,0 +1,4 @@ +// This is necessary because tests are run in batch mode +object CompileState { + @volatile var previousIterations: Int = -1 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/test b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/test index c6df5698e0db..d0ccf51b9d88 100644 --- a/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/test +++ b/sbt-dotty/sbt-test/source-dependencies/less-inter-inv/test @@ -1,3 +1,4 @@ +> recordPreviousIterations # 1 iteration from initial full compile > run $ copy-file changes/A2.scala A.scala diff --git a/sbt-dotty/sbt-test/source-dependencies/restore-classes/build.sbt b/sbt-dotty/sbt-test/source-dependencies/restore-classes/build.sbt index cf38564cc570..1036709ccfc1 100644 --- a/sbt-dotty/sbt-test/source-dependencies/restore-classes/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/restore-classes/build.sbt @@ -1,14 +1,25 @@ +import sbt.internal.inc.Analysis import complete.DefaultParsers._ -crossTarget in Compile := target.value +// Reset compiler iterations, necessary because tests run in batch mode +val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") +recordPreviousIterations := { + val log = streams.value.log + CompileState.previousIterations = { + val previousAnalysis = (previousCompile in Compile).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 accumlated number of iterations of incremental compilation.") +val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") checkIterations := { - val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] - val expected: Int = (Space ~> NatBasic).parsed - val actual: Int = analysis.compilations.allCompilations.size + val actual: Int = ((compile in 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-dotty/sbt-test/source-dependencies/restore-classes/project/CompileState.scala b/sbt-dotty/sbt-test/source-dependencies/restore-classes/project/CompileState.scala new file mode 100644 index 000000000000..078db9c7bf56 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/restore-classes/project/CompileState.scala @@ -0,0 +1,4 @@ +// This is necessary because tests are run in batch mode +object CompileState { + @volatile var previousIterations: Int = -1 +} diff --git a/sbt-dotty/sbt-test/source-dependencies/restore-classes/test b/sbt-dotty/sbt-test/source-dependencies/restore-classes/test index 028d6226cd95..f8810f81c8b2 100644 --- a/sbt-dotty/sbt-test/source-dependencies/restore-classes/test +++ b/sbt-dotty/sbt-test/source-dependencies/restore-classes/test @@ -1,3 +1,4 @@ +> recordPreviousIterations $ copy-file changes/A1.scala A.scala $ copy-file changes/B.scala B.scala # B depends on A diff --git a/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/build.sbt b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/build.sbt index eb7dacf3414f..3cb1388c242e 100644 --- a/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/build.sbt @@ -1,14 +1,28 @@ -lazy val commonSettings = Seq( - logLevel := Level.Debug -) -lazy val provider = project.settings(commonSettings) -lazy val use = project.settings(commonSettings).dependsOn(provider) +import sbt.internal.inc.Analysis +import complete.DefaultParsers._ -InputKey[Unit]("check-number-of-compiler-iterations") <<= inputTask { (argTask: TaskKey[Seq[String]]) => - (argTask, compile in Compile in use) map { (args: Seq[String], a: sbt.inc.Analysis) => - assert(args.size == 1) - val expectedIterationsNumber = args(0).toInt - assert(a.compilations.allCompilations.size == expectedIterationsNumber, - "a.compilations.allCompilations.size = %d (expected %d)".format(a.compilations.allCompilations.size, expectedIterationsNumber)) +// Reset compiler iterations, necessary because tests run in batch mode +val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") +recordPreviousIterations := { + val log = streams.value.log + CompileState.previousIterations = { + val previousAnalysis = (previousCompile in Compile).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 in Compile).value match { case a: Analysis => a.compilations.allCompilations.size }) - CompileState.previousIterations + assert(expected == actual, s"Expected $expected compilations, got $actual") +} + +lazy val provider = project.settings(commonSettings) +lazy val use = project.settings(commonSettings).dependsOn(provider) diff --git a/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/pending b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/pending index ee782c14ca26..98ab992e4833 100644 --- a/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/pending +++ b/sbt-dotty/sbt-test/source-dependencies/subproject-dependency-b/pending @@ -1,9 +1,10 @@ +> recordPreviousIterations > compile $ copy-file changes/A1.scala provider/A.scala > compile -> check-number-of-compiler-iterations 1 +> checkIterations 1 $ copy-file changes/A2.scala provider/A.scala > compile -> check-number-of-compiler-iterations 1 +> checkIterations 1 diff --git a/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/build.sbt b/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/build.sbt index 1ebe8fad1a41..d951aaaf52f7 100644 --- a/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/build.sbt @@ -1,24 +1,46 @@ +import xsbti.VirtualFileRef +import sbt.internal.inc.Analysis +import xsbti.compile.{PreviousResult, CompileAnalysis, MiniSetup} +import xsbti.compile.analysis.{ Compilation => XCompilation } + +previousCompile in Compile := { + val previous = (previousCompile in Compile).value + if (!CompileState.isNew) { + val res = PreviousResult.of(none[CompileAnalysis].asJava, none[MiniSetup].asJava) + CompileState.isNew = true + res + } else previous +} + /* Performs checks related to compilations: * a) checks in which compilation given set of files was recompiled * b) checks overall number of compilations performed */ -TaskKey[Unit]("check-compilations") := { - val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] +TaskKey[Unit]("checkCompilations") := { + val analysis = (compile in Compile).value match { case a: Analysis => a } + val srcDir = (scalaSource in Compile).value + def findFile(className: String): VirtualFileRef = { + analysis.relations.definesClass(className).head + } val allCompilations = analysis.compilations.allCompilations - val recompiledClasses: Seq[Set[String]] = allCompilations map { c => - val recompiledClasses = analysis.apis.internal.collect { - case (clazz, api) if api.compilationTimestamp() == c.getStartTime() => clazz + val recompiledFiles: Seq[Set[VirtualFileRef]] = allCompilations map { c: XCompilation => + val recompiledFiles = analysis.apis.internal.collect { + case (cn, api) if api.compilationTimestamp == c.getStartTime => findFile(cn) } - recompiledClasses.toSet + recompiledFiles.toSet } - def recompiledFilesInIteration(iteration: Int, classNames: Set[String]): Unit = { - assert(recompiledClasses(iteration) == classNames, "%s != %s".format(recompiledClasses(iteration), classNames)) + def recompiledFilesInIteration(iteration: Int, fileNames: Set[String]) = { + assert(recompiledFiles(iteration).map(_.name) == fileNames, + s"""${recompiledFiles(iteration).map(_.name)} != $fileNames + | + |allCompilations = $allCompilations + |""".stripMargin) } - assert(allCompilations.size == 2) + assert(allCompilations.size == 2, s"All compilations is ${allCompilations.size}") // B.scala is just compiled at the beginning - recompiledFilesInIteration(0, Set("B")) + recompiledFilesInIteration(0, Set("B.scala")) // A.scala is changed and recompiled - recompiledFilesInIteration(1, Set("A")) + recompiledFilesInIteration(1, Set("A.scala")) } logLevel := Level.Debug diff --git a/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/project/CompileState.scala b/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/project/CompileState.scala new file mode 100644 index 000000000000..c50b231cc9e3 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/trait-member-modified/project/CompileState.scala @@ -0,0 +1,4 @@ +// This is necessary because tests are run in batch mode +object CompileState { + @volatile var isNew: Boolean = false +} diff --git a/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/build.sbt b/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/build.sbt index 5180981ce13c..9124b2590c35 100644 --- a/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/build.sbt +++ b/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/build.sbt @@ -1,36 +1,69 @@ +import sbt.internal.inc.Analysis +import xsbti.VirtualFileRef +import xsbti.api.AnalyzedClass +import xsbti.compile.{PreviousResult, CompileAnalysis, MiniSetup} +import xsbti.compile.analysis.{ Compilation => XCompilation } + logLevel := Level.Debug +// Reset compile status because scripted tests are run in batch mode +previousCompile in Compile := { + val previous = (previousCompile in Compile).value + if (!CompileState.isNew) { + val res = PreviousResult.of(none[CompileAnalysis].asJava, none[MiniSetup].asJava) + CompileState.isNew = true + res + } else previous +} + // disable sbt's heuristic which recompiles everything in case // some fraction (e.g. 50%) of files is scheduled to be recompiled // in this test we want precise information about recompiled files // which that heuristic would distort incOptions := incOptions.value.withRecompileAllFraction(1.0) +Global / allowMachinePath := false + /* Performs checks related to compilations: * a) checks in which compilation given set of files was recompiled * b) checks overall number of compilations performed */ -TaskKey[Unit]("check-compilations") := { - val analysis = (compile in Compile).value.asInstanceOf[sbt.internal.inc.Analysis] +TaskKey[Unit]("checkCompilations") := { + val log = streams.value.log + val c = fileConverter.value + val vs = (Compile / sources).value.toVector map { x => + c.toVirtualFile(x.toPath) + } + // log.info(vs.mkString(",")) + + val analysis = (compile in Compile).value match { case a: Analysis => a } val srcDir = (scalaSource in Compile).value - val allCompilations = analysis.compilations.allCompilations - val recompiledClasses: Seq[Set[String]] = allCompilations map { c => - val recompiledClasses = analysis.apis.internal.collect { - case (clazz, api) if api.compilationTimestamp() == c.getStartTime() => clazz + def findFile(className: String): VirtualFileRef = { + analysis.relations.definesClass(className).head + } + val allCompilations: Seq[XCompilation] = analysis.compilations.allCompilations + log.info(s"allCompilations: $allCompilations") + val recompiledFiles: Seq[Set[VirtualFileRef]] = allCompilations map { c: XCompilation => + val recompiledFiles = analysis.apis.internal.collect { + case (cn, api) if api.compilationTimestamp == c.getStartTime => findFile(cn) } - recompiledClasses.toSet + recompiledFiles.toSet } - def recompiledClassesInIteration(iteration: Int, classNames: Set[String]): Unit = { - assert(recompiledClasses(iteration) == classNames, "%s != %s".format(recompiledClasses(iteration), classNames)) + def recompiledFilesInIteration(iteration: Int, fileNames: Set[String]) = { + assert(recompiledFiles(iteration).map(_.name) == fileNames, + s"""${recompiledFiles(iteration).map(_.name)} != $fileNames + | + |allCompilations = $allCompilations + |""".stripMargin) } - // test.Y is compiled only at the beginning as changes to test.A do not affect it - recompiledClassesInIteration(0, Set("test.X", "test.Y")) - // test.A is changed and recompiled - recompiledClassesInIteration(1, Set("test.A")) - // change in test.A causes recompilation of test.B, test.C, test.D which depend on transitively - // and by inheritance on test.A - // test.X is also recompiled because it depends by member reference on test.B - // Note that test.Y is not recompiled because it depends just on X through member reference dependency - recompiledClassesInIteration(2, Set("test.B", "test.C", "test.D")) + // Y.scala is compiled only at the beginning as changes to A.scala do not affect it + recompiledFilesInIteration(0, Set("X.scala", "Y.scala")) + // A.scala is changed and recompiled + recompiledFilesInIteration(1, Set("A.scala")) + // change in A.scala causes recompilation of B.scala, C.scala, D.scala which depend on transitively + // and by inheritance on A.scala + // X.scala is also recompiled because it depends by member reference on B.scala + // Note that Y.scala is not recompiled because it depends just on X through member reference dependency + recompiledFilesInIteration(2, Set("B.scala", "C.scala", "D.scala")) assert(allCompilations.size == 3) } diff --git a/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/project/CompileState.scala b/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/project/CompileState.scala new file mode 100644 index 000000000000..c50b231cc9e3 --- /dev/null +++ b/sbt-dotty/sbt-test/source-dependencies/transitive-memberRef/project/CompileState.scala @@ -0,0 +1,4 @@ +// This is necessary because tests are run in batch mode +object CompileState { + @volatile var isNew: Boolean = false +} diff --git a/sbt-dotty/src/dotty/tools/sbtplugin/DottyIDEPlugin.scala b/sbt-dotty/src/dotty/tools/sbtplugin/DottyIDEPlugin.scala index 653accb21076..c0056aa7ceae 100644 --- a/sbt-dotty/src/dotty/tools/sbtplugin/DottyIDEPlugin.scala +++ b/sbt-dotty/src/dotty/tools/sbtplugin/DottyIDEPlugin.scala @@ -394,6 +394,10 @@ object DottyIDEPlugin extends AutoPlugin { ) ++ addCommandAlias("launchIDE", ";configureIDE;runCode") + override def globalSettings: Seq[Setting[_]] = Seq( + excludeLintKeys += excludeFromIDE + ) + // Ported from Bloop /** * Detect the eligible configuration dependencies from a given configuration.