diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34a2a9f925..cc56a380e0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,7 +54,7 @@ jobs: if: ${{ matrix.jobtype == 2 }} shell: bash run: | - sbt -v -Dfile.encoding=UTF-8 -Dsbt.supershell=never "crossTestBridges" "zincRoot/test" "zincScripted/Test/run" + sbt -v -Dfile.encoding=UTF-8 -Dsbt.supershell=never "Test/compile" "crossTestBridges" "zincRoot/test" "scripted" - name: Build and test (3) if: ${{ matrix.jobtype == 3 }} shell: bash diff --git a/.scalafmt.conf b/.scalafmt.conf index 31d427c8a9..5401d30296 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,5 +1,5 @@ version = 3.8.3 -runner.dialect = scala212 +runner.dialect = scala3 project.git = true project.excludeFilters = [ /sbt-test/, /input_sources/, /contraband-scala/ ] @@ -27,12 +27,13 @@ danglingParentheses.defnSite = true rewrite.trailingCommas.style = keep rewrite.scala3.convertToNewSyntax = true +rewrite.scala3.newSyntax.control = false fileOverride { "glob:**/internal/compiler-bridge/**" { rewrite.scala3.convertToNewSyntax = false + runner.dialect = scala213 } } runner.dialectOverride.allowSignificantIndentation = false runner.dialectOverride.allowAsForImportRename = false runner.dialectOverride.allowStarWildcardImport = false -runner.dialectOverride.allowPostfixStarVarargSplices = false diff --git a/bin/run-ci.sh b/bin/run-ci.sh index 4074e9705a..0477c26ad7 100755 --- a/bin/run-ci.sh +++ b/bin/run-ci.sh @@ -3,7 +3,10 @@ set -eu set -o nounset sbt -Dfile.encoding=UTF-8 \ - mimaReportBinaryIssues \ + -J-XX:ReservedCodeCacheSize=512M \ + -J-Xms1024M -J-Xmx2048M -J-server \ + scalafmtCheckAll \ + scalafmtSbtCheck \ Test/compile \ doc \ crossTestBridges \ diff --git a/build.sbt b/build.sbt index 2a90357139..ca2f06e3dc 100644 --- a/build.sbt +++ b/build.sbt @@ -46,7 +46,7 @@ ThisBuild / version := { nightlyVersion match { case Some(v) => v case _ => - if ((ThisBuild / isSnapshot).value) "1.10.6-SNAPSHOT" + if ((ThisBuild / isSnapshot).value) "2.0.0-M6-SNAPSHOT" else old } } @@ -91,7 +91,6 @@ def baseSettings: Seq[Setting[?]] = Seq( testFrameworks += new TestFramework("verify.runner.Framework"), compile / javacOptions ++= Seq("-Xlint", "-Xlint:-serial"), Test / publishArtifact := false, - scalacOptions ++= Seq("-YdisableFlatCpCaching"), scalacOptions += { scalaBinaryVersion.value match { case "2.10" | "2.11" => @@ -107,27 +106,6 @@ def baseSettings: Seq[Setting[?]] = Seq( ideSkipProject := scalaVersion.value != defaultScalaVersion, ) -def compilerVersionDependentScalacOptions: Seq[Setting[?]] = Seq( - scalacOptions := { - scalaBinaryVersion.value match { - case "2.12" | "2.13" => - scalacOptions.value ++ List( - "-opt-inline-from:", - "-opt:l:inline", - "-Yopt-inline-heuristics:at-inline-annotated" - ) - case _ => - scalacOptions.value.filterNot( - Set( - "-Xfatal-warnings", - "-deprecation", - "-YdisableFlatCpCaching", - ) - ) - } - } -) - def addBaseSettingsAndTestDeps(p: Project): Project = p.settings(baseSettings).configure(addTestDependencies) @@ -139,11 +117,8 @@ lazy val aggregated: Seq[ProjectReference] = compilerInterface.projectRefs ++ zincClasspath.projectRefs ++ zincClassfile.projectRefs ++ zincCompileCore.projectRefs ++ - zincCompile.projectRefs ++ zincCore.projectRefs ++ zincPersist.projectRefs ++ - Seq(zincPersistCore: ProjectReference) ++ - zincPersistCoreAssembly.projectRefs ++ zincTesting.projectRefs ++ zinc.projectRefs @@ -156,7 +131,7 @@ lazy val zincRoot: Project = (project in file(".")) scriptedBufferLog := true, scripted := scriptedTask.evaluated, scripted / watchTriggers += baseDirectory.value.toGlob / "zinc" / "src" / "sbt-test" / **, - Scripted.scriptedSource := (zinc212 / sourceDirectory).value / "sbt-test", + Scripted.scriptedSource := (zinc3 / sourceDirectory).value / "sbt-test", Scripted.scriptedCompileToJar := false, publish / skip := true, commands += Command.command("release") { state => @@ -239,8 +214,7 @@ lazy val zinc = (projectMatrix in (zincRootPath / "zinc")) exclude[IncompatibleResultTypeProblem]("sbt.internal.*"), ) ) - .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) - .jvmPlatform(scalaVersions = scala212_213) + .jvmPlatform(scalaVersions = scala3_only) .configure(addBaseSettingsAndTestDeps) def resGenFile = (zincRootPath / "zinc" / "resGenerator").getAbsoluteFile @@ -250,7 +224,7 @@ lazy val jar2 = (project in resGenFile / "jar2").settings(sampleProjectSettings( lazy val classesDep1 = (project in resGenFile / "classesDep1").settings(sampleProjectSettings("zip")) -lazy val zinc212 = zinc.jvm(scala212) +lazy val zinc3 = zinc.jvm(scala3) lazy val zincTesting = (projectMatrix in internalPath / "zinc-testing") .dependsOn(compilerInterface) @@ -261,42 +235,19 @@ lazy val zincTesting = (projectMatrix in internalPath / "zinc-testing") libraryDependencies ++= Seq(scalaCheck, scalatest, verify, sjsonnewScalaJson.value), dependencyOverrides += scalaXml, ) - .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) - .jvmPlatform(scalaVersions = List(scala212, scala213)) + .jvmPlatform(scalaVersions = scala3_only) .configure(addSbtIO, addSbtUtilLogging) -lazy val zincCompile = (projectMatrix in zincRootPath / "zinc-compile") - .dependsOn(zincCompileCore, zincCompileCore % "test->test") - .settings( - name := "zinc Compile", - mimaSettings, - mimaBinaryIssueFilters ++= Seq( - exclude[IncompatibleSignatureProblem]("sbt.inc.Doc*"), - exclude[IncompatibleResultTypeProblem]("sbt.inc.Doc*"), - exclude[IncompatibleMethTypeProblem]("sbt.inc.Doc*"), - exclude[DirectMissingMethodProblem]("sbt.inc.Doc*"), - exclude[ReversedMissingMethodProblem]("sbt.inc.Doc*"), - ), - ) - .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) - .jvmPlatform(scalaVersions = scala212_213) - .configure(addBaseSettingsAndTestDeps, addSbtUtilTracking) - -// Persists the incremental data structures using Protobuf +// Persists the incremental data structures lazy val zincPersist = (projectMatrix in internalPath / "zinc-persist") - .dependsOn(zincCore, zincCompileCore, zincPersistCoreAssembly, zincCore % "test->test") + .dependsOn(zincCore, zincCompileCore, zincCore % "test->test") .settings( name := "zinc Persist", - libraryDependencies ++= Seq( - sbinary.exclude("org.scala-lang.modules", "scala-xml_" + scalaBinaryVersion.value), - scalaXml + libraryDependencies ++= List( + sbinary, + "org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.4", ), compileOrder := sbt.CompileOrder.Mixed, - Compile / scalacOptions ++= (scalaVersion.value match { - case VersionNumber(Seq(2, 12, _*), _, _) => - List("-Ywarn-unused:-imports,-locals,-implicits,-explicits,-privates") - case _ => Nil - }), Test / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.Flat, mimaSettings, mimaBinaryIssueFilters ++= ZincBuildUtil.excludeInternalProblems, @@ -309,41 +260,9 @@ lazy val zincPersist = (projectMatrix in internalPath / "zinc-persist") exclude[MissingClassProblem]("xsbti.api.InternalApiProxy") ), ) - .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) - .jvmPlatform(scalaVersions = scala212_213) + .jvmPlatform(scalaVersions = scala3_only) .configure(addBaseSettingsAndTestDeps) -lazy val zincPersistCoreAssembly = (projectMatrix in internalPath / "zinc-persist-core-assembly") - .jvmPlatform(autoScalaLibrary = false) - .settings( - name := "zinc-persist-core-assembly", - crossPaths := false, - autoScalaLibrary := false, - exportJars := true, - Compile / packageBin := (zincPersistCore / Compile / assembly).value, - mimaPreviousArtifacts := Set.empty, - ) - -lazy val zincPersistCore = (project in internalPath / "zinc-persist-core") - .enablePlugins(ProtobufPlugin) - .settings( - name := "zinc-persist-core", - crossPaths := false, - autoScalaLibrary := false, - exportJars := true, - ProtobufConfig / version := "3.25.8", - publish / skip := true, - assembly / assemblyShadeRules := Seq( - ShadeRule - .rename("com.google.protobuf.**" -> "sbt.internal.shaded.com.google.protobuf.@1") - .inAll - ), - assembly / assemblyMergeStrategy := { // remove *.proto files - case PathList(ps @ _*) if ps.last.endsWith(".proto") => MergeStrategy.discard - case x => (assembly / assemblyMergeStrategy).value(x) - }, - ) - // Implements the core functionality of detecting and propagating changes incrementally. // Defines the data structures for representing file fingerprints and relationships and the overall source analysis lazy val zincCore = (projectMatrix in internalPath / "zinc-core") @@ -352,8 +271,7 @@ lazy val zincCore = (projectMatrix in internalPath / "zinc-core") zincApiInfo, zincClasspath, compilerInterface, - zincPersistCoreAssembly, - compilerBridge % Test, + // compilerBridge % Test, zincTesting % Test ) .settings( @@ -373,18 +291,11 @@ lazy val zincCore = (projectMatrix in internalPath / "zinc-core") exclude[ReversedMissingMethodProblem]("xsbti.*"), exclude[MissingClassProblem]("xsbti.*"), ), - libraryDependencies ++= { - scalaPartialVersion.value match { - case Some((2, major)) if major >= 13 => - // should match version in sbt's util-collection module - List("org.scala-lang.modules" %% "scala-parallel-collections" % "0.2.0") - case _ => - List() - } - }, + libraryDependencies ++= List( + "org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.4" + ), ) - .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) - .jvmPlatform(scalaVersions = scala212_213) + .jvmPlatform(scalaVersions = scala3_only) .configure(addBaseSettingsAndTestDeps, addSbtIO, addSbtUtilLogging, addSbtUtilRelation) lazy val zincBenchmarks = (projectMatrix in internalPath / "zinc-benchmarks") @@ -411,8 +322,7 @@ lazy val zincBenchmarks = (projectMatrix in internalPath / "zinc-benchmarks") ) ), ) - .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) - .jvmPlatform(scalaVersions = scala212_213) + .jvmPlatform(scalaVersions = scala3_only) // sbt-side interface to compiler. Calls compiler-side interface reflectively lazy val zincCompileCore = (projectMatrix in internalPath / "zinc-compile-core") @@ -427,7 +337,7 @@ lazy val zincCompileCore = (projectMatrix in internalPath / "zinc-compile-core") .settings( name := "zinc Compile Core", libraryDependencies ++= Seq( - scalaCompiler.value % Test, + // scalaCompiler.value % Test, launcherInterface, parserCombinator, zeroAllocationHashing @@ -439,8 +349,7 @@ lazy val zincCompileCore = (projectMatrix in internalPath / "zinc-compile-core") mimaSettings, mimaBinaryIssueFilters ++= ZincBuildUtil.excludeInternalProblems, ) - .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) - .jvmPlatform(scalaVersions = List(scala212, scala213)) + .jvmPlatform(scalaVersions = scala3_only) .configure(addBaseSettingsAndTestDeps, addSbtUtilLogging, addSbtIO, addSbtUtilControl) // defines Java structures used across Scala versions, such as the API structures and relationships extracted by @@ -451,10 +360,7 @@ lazy val compilerInterface = (projectMatrix in internalPath / "compiler-interfac .settings( baseSettings, name := "Compiler Interface", - scalaVersion := scala212, - crossScalaVersions := Seq(scala212), - compilerVersionDependentScalacOptions, - libraryDependencies ++= Seq(scalaLibrary.value % Test), + scalaVersion := scala3, libraryDependencies ++= Seq(scalatest % Test), exportJars := true, Compile / resourceGenerators += Def.task { @@ -501,7 +407,6 @@ lazy val compilerInterface = (projectMatrix in internalPath / "compiler-interfac exclude[InheritedNewAbstractMethodProblem]("xsbti.InteractiveConsoleInterface.close"), ), ) - .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) .jvmPlatform(autoScalaLibrary = false) .configure(addSbtUtilInterface(_)) @@ -519,8 +424,10 @@ lazy val compilerBridge = (projectMatrix in internalPath / "compiler-bridge") .settings( name := "Compiler Bridge", autoScalaLibrary := false, + semanticdbEnabled := { + semanticdbEnabled.value && !scalaVersion.value.startsWith("2.10") + }, baseSettings, - compilerVersionDependentScalacOptions, // We need this for import Compat._ Compile / scalacOptions --= Seq("-Ywarn-unused-import", "-Xfatal-warnings"), Compile / scalacOptions ++= (scalaVersion.value match { @@ -566,11 +473,14 @@ lazy val compilerBridgeScala3Bin = (project in internalPath / "compilerBridgeSca * (Zinc API Info, which transitively depends on IO). */ lazy val compilerBridgeTest = (projectMatrix in internalPath / "compiler-bridge-test") - .dependsOn(zinc % "compile->compile;test->test", compilerInterface) + .dependsOn( + zinc3 % "compile->compile;test->test", + compilerInterface.jvm(false) + ) .settings( name := "Compiler Bridge Test", baseSettings, - compilerVersionDependentScalacOptions, + scalaVersion := scala3, // we need to fork because in unit tests we set usejavacp = true which means // we are expecting all of our dependencies to be on classpath so Scala compiler // can use them while constructing its own classpath for compilation @@ -578,11 +488,10 @@ lazy val compilerBridgeTest = (projectMatrix in internalPath / "compiler-bridge- // needed because we fork tests and tests are ran in parallel so we have multiple Scala // compiler instances that are memory hungry Test / javaOptions += "-Xmx1G", - Test / javaOptions += s"-Dzinc.build.compilerbridge.scalaVersion=${scalaVersion.value}", + Test / javaOptions += s"-Dzinc.build.compilerbridge.scalaVersion=${scala213}", publish / skip := true, ) - .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) - .jvmPlatform(scalaVersions = scala212_213) + .jvmPlatform(scalaVersions = scala3_only) val scalaPartialVersion = Def.setting(CrossVersion.partialVersion(scalaVersion.value)) @@ -591,10 +500,13 @@ def inBoth(ss: Setting[?]*): Seq[Setting[?]] = Seq(Compile, Test).flatMap(inConf // defines operations on the API of a source, including determining whether it has changed and converting it to a string // and discovery of classes and annotations lazy val zincApiInfo = (projectMatrix in internalPath / "zinc-apiinfo") - .dependsOn(compilerInterface, compilerBridge, zincClassfile % "compile;test->test") + .dependsOn( + compilerInterface, + // compilerBridge, + zincClassfile % "compile;test->test" + ) .settings( name := "zinc ApiInfo", - compilerVersionDependentScalacOptions, mimaSettings, mimaBinaryIssueFilters ++= Seq( exclude[IncompatibleMethTypeProblem]("xsbt.api.HashAPI.hashTypeParameters"), @@ -620,8 +532,7 @@ lazy val zincApiInfo = (projectMatrix in internalPath / "zinc-apiinfo") exclude[DirectMissingMethodProblem]("sbt.internal.inc.ClassToAPI.handleMalformedNameOf*"), ), ) - .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) - .jvmPlatform(scalaVersions = scala212_213) + .jvmPlatform(scalaVersions = scala3_only) .configure(addBaseSettingsAndTestDeps(_)) // Utilities related to reflection, managing Scala versions, and custom class loaders @@ -629,8 +540,10 @@ lazy val zincClasspath = (projectMatrix in internalPath / "zinc-classpath") .dependsOn(compilerInterface) .settings( name := "zinc Classpath", - compilerVersionDependentScalacOptions, - libraryDependencies ++= Seq(scalaCompiler.value, launcherInterface), + libraryDependencies ++= Seq( + // scalaCompiler.value, + launcherInterface + ), mimaSettings, mimaBinaryIssueFilters ++= Seq( // private[sbt] @@ -654,8 +567,7 @@ lazy val zincClasspath = (projectMatrix in internalPath / "zinc-classpath") exclude[IncompatibleMethTypeProblem]("sbt.internal.inc.classpath.NativeCopyConfig.*"), ), ) - .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) - .jvmPlatform(scalaVersions = scala212_213) + .jvmPlatform(scalaVersions = scala3_only) .configure(addBaseSettingsAndTestDeps, addSbtIO) // class file reader and analyzer @@ -663,7 +575,6 @@ lazy val zincClassfile = (projectMatrix in internalPath / "zinc-classfile") .dependsOn(compilerInterface, zincTesting % Test) .settings( name := "zinc Classfile", - compilerVersionDependentScalacOptions, Compile / headerSources ~= { xs => val excluded = Set("ZipCentralDir.java", "ZipConstants.java", "ZipUtils.java") xs filter { x => @@ -683,8 +594,7 @@ lazy val zincClassfile = (projectMatrix in internalPath / "zinc-classfile") ), mimaBinaryIssueFilters ++= ZincBuildUtil.excludeInternalProblems, ) - .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) - .jvmPlatform(scalaVersions = scala212_213) + .jvmPlatform(scalaVersions = scala3_only) .configure(addBaseSettingsAndTestDeps, addSbtIO, addSbtUtilLogging) // re-implementation of scripted engine @@ -698,17 +608,13 @@ lazy val zincScripted = (projectMatrix in internalPath / "zinc-scripted") Compile / buildInfo := Nil, // Only generate build info for tests BuildInfoPlugin.buildInfoScopedSettings(Test), Test / buildInfoPackage := "sbt.internal.inc", - Test / buildInfoKeys := Seq[BuildInfoKey](zinc212 / sourceDirectory), + Test / buildInfoKeys := Seq[BuildInfoKey](zinc3 / sourceDirectory), conflictWarning := ConflictWarning.disable, ) - .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) - .jvmPlatform(scalaVersions = List(scala212)) - .configure( - _.dependsOn(compilerBridge210, compilerBridge211, compilerBridge212, compilerBridge213) - ) + .jvmPlatform(scalaVersions = scala3_only) .configure(addSbtUtilScripted) -lazy val zincScripted212 = zincScripted.jvm(scala212) +lazy val zincScripted3 = zincScripted.jvm(scala3) def bridges = { if (sys.props("java.specification.version") == "1.8") { @@ -727,7 +633,7 @@ val publishBridges = taskKey[Unit]("") val crossTestBridges = taskKey[Unit]("") publishBridges := Def.task(()).dependsOn(bridges: _*).value -crossTestBridges := (compilerBridgeTest.jvm(scala213) / Test / test).dependsOn(publishBridges).value +crossTestBridges := (compilerBridgeTest.jvm(scala3) / Test / test).dependsOn(publishBridges).value addCommandAlias( "runBenchmarks", { @@ -736,8 +642,8 @@ addCommandAlias( Seq( s"${compilerBridge213.id}/packageBin", s"${compilerBridge212.id}/packageBin", - s"${zincBenchmarks.jvm(scala212).id}/Test/run $dir $pattern", - s"${zincBenchmarks.jvm(scala212).id}/jmh:run -p _tempDir=$dir -prof gc -foe true $pattern", + s"${zincBenchmarks.jvm(scala3).id}/Test/run $dir $pattern", + s"${zincBenchmarks.jvm(scala3).id}/jmh:run -p _tempDir=$dir -prof gc -foe true $pattern", s"""eval IO.delete(file("$dir"))""", ).mkString(";", ";", "") } @@ -746,11 +652,11 @@ addCommandAlias( def scriptedTask: Def.Initialize[InputTask[Unit]] = Def.inputTask { val result = scriptedSource(dir => (_: State) => scriptedParser(dir)).parsed doScripted( - (zincScripted212 / Test / fullClasspath).value, - (zincScripted212 / scalaInstance).value, + (zincScripted3 / Test / fullClasspath).value, + (zincScripted3 / scalaInstance).value, scriptedSource.value, result, scriptedBufferLog.value, scriptedCompileToJar.value, ) -} +}.dependsOn(publishBridges) diff --git a/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/ActionTest.scala b/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/ActionTest.scala index f873220166..e8b40c07a6 100644 --- a/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/ActionTest.scala +++ b/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/ActionTest.scala @@ -4,7 +4,7 @@ package inc import verify._ import sbt.io.IO.withTemporaryDirectory -import scala.collection.JavaConverters._ +import scala.jdk.CollectionConverters._ /** This is a basic test for compiler bridge, mostly wrapped as * AnalyzingCompiler. diff --git a/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/CompilingSpecification.scala b/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/CompilingSpecification.scala index fb33fd7f30..dba2224a89 100644 --- a/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/CompilingSpecification.scala +++ b/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/CompilingSpecification.scala @@ -68,7 +68,7 @@ trait CompilingSpecification extends AbstractBridgeProviderTestkit { def extractBinaryDependenciesFromSrcs(srcs: List[List[String]]): ExtractedClassDependencies = { val (_, testCallback) = compileSrcs(srcs) - val binaryDependencies = testCallback.binaryDependencies + val binaryDependencies = testCallback.binaryDependencies.toSeq ExtractedClassDependencies.fromPairs( binaryDependencies.toList.collect { case (_, bin, src, DependencyByMemberRef) => src -> bin }, binaryDependencies.toList.collect { case (_, bin, src, DependencyByInheritance) => diff --git a/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/ExtractUsedNamesPerformanceSpecification.scala b/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/ExtractUsedNamesPerformanceSpecification.scala index 8bb081df26..d649c5216f 100644 --- a/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/ExtractUsedNamesPerformanceSpecification.scala +++ b/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/ExtractUsedNamesPerformanceSpecification.scala @@ -22,7 +22,7 @@ class ExtractUsedNamesPerformanceSpecification catch { case _: FileSystemNotFoundException => val env = Map("create" -> "true") - import scala.collection.JavaConverters._ + import scala.jdk.CollectionConverters._ Option(FileSystems.newFileSystem(uri, env.asJava)) case _: IllegalArgumentException => Option(FileSystems.getDefault) @@ -59,11 +59,16 @@ class ExtractUsedNamesPerformanceSpecification catch { case _: Throwable => /*ignore*/ } } import org.scalatest.time.SpanSugar._ - val usedNames = failAfter(30 seconds) { + val usedNames = failAfter(30.seconds) { extractUsedNamesFromSrc(src) } // format: off - val expectedNamesForTupler = Set("_$3", "Tupler", "hnilTupler", "L", "Object", "Out0", "HList", "ModuleSerializationProxy", "java;lang;Object;init;", "tupler", "TuplerInstances", "DepFn1", "package", "HNil", "$anon", "Out", "T", "Aux", "scala", "Class", "Serializable", "scala;runtime;ModuleSerializationProxy;init;", "acme;Tupler;$anon;init;", "Unit") + val expectedNamesForTuplerScala2 = Set("_$3", "Tupler", "hnilTupler", "L", "Object", "Out0", "HList", "ModuleSerializationProxy", + "java;lang;Object;init;", "tupler", "TuplerInstances", "DepFn1", "package", "HNil", "$anon", "Out", "T", "Aux", "scala", "Class", + "Serializable", "scala;runtime;ModuleSerializationProxy;init;", "acme;Tupler;$anon;init;", "Unit") + val expectedNamesForTuplerScala3 = Set("$anon", "_$3", "acme;Tupler;$anon;init;", "Aux", "Class", "DepFn1", "HList", "HNil", "hnilTupler", +"java;lang;Object;init;", "L", "ModuleSerializationProxy", "Object", "Out", "Out0", "package", "scala", +"scala;runtime;ModuleSerializationProxy;init;", "Serializable", "T", "Tupler", "tupler", "TuplerInstances", "Unit") // val expectedNamesForTuplerInstances = Set("E", "Tuple4", "e", "case7", "Tuple15", "s", "case19", "T7", "x", "TuplerInstances", "matchEnd19", "T20", "Tuple11", "HNil", "matchEnd6", "p16", "$anon", "T19", "p20", "T2", "p10", "case22", "p19", "n", "Tuple12", "case11", "Tuple22", "p12", "matchEnd7", "N", "p4", "T13", "case26", "Tuple19", "p7", "p5", "j", "Out", "T", "p23", "case15", "matchEnd20", "t", "p21", "matchEnd15", "J", "head", "case13", "u", "matchEnd18", "U", "Tupler", "f", "T8", "T16", "F", "Tuple3", "case8", "case18", "case24", "Boolean", "matchEnd21", "A", "matchEnd26", "a", "Tuple14", "T1", "::", "Nothing", "p18", "case20", "m", "matchEnd10", "M", "matchEnd25", "tail", "Tuple2", "matchEnd5", "p15", "matchEnd23", "I", "i", "matchEnd14", "AnyRef", "Tuple8", "matchEnd8", "case25", "T12", "p3", "case14", "case23", "T5", "matchEnd22", "T17", "v", "p22", "Tuple18", "G", "Tuple13", "matchEnd12", "scala;MatchError;init;", "acme;TuplerInstances;$anon;init;", "java;lang;Object;init;", "V", "q", "p11", "Q", "case12", "L", "b", "apply", "Object", "g", "B", "l", "==", "Out0", "Tuple1", "matchEnd9", "P", "p2", "T15", "Aux", "matchEnd24", "p", "scala", "matchEnd11", "Tuple20", "HList", "case17", "T9", "p14", "Tuple7", "matchEnd17", "T4", "case28", "T22", "p17", "C", "Tuple6", "MatchError", "T11", "x1", "H", "case16", "matchEnd13", "c", "Tuple9", "h", "T6", "T18", "r", "K", "Tuple17", "p9", "R", "ne", "T14", "case21", "k", "case10", "Tuple21", "O", "case9", "Tuple10", "Any", "T10", "case27", "Tuple5", "D", "p13", "o", "p6", "p8", "matchEnd16", "S", "T21", "Tuple16", "d", "T3") val expectedNamesForRefinement = Set("Out0") // val `expectedNamesFor::` = Set("x", "T2", "ScalaRunTime", "Iterator", "T", "head", "asInstanceOf", "Boolean", "A", "$" + "isInstanceOf", "T1", "||", "acme;::;init;", "::", "Nothing", "x$1", "any2stringadd", "acme", "typedProductIterator", "tail", "Tuple2", "AnyRef", "isInstanceOf", "Int", "java;lang;Object;init;", "_hashCode", "apply", "Object", "x$0", "==", "Some", "IndexOutOfBoundsException", "java;lang;IndexOutOfBoundsException;init;", "T0", "Predef", "scala", "matchEnd4", "HList", "None", "x1", "toString", "H", "+", "&&", "Serializable", "Product", "case6", "::$1", "eq", "Any", "runtime", "String") @@ -72,7 +77,7 @@ class ExtractUsedNamesPerformanceSpecification val expectedNamesForHList = Set("Tupler", "acme", "scala", "Serializable", "Product") // format: on - assert(diffAndSort(usedNames("acme.Tupler")) === diffAndSort(expectedNamesForTupler)) + assert(diffAndSort(usedNames("acme.Tupler")) === diffAndSort(expectedNamesForTuplerScala3)) assert( diffAndSort(usedNames("acme.TuplerInstances.")) === diffAndSort( expectedNamesForRefinement diff --git a/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/InteractiveConsoleInterfaceSpecification.scala b/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/InteractiveConsoleInterfaceSpecification.scala index 35411584ee..cd5dc43019 100644 --- a/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/InteractiveConsoleInterfaceSpecification.scala +++ b/internal/compiler-bridge-test/src/test/scala/sbt/internal/inc/InteractiveConsoleInterfaceSpecification.scala @@ -7,6 +7,7 @@ import sbt.io.IO import xsbti.InteractiveConsoleResult // This is a specification to check the REPL block parsing. +/* object InteractiveConsoleInterfaceSpecification extends BasicTestSuite with BridgeProviderTestkit @@ -66,3 +67,4 @@ object InteractiveConsoleInterfaceSpecification } } + */ diff --git a/internal/compiler-interface/src/main/contraband-java/xsbti/api/AnalyzedClass.java b/internal/compiler-interface/src/main/contraband-java/xsbti/api/AnalyzedClass.java index f931ba0d76..4a664649af 100644 --- a/internal/compiler-interface/src/main/contraband-java/xsbti/api/AnalyzedClass.java +++ b/internal/compiler-interface/src/main/contraband-java/xsbti/api/AnalyzedClass.java @@ -24,6 +24,12 @@ public static AnalyzedClass create(long _compilationTimestamp, String _name, xsb public static AnalyzedClass of(long _compilationTimestamp, String _name, xsbti.api.Lazy _api, int _apiHash, NameHash[] _nameHashes, boolean _hasMacro, int _extraHash, String _provenance) { return new AnalyzedClass(_compilationTimestamp, _name, _api, _apiHash, _nameHashes, _hasMacro, _extraHash, _provenance); } + public static AnalyzedClass create(long _compilationTimestamp, String _name, xsbti.api.Lazy _api, int _apiHash, NameHash[] _nameHashes, boolean _hasMacro, int _extraHash, String _provenance, long _bytecodeHash, long _transitiveBytecodeHash) { + return new AnalyzedClass(_compilationTimestamp, _name, _api, _apiHash, _nameHashes, _hasMacro, _extraHash, _provenance, _bytecodeHash, _transitiveBytecodeHash); + } + public static AnalyzedClass of(long _compilationTimestamp, String _name, xsbti.api.Lazy _api, int _apiHash, NameHash[] _nameHashes, boolean _hasMacro, int _extraHash, String _provenance, long _bytecodeHash, long _transitiveBytecodeHash) { + return new AnalyzedClass(_compilationTimestamp, _name, _api, _apiHash, _nameHashes, _hasMacro, _extraHash, _provenance, _bytecodeHash, _transitiveBytecodeHash); + } private long compilationTimestamp; private String name; private xsbti.api.Lazy api; @@ -32,6 +38,8 @@ public static AnalyzedClass of(long _compilationTimestamp, String _name, xsbti.a private boolean hasMacro; private int extraHash; private String provenance; + private long bytecodeHash; + private long transitiveBytecodeHash; protected AnalyzedClass(long _compilationTimestamp, String _name, xsbti.api.Lazy _api, int _apiHash, NameHash[] _nameHashes, boolean _hasMacro) { super(); compilationTimestamp = _compilationTimestamp; @@ -42,6 +50,8 @@ protected AnalyzedClass(long _compilationTimestamp, String _name, xsbti.api.Lazy hasMacro = _hasMacro; extraHash = apiHash; provenance = ""; + bytecodeHash = 0; + transitiveBytecodeHash = 0; } protected AnalyzedClass(long _compilationTimestamp, String _name, xsbti.api.Lazy _api, int _apiHash, NameHash[] _nameHashes, boolean _hasMacro, int _extraHash) { super(); @@ -53,6 +63,8 @@ protected AnalyzedClass(long _compilationTimestamp, String _name, xsbti.api.Lazy hasMacro = _hasMacro; extraHash = _extraHash; provenance = ""; + bytecodeHash = 0; + transitiveBytecodeHash = 0; } protected AnalyzedClass(long _compilationTimestamp, String _name, xsbti.api.Lazy _api, int _apiHash, NameHash[] _nameHashes, boolean _hasMacro, int _extraHash, String _provenance) { super(); @@ -64,6 +76,21 @@ protected AnalyzedClass(long _compilationTimestamp, String _name, xsbti.api.Lazy hasMacro = _hasMacro; extraHash = _extraHash; provenance = _provenance; + bytecodeHash = 0; + transitiveBytecodeHash = 0; + } + protected AnalyzedClass(long _compilationTimestamp, String _name, xsbti.api.Lazy _api, int _apiHash, NameHash[] _nameHashes, boolean _hasMacro, int _extraHash, String _provenance, long _bytecodeHash, long _transitiveBytecodeHash) { + super(); + compilationTimestamp = _compilationTimestamp; + name = _name; + api = _api; + apiHash = _apiHash; + nameHashes = _nameHashes; + hasMacro = _hasMacro; + extraHash = _extraHash; + provenance = _provenance; + bytecodeHash = _bytecodeHash; + transitiveBytecodeHash = _transitiveBytecodeHash; } public long compilationTimestamp() { @@ -95,29 +122,43 @@ public int extraHash() { public String provenance() { return this.provenance; } + /** A hash of generated bytecode of source file hosting the class */ + public long bytecodeHash() { + return this.bytecodeHash; + } + /** A hash of generated bytecode of all upstream dependencies */ + public long transitiveBytecodeHash() { + return this.transitiveBytecodeHash; + } public AnalyzedClass withCompilationTimestamp(long compilationTimestamp) { - return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance); + return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance, bytecodeHash, transitiveBytecodeHash); } public AnalyzedClass withName(String name) { - return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance); + return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance, bytecodeHash, transitiveBytecodeHash); } public AnalyzedClass withApi(xsbti.api.Lazy api) { - return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance); + return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance, bytecodeHash, transitiveBytecodeHash); } public AnalyzedClass withApiHash(int apiHash) { - return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance); + return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance, bytecodeHash, transitiveBytecodeHash); } public AnalyzedClass withNameHashes(NameHash[] nameHashes) { - return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance); + return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance, bytecodeHash, transitiveBytecodeHash); } public AnalyzedClass withHasMacro(boolean hasMacro) { - return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance); + return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance, bytecodeHash, transitiveBytecodeHash); } public AnalyzedClass withExtraHash(int extraHash) { - return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance); + return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance, bytecodeHash, transitiveBytecodeHash); } public AnalyzedClass withProvenance(String provenance) { - return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance); + return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance, bytecodeHash, transitiveBytecodeHash); + } + public AnalyzedClass withBytecodeHash(long bytecodeHash) { + return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance, bytecodeHash, transitiveBytecodeHash); + } + public AnalyzedClass withTransitiveBytecodeHash(long transitiveBytecodeHash) { + return new AnalyzedClass(compilationTimestamp, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance, bytecodeHash, transitiveBytecodeHash); } public boolean equals(Object obj) { return this == obj; // We have lazy members, so use object identity to avoid circularity. diff --git a/internal/compiler-interface/src/main/contraband/other.json b/internal/compiler-interface/src/main/contraband/other.json index d344ddb0ac..281320b8ac 100644 --- a/internal/compiler-interface/src/main/contraband/other.json +++ b/internal/compiler-interface/src/main/contraband/other.json @@ -28,6 +28,24 @@ "Combined with a way to tell if the provenance has changed,", "it can be used to short-circuit the 'lookupAnalyzedClass' operation." ] + }, + { + "name": "bytecodeHash", + "type": "long", + "default": "0", + "since": "2.0.0", + "doc": [ + "A hash of generated bytecode of source file hosting the class" + ] + }, + { + "name": "transitiveBytecodeHash", + "type": "long", + "default": "0", + "since": "2.0.0", + "doc": [ + "A hash of generated bytecode of all upstream dependencies" + ] } ] }, diff --git a/internal/compiler-interface/src/main/java/xsbti/BasicHashedVirtualFileRef.java b/internal/compiler-interface/src/main/java/xsbti/BasicHashedVirtualFileRef.java new file mode 100644 index 0000000000..a4ab7cb4be --- /dev/null +++ b/internal/compiler-interface/src/main/java/xsbti/BasicHashedVirtualFileRef.java @@ -0,0 +1,52 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright Scala Center, Lightbend, and Mark Harrah + * + * Licensed under Apache License 2.0 + * SPDX-License-Identifier: Apache-2.0 + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package xsbti; + +import java.util.Objects; + +public class BasicHashedVirtualFileRef + extends BasicVirtualFileRef + implements HashedVirtualFileRef { + private final String contentHashStr; + private final long sizeBytes; + + protected BasicHashedVirtualFileRef(String id, String contentHashStr, long sizeBytes) { + super(id); + this.contentHashStr = contentHashStr; + this.sizeBytes = sizeBytes; + } + + public String contentHashStr() { return contentHashStr; } + + public long sizeBytes() { return sizeBytes; } + + public String toString() { return id() + ">" + contentHashStr + "/" + Long.toString(sizeBytes); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BasicHashedVirtualFileRef)) return false; + BasicHashedVirtualFileRef that = (BasicHashedVirtualFileRef) o; + return Objects.equals(id(), that.id()) && + Objects.equals(contentHashStr, that.contentHashStr) && + (sizeBytes == that.sizeBytes); + } + + @Override + public int hashCode() { + return Objects.hash( + "xsbti.BasicHashedVirtualFileRef", + id(), + contentHashStr, + Long.valueOf(sizeBytes) + ); } +} diff --git a/internal/compiler-interface/src/main/java/xsbti/HashedVirtualFileRef.java b/internal/compiler-interface/src/main/java/xsbti/HashedVirtualFileRef.java new file mode 100644 index 0000000000..253c687b10 --- /dev/null +++ b/internal/compiler-interface/src/main/java/xsbti/HashedVirtualFileRef.java @@ -0,0 +1,30 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright Scala Center, Lightbend, and Mark Harrah + * + * Licensed under Apache License 2.0 + * SPDX-License-Identifier: Apache-2.0 + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package xsbti; + +/** + * HashedVirtualFileRef represents a virtual file reference + * with content hash. + */ +public interface HashedVirtualFileRef extends VirtualFileRef { + // TODO: remove this + static HashedVirtualFileRef of(String id, String contentHashStr) { + return new BasicHashedVirtualFileRef(id, contentHashStr, 0L); + } + + static HashedVirtualFileRef of(String id, String contentHashStr, long sizeBytes) { + return new BasicHashedVirtualFileRef(id, contentHashStr, sizeBytes); + } + + String contentHashStr(); + long sizeBytes(); +} diff --git a/internal/compiler-interface/src/main/java/xsbti/VirtualFile.java b/internal/compiler-interface/src/main/java/xsbti/VirtualFile.java index 87d6ca3d15..27ea9b1e0b 100644 --- a/internal/compiler-interface/src/main/java/xsbti/VirtualFile.java +++ b/internal/compiler-interface/src/main/java/xsbti/VirtualFile.java @@ -45,7 +45,7 @@ * which extends scala.reflect.io.AbstractFile, * which the compiler is able to compile. */ -public interface VirtualFile extends VirtualFileRef { +public interface VirtualFile extends HashedVirtualFileRef { long contentHash(); InputStream input(); } diff --git a/internal/zinc-apiinfo/src/main/scala/xsbt/api/HashAPI.scala b/internal/zinc-apiinfo/src/main/scala/xsbt/api/HashAPI.scala index 90349cac35..005e27bc6a 100644 --- a/internal/zinc-apiinfo/src/main/scala/xsbt/api/HashAPI.scala +++ b/internal/zinc-apiinfo/src/main/scala/xsbt/api/HashAPI.scala @@ -143,7 +143,7 @@ final class HashAPI private ( i += 1 } } - final def hashSymmetric[T](ts: TraversableOnce[T], hashF: T => Unit): Unit = { + final def hashSymmetric[T](ts: IterableOnce[T], hashF: T => Unit): Unit = { val current = hash val tsHash: Hash = ts match { case ts: collection.Iterable[T] => @@ -218,12 +218,12 @@ final class HashAPI private ( * * NOTE: This method doesn't perform any filtering of passed definitions. */ - def hashDefinitionsWithExtraHash(ds: TraversableOnce[Definition], extraHash: Hash): Unit = { + def hashDefinitionsWithExtraHash(ds: IterableOnce[Definition], extraHash: Hash): Unit = { def hashDefinitionCombined(d: Definition): Unit = { hashDefinition(d) extend(extraHash) } - hashSymmetric(ds, hashDefinitionCombined _) + hashSymmetric(ds, hashDefinitionCombined) } def hashDefinition(d: Definition): Unit = { hashString(d.name) diff --git a/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassCanonicalNameSpec.scala b/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassCanonicalNameSpec.scala index fa155f6894..173fb9cffe 100644 --- a/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassCanonicalNameSpec.scala +++ b/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassCanonicalNameSpec.scala @@ -55,16 +55,16 @@ class ClassCanonicalNameSpec extends AnyFlatSpec with Matchers with Diagrams { check[p1.x.y.type](OO) check[p2.x.y](OC) - check[c1.y.type forSome { val c1: p3.x }](CO) + // check[c1.y.type forSome { val c1: p3.x }](CO) check[p4.x#y](CC) check[p1.x.y.z.type](OOO) check[p1.x.y.z](OOC) - check[c2.z.type forSome { val c2: p2.x.y }](OCO) + // check[c2.z.type forSome { val c2: p2.x.y }](OCO) check[p2.x.y#z](OCC) - check[c1.y.z.type forSome { val c1: p3.x }](COO) - check[c1.y.z forSome { val c1: p3.x }](COC) - check[c2.z.type forSome { val c2: p4.x#y }](CCO) + // check[c1.y.z.type forSome { val c1: p3.x }](COO) + // check[c1.y.z forSome { val c1: p3.x }](COC) + // check[c2.z.type forSome { val c2: p4.x#y }](CCO) check[p4.x#y#z](CCC) // Now again, but calling getClass on an instance instead diff --git a/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassToAPISpecification.scala b/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassToAPISpecification.scala index 73f91f779d..8bf9f4cc9a 100644 --- a/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassToAPISpecification.scala +++ b/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassToAPISpecification.scala @@ -60,7 +60,7 @@ class ClassToAPISpecification extends UnitSpec { val (Seq(tempSrcFile), analysisCallback) = JavaCompilerForUnitTesting.compileJavaSrcs(src)(readAPI) val apis = analysisCallback.apis(tempSrcFile) - apis.groupBy(_.name).map((companions _).tupled).toSet + apis.groupBy(_.name).map(companions.tupled).toSet } private def companions(className: String, classes: Set[ClassLike]): Companions = { diff --git a/internal/zinc-apiinfo/src/test/scala/xsbt/api/ClassLikeHelpers.scala b/internal/zinc-apiinfo/src/test/scala/xsbt/api/ClassLikeHelpers.scala index 38347bc6b4..21a86df644 100644 --- a/internal/zinc-apiinfo/src/test/scala/xsbt/api/ClassLikeHelpers.scala +++ b/internal/zinc-apiinfo/src/test/scala/xsbt/api/ClassLikeHelpers.scala @@ -20,17 +20,17 @@ object ClassLikeHelpers { Structure.of(lzy(Array.empty[Type]), lzy(defs.toArray), emptyMembers) def simpleTrait(name: String, defs: List[ClassDefinition]): ClassLike = { - val structure = simpleStructure(defs: _*) + val structure = simpleStructure(defs*) simpleClassLike(name, structure, dt = DefinitionType.Trait) } def simpleClass(name: String, defs: ClassDefinition*): ClassLike = { - val structure = simpleStructure(defs: _*) + val structure = simpleStructure(defs*) simpleClassLike(name, structure) } def simpleObject(name: String, defs: ClassDefinition*): ClassLike = { - val structure = simpleStructure(defs: _*) + val structure = simpleStructure(defs*) simpleClassLike(name, structure, dt = DefinitionType.Module) } diff --git a/internal/zinc-benchmarks/src/test/scala/xsbt/AnalysisFormatBenchmark.scala b/internal/zinc-benchmarks/src/test/scala/xsbt/AnalysisFormatBenchmark.scala index eb54d69c2b..3991175343 100644 --- a/internal/zinc-benchmarks/src/test/scala/xsbt/AnalysisFormatBenchmark.scala +++ b/internal/zinc-benchmarks/src/test/scala/xsbt/AnalysisFormatBenchmark.scala @@ -46,7 +46,7 @@ class AnalysisFormatBenchmark { IO.copyFile(f, f2) assert(f2.exists()) } - this.cached = readAll("", FileAnalysisStore.binary(_)) + this.cached = readAll("", FileAnalysisStore.text(_)) writeAll("-ref-text", FileAnalysisStore.text(_), cached) // writeAll("-ref-ctext", ConsistentFileAnalysisStore.text(_, ReadWriteMappers.getEmptyMappers), cached) writeAll( diff --git a/internal/zinc-benchmarks/src/test/scala/xsbt/GlobalBenchmarkSetup.scala b/internal/zinc-benchmarks/src/test/scala/xsbt/GlobalBenchmarkSetup.scala index e7dfd8401a..44c5fc24de 100644 --- a/internal/zinc-benchmarks/src/test/scala/xsbt/GlobalBenchmarkSetup.scala +++ b/internal/zinc-benchmarks/src/test/scala/xsbt/GlobalBenchmarkSetup.scala @@ -22,7 +22,7 @@ object GlobalBenchmarkSetup { def runSetup(setupDir: File, pattern: String): (Int, String) = { val projectsPreparation = projects - .filterKeys { _.matches(pattern) } + .view.filterKeys { _.matches(pattern) } .map { case (_, project) => val benchmark = new ZincBenchmark(project) project -> benchmark.writeSetup(new File(setupDir, project.repo)) diff --git a/internal/zinc-classfile/src/main/scala/sbt/internal/inc/IndexBasedZipFsOps.scala b/internal/zinc-classfile/src/main/scala/sbt/internal/inc/IndexBasedZipFsOps.scala index 7759af62c8..5706a55f10 100644 --- a/internal/zinc-classfile/src/main/scala/sbt/internal/inc/IndexBasedZipFsOps.scala +++ b/internal/zinc-classfile/src/main/scala/sbt/internal/inc/IndexBasedZipFsOps.scala @@ -16,7 +16,7 @@ import java.nio.file.Path import sbt.internal.inc.zip.ZipCentralDir -import scala.collection.JavaConverters._ +import scala.jdk.CollectionConverters._ import scala.collection.immutable.Seq /** diff --git a/internal/zinc-classfile/src/main/scala/sbt/internal/inc/classfile/ClassFile.scala b/internal/zinc-classfile/src/main/scala/sbt/internal/inc/classfile/ClassFile.scala index 83b5e0802d..6c0a80f1d6 100644 --- a/internal/zinc-classfile/src/main/scala/sbt/internal/inc/classfile/ClassFile.scala +++ b/internal/zinc-classfile/src/main/scala/sbt/internal/inc/classfile/ClassFile.scala @@ -27,7 +27,7 @@ private[sbt] trait ClassFile { val fields: Array[FieldOrMethodInfo] val methods: Array[FieldOrMethodInfo] val attributes: Array[AttributeInfo] - val sourceFile: Option[String] + def sourceFile: Option[String] def types: Set[String] def stringValue(a: AttributeInfo): String diff --git a/internal/zinc-classfile/src/main/scala/sbt/internal/inc/classfile/JavaAnalyze.scala b/internal/zinc-classfile/src/main/scala/sbt/internal/inc/classfile/JavaAnalyze.scala index 28eb16f4b4..892d7b1721 100644 --- a/internal/zinc-classfile/src/main/scala/sbt/internal/inc/classfile/JavaAnalyze.scala +++ b/internal/zinc-classfile/src/main/scala/sbt/internal/inc/classfile/JavaAnalyze.scala @@ -71,7 +71,7 @@ private[sbt] object JavaAnalyze { classFile val sourceToClassFiles = mutable.HashMap[VirtualFile, Buffer[ClassFile]]( - sources.map(vf => vf -> new ArrayBuffer[ClassFile]): _* + sources.map(vf => vf -> new ArrayBuffer[ClassFile])* ) val binaryClassNameToLoadedClass = new mutable.HashMap[String, Class[?]] diff --git a/internal/zinc-classfile/src/main/scala/sbt/internal/inc/classfile/Parser.scala b/internal/zinc-classfile/src/main/scala/sbt/internal/inc/classfile/Parser.scala index 28f560a00f..789c6476d5 100644 --- a/internal/zinc-classfile/src/main/scala/sbt/internal/inc/classfile/Parser.scala +++ b/internal/zinc-classfile/src/main/scala/sbt/internal/inc/classfile/Parser.scala @@ -80,7 +80,7 @@ private[sbt] object Parser { val attributes = array(in.readUnsignedShort())(parseAttribute()) - lazy val sourceFile = + override lazy val sourceFile: Option[String] = for (sourceFileAttribute <- attributes.find(_.isSourceFile)) yield toUTF8(entryIndex(sourceFileAttribute)) diff --git a/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/IndexBasedZipFsOpsSpec.scala b/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/IndexBasedZipFsOpsSpec.scala index 7080ba7e89..db86527aed 100644 --- a/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/IndexBasedZipFsOpsSpec.scala +++ b/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/IndexBasedZipFsOpsSpec.scala @@ -14,7 +14,7 @@ package classfile import java.nio.file._ import java.nio.file.spi.FileSystemProvider -import scala.collection.JavaConverters._ +import scala.jdk.CollectionConverters._ class IndexBasedZipFsOpsSpec extends UnitSpec { private val XL = 0xffff // minimum size to be zip64, which I'm calling "XL" diff --git a/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/JavaCompilerForUnitTesting.scala b/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/JavaCompilerForUnitTesting.scala index 08ca817704..f43f828840 100644 --- a/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/JavaCompilerForUnitTesting.scala +++ b/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/JavaCompilerForUnitTesting.scala @@ -26,16 +26,18 @@ import xsbti.{ AnalysisCallback, BasicVirtualFileRef, TestCallback, VirtualFile, import xsbti.TestCallback.ExtractedClassDependencies import xsbti.compile.SingleOutput -import scala.collection.JavaConverters._ +import scala.jdk.CollectionConverters._ object JavaCompilerForUnitTesting { private class TestVirtualFile(p: Path) extends BasicVirtualFileRef(p.toString) with VirtualFile { override def contentHash(): Long = sbt.io.Hash(p.toFile).hashCode.toLong + override def sizeBytes: Long = Files.size(p) + override lazy val contentHashStr: String = contentHash().toHexString override def input(): InputStream = Files.newInputStream(p) } def extractDependenciesFromSrcs(srcs: (String, String)*): ExtractedClassDependencies = { - val (_, testCallback) = compileJavaSrcs(srcs: _*)((_, _, classes) => extractParents(classes)) + val (_, testCallback) = compileJavaSrcs(srcs*)((_, _, classes) => extractParents(classes)) val memberRefDeps = testCallback.classDependencies .collect({ diff --git a/internal/zinc-classpath/src/main/scala/sbt/internal/inc/ReflectUtilities.scala b/internal/zinc-classpath/src/main/scala/sbt/internal/inc/ReflectUtilities.scala index 85bdb0e324..c46fa13f5a 100644 --- a/internal/zinc-classpath/src/main/scala/sbt/internal/inc/ReflectUtilities.scala +++ b/internal/zinc-classpath/src/main/scala/sbt/internal/inc/ReflectUtilities.scala @@ -37,7 +37,7 @@ object ReflectUtilities { else clazz :: ancestry(clazz.getSuperclass) def fields(clazz: Class[?]): mutable.Map[String, Field] = - mutable.HashMap(ancestry(clazz).flatMap(_.getDeclaredFields).map(f => (f.getName, f)): _*) + mutable.AnyRefMap(ancestry(clazz).flatMap(_.getDeclaredFields).map(f => (f.getName, f))*) /** * Collects all `val`s of type `T` defined on value `self`. diff --git a/internal/zinc-classpath/src/main/scala/sbt/internal/inc/classpath/ClassLoaders.scala b/internal/zinc-classpath/src/main/scala/sbt/internal/inc/classpath/ClassLoaders.scala index fde68b471f..24148976ab 100644 --- a/internal/zinc-classpath/src/main/scala/sbt/internal/inc/classpath/ClassLoaders.scala +++ b/internal/zinc-classpath/src/main/scala/sbt/internal/inc/classpath/ClassLoaders.scala @@ -108,7 +108,7 @@ final class ClasspathFilter(parent: ClassLoader, root: ClassLoader, classpath: S } override def getResources(name: String): java.util.Enumeration[URL] = { - import scala.collection.JavaConverters._ + import scala.jdk.CollectionConverters._ val us = super.getResources(name) if (us ne null) us.asScala.filter(onClasspath).asJavaEnumeration else null } diff --git a/internal/zinc-classpath/src/main/scala/sbt/internal/inc/classpath/ClasspathUtilities.scala b/internal/zinc-classpath/src/main/scala/sbt/internal/inc/classpath/ClasspathUtilities.scala index aea685817d..0f58414cc0 100644 --- a/internal/zinc-classpath/src/main/scala/sbt/internal/inc/classpath/ClasspathUtilities.scala +++ b/internal/zinc-classpath/src/main/scala/sbt/internal/inc/classpath/ClasspathUtilities.scala @@ -151,7 +151,7 @@ object ClasspathUtil { /** Returns all entries in 'classpath' that correspond to a compiler plugin.*/ private[sbt] def compilerPlugins(classpath: Seq[Path], isDotty: Boolean): Iterable[Path] = { - import collection.JavaConverters._ + import scala.jdk.CollectionConverters._ val loader = new URLClassLoader(toURLs(classpath).toArray) val metaFile = if (isDotty) "plugin.properties" else "scalac-plugin.xml" loader.getResources(metaFile).asScala.toList.flatMap(asFile(true)) diff --git a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/AnalyzingCompiler.scala b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/AnalyzingCompiler.scala index b9f0cc9b05..5329a51f45 100644 --- a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/AnalyzingCompiler.scala +++ b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/AnalyzingCompiler.scala @@ -311,7 +311,7 @@ final class AnalyzingCompiler( // see https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html private def loadService[A](cls: Class[A], loader: ClassLoader): Option[A] = { - import scala.collection.JavaConverters._ + import scala.jdk.CollectionConverters._ val sl = ServiceLoader.load(cls, loader) val list = sl.iterator.asScala.toList list.lastOption @@ -325,8 +325,8 @@ final class AnalyzingCompiler( private def invoke(bridge: AnyRef, bridgeClass: Class[?], methodName: String, log: Logger)( argTypes: Class[?]* )(args: AnyRef*): AnyRef = { - val method = bridgeClass.getMethod(methodName, argTypes: _*) - try method.invoke(bridge, args: _*) + val method = bridgeClass.getMethod(methodName, argTypes*) + try method.invoke(bridge, args*) catch { case e: InvocationTargetException => e.getCause match { diff --git a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/BasicVirtualDirectory.scala b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/BasicVirtualDirectory.scala index 6bbea75258..337cdf8925 100644 --- a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/BasicVirtualDirectory.scala +++ b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/BasicVirtualDirectory.scala @@ -37,6 +37,8 @@ object BasicVirtualDirectory { class BasicMemoryFile(val name: String, parent: VirtualDirectory) extends VirtualFileWrite { private[this] val byteArray = new ByteArrayOutputStream() override def contentHash: Long = HashUtil.farmHash(byteArray.toByteArray()) + override def sizeBytes: Long = byteArray.toByteArray().size + override lazy val contentHashStr: String = HashUtil.sha256HashStr(input) override def input: InputStream = new ByteArrayInputStream(byteArray.toByteArray()) override def output: OutputStream = byteArray override def id: String = s"$parent$name" diff --git a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/CompilerArguments.scala b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/CompilerArguments.scala index c6834ada4f..1ad475e421 100644 --- a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/CompilerArguments.scala +++ b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/CompilerArguments.scala @@ -89,9 +89,9 @@ final class CompilerArguments( def finishClasspath(classpath: Seq[Path]): Seq[Path] = { val filteredClasspath = filterLibrary(classpath) val extraCompiler = - include(cpOptions.compiler, scalaInstance.compilerJars.toIndexedSeq.map(_.toPath): _*) + include(cpOptions.compiler, scalaInstance.compilerJars.toIndexedSeq.map(_.toPath)*) val otherJars = scalaInstance.otherJars.toList.map(_.toPath) - val extraClasspath = include(cpOptions.extra, otherJars: _*) + val extraClasspath = include(cpOptions.extra, otherJars*) filteredClasspath ++ extraCompiler ++ extraClasspath } @@ -104,7 +104,7 @@ final class CompilerArguments( */ def createBootClasspath(addLibrary: Boolean): String = { def findBoot: String = { - import scala.collection.JavaConverters._ + import scala.jdk.CollectionConverters._ System.getProperties.asScala.iterator .collectFirst { case (k, v) if k.endsWith(".boot.class.path") => v diff --git a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/FilteredReporter.scala b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/FilteredReporter.scala index 2312de34a5..d34076faf0 100644 --- a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/FilteredReporter.scala +++ b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/FilteredReporter.scala @@ -36,8 +36,8 @@ class ManagedFilteredReporter( logger: ManagedLogger, positionMapper: Position => Position ) extends FilteredReporter(fileFilters, msgFilters, maximumErrors, logger, positionMapper) { - import LoggedReporter.problemFormats._ - import LoggedReporter.problemStringFormats._ + import LoggedReporter.problemFormats.given + import LoggedReporter.problemStringFormats.given logger.registerStringCodec[Problem] override def logError(problem: Problem): Unit = logger.errorEvent(problem) diff --git a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/HashUtil.scala b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/HashUtil.scala index b4dd38321f..2e22cd2426 100644 --- a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/HashUtil.scala +++ b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/HashUtil.scala @@ -15,9 +15,14 @@ package inc import net.openhft.hashing.LongHashFunction +import java.io.{ BufferedInputStream, InputStream } import java.nio.file.{ Files, Path } +import sbt.io.Hash object HashUtil { + def toFarmHashString(digest: Long): String = + s"farm64-${digest.toHexString}" + def farmHash(bytes: Array[Byte]): Long = LongHashFunction.farmNa().hashBytes(bytes) @@ -33,4 +38,23 @@ object HashUtil { else farmHash(Hash(path.toFile)) } + + def sha256Hash(input: InputStream): Array[Byte] = { + val BufferSize = 8192 + import java.security.{ DigestInputStream, MessageDigest } + val bis = new BufferedInputStream(input) + val digest = MessageDigest.getInstance("SHA-256") + try { + val dis = new DigestInputStream(bis, digest) + val buffer = new Array[Byte](BufferSize) + while (dis.read(buffer) >= 0) {} + dis.close() + digest.digest + } finally { + bis.close() + } + } + + def sha256HashStr(input: InputStream): String = + "sha256-" + Hash.toHex(sha256Hash(input)) } diff --git a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/LoggedReporter.scala b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/LoggedReporter.scala index 5fcfbd3639..03f4948a96 100644 --- a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/LoggedReporter.scala +++ b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/LoggedReporter.scala @@ -79,8 +79,8 @@ class ManagedLoggedReporter( logger: ManagedLogger, sourcePositionMapper: Position => Position = identity[Position] ) extends LoggedReporter(maximumErrors, logger, sourcePositionMapper) { - import problemFormats._ - import problemStringFormats._ + import problemFormats.given + import problemStringFormats.given logger.registerStringCodec[Problem] override def logError(problem: Problem): Unit = logger.errorEvent(problem) diff --git a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/PlainVirtualFile.scala b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/PlainVirtualFile.scala index 15ad86c1eb..3e27a070da 100644 --- a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/PlainVirtualFile.scala +++ b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/PlainVirtualFile.scala @@ -19,6 +19,8 @@ import xsbti.{ BasicVirtualFileRef, FileConverter, PathBasedFile, VirtualFileRef class PlainVirtualFile(path: Path) extends BasicVirtualFileRef(path.toString) with PathBasedFile { override def contentHash: Long = HashUtil.farmHash(path) + override def sizeBytes: Long = Files.size(path) + override lazy val contentHashStr: String = HashUtil.sha256HashStr(input) override def name(): String = path.getFileName.toString override def input(): InputStream = Files.newInputStream(path) override def toPath: Path = path diff --git a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/RawCompiler.scala b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/RawCompiler.scala index b22165f439..ce993e725b 100644 --- a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/RawCompiler.scala +++ b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/RawCompiler.scala @@ -60,7 +60,7 @@ class RawCompiler(val scalaInstance: XScalaInstance, cp: ClasspathOptions, log: } // Make sure that methods exist so that reflection is safe (trick) - import scala.tools.nsc.Main.{ process => _, reporter => _ } + // import scala.tools.nsc.Main.{ process => _, reporter => _ } val uniqueCompilerVersion = scalaInstance.actualVersion val compilerOut = Some(outputDirectory) val arguments = compilerArguments.makeArguments(sources, classpath, compilerOut, options) diff --git a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/StringVirtualFile.scala b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/StringVirtualFile.scala index 991e1dfd47..86644821ca 100644 --- a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/StringVirtualFile.scala +++ b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/StringVirtualFile.scala @@ -21,6 +21,8 @@ case class StringVirtualFile(path: String, content: String) extends BasicVirtualFileRef(path) with VirtualFile { override def contentHash: Long = HashUtil.farmHash(content.getBytes("UTF-8")) + override def sizeBytes: Long = content.getBytes("UTF-8").size + override lazy val contentHashStr: String = HashUtil.sha256HashStr(input) override def input: InputStream = new ByteArrayInputStream(content.getBytes("UTF-8")) override def toString: String = s"StringVirtualFile($path, )" } diff --git a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/javac/ForkedJava.scala b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/javac/ForkedJava.scala index 6a6fb039d2..7472690066 100644 --- a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/javac/ForkedJava.scala +++ b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/javac/ForkedJava.scala @@ -78,7 +78,7 @@ object ForkedJava { } } // javac's argument file seems to allow naive space escaping with quotes. escaping a quote with a backslash does not work - private def escapeSpaces(s: String): String = '\"' + normalizeSlash(s) + '\"' + private def escapeSpaces(s: String): String = s"\"${normalizeSlash(s)}\"" private def normalizeSlash(s: String) = s.replace(File.separatorChar, '/') /** create the executable name for java */ diff --git a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/javac/LocalJava.scala b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/javac/LocalJava.scala index b305a053dd..cc8596a129 100644 --- a/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/javac/LocalJava.scala +++ b/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/javac/LocalJava.scala @@ -38,7 +38,7 @@ import javax.tools.{ import sbt.internal.util.LoggerWriter import sbt.util.{ Level, Logger } -import scala.collection.JavaConverters._ +import scala.jdk.CollectionConverters._ import scala.util.control.NonFatal import xsbti.{ Reporter, Logger => XLogger, PathBasedFile, VirtualFile, VirtualFileRef } import xsbti.compile.{ @@ -128,7 +128,7 @@ object LocalJava { ): Int = javadocTool match { case Some(m) => - m.run(in, out, err, args: _*) + m.run(in, out, err, args*) case _ => System.err.println(JavadocFailure) -1 diff --git a/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/javac/JavaCompilerSpec.scala b/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/javac/JavaCompilerSpec.scala index 63eefd4bd6..601e88e5be 100644 --- a/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/javac/JavaCompilerSpec.scala +++ b/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/javac/JavaCompilerSpec.scala @@ -185,7 +185,7 @@ class JavaCompilerSpec extends UnitSpec with Diagrams { val leftAPI = compileWithPrimitive(leftType, left) val rightAPI = compileWithPrimitive(rightType, right) assert(leftAPI.size == rightAPI.size) - assert(((leftAPI, rightAPI).zipped forall SameAPI.apply) == (left == right)) + assert(leftAPI.lazyZip(rightAPI).forall(SameAPI.apply) == (left == right)) () } diff --git a/internal/zinc-core/src/main/scala-2.12/sbt/internal/inc/WrappedSet.scala b/internal/zinc-core/src/main/scala-2.12/sbt/internal/inc/WrappedSet.scala deleted file mode 100644 index 75177061dc..0000000000 --- a/internal/zinc-core/src/main/scala-2.12/sbt/internal/inc/WrappedSet.scala +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Zinc - The incremental compiler for Scala. - * Copyright Scala Center, Lightbend, and Mark Harrah - * - * Licensed under Apache License 2.0 - * SPDX-License-Identifier: Apache-2.0 - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package sbt.internal.inc - -import xsbti.VirtualFileRef -import scala.collection.immutable.Set - -private[inc] class WrappedSet(s: java.util.Set[VirtualFileRef]) extends Set[VirtualFileRef] { - import scala.collection.JavaConverters._ - def iterator: Iterator[xsbti.VirtualFileRef] = s.asScala.iterator - def contains(elem: xsbti.VirtualFileRef): Boolean = s.contains(elem) - - def +(elem: xsbti.VirtualFileRef): Set[xsbti.VirtualFileRef] = - s.asScala.foldLeft(Set(elem)) { case (a, e) => a + e } - def -(elem: xsbti.VirtualFileRef): Set[xsbti.VirtualFileRef] = - s.asScala.foldLeft(Set.empty[VirtualFileRef]) { - case (a, e) => if (e != elem) a + e else a - } -} diff --git a/internal/zinc-core/src/main/scala-2.13/sbt/internal/inc/WrappedSet.scala b/internal/zinc-core/src/main/scala-3/sbt/internal/inc/WrappedSet.scala similarity index 100% rename from internal/zinc-core/src/main/scala-2.13/sbt/internal/inc/WrappedSet.scala rename to internal/zinc-core/src/main/scala-3/sbt/internal/inc/WrappedSet.scala diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/APIs.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/APIs.scala index c877377ebb..43d449b12b 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/APIs.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/APIs.scala @@ -86,7 +86,7 @@ private class MAPIs( def removeInternal(removeClasses: Iterable[String]): APIs = new MAPIs(internal -- removeClasses, external) def filterExt(keep: String => Boolean): APIs = - new MAPIs(internal, external.filterKeys(keep).toMap) + new MAPIs(internal, external.view.filterKeys(keep).toMap) def internalAPI(className: String) = getAPI(internal, className) def externalAPI(ext: String) = getAPI(external, ext) diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/Analysis.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/Analysis.scala index 5f28130713..aef15166c9 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/Analysis.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/Analysis.scala @@ -99,6 +99,15 @@ object Analysis { case class Sources(java: Set[String], scala: Set[String]) + def computeBytecodeHash( + localProducts: scala.collection.Set[LocalProduct], + nonLocalProduct: scala.collection.Set[NonLocalProduct] + ): Int = { + val hashes = + localProducts.map(_.classFileStamp.getHash) ++ nonLocalProduct.map(_.classFileStamp.getHash) + hashes.hashCode() + } + def sources(a: Analysis): Sources = { def sourceFileForClass(className: String): VirtualFileRef = a.relations.definesClass(className).headOption.getOrElse { diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/Changes.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/Changes.scala index 3a895f887e..26e6a02da4 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/Changes.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/Changes.scala @@ -13,7 +13,7 @@ package sbt package internal package inc -import scala.collection.JavaConverters._ +import scala.jdk.CollectionConverters._ import xsbti.{ UseScope, VirtualFileRef } import xsbti.api.NameHash @@ -126,12 +126,12 @@ abstract class UnderlyingChanges[A] extends Changes[A] { def changed: Set[A] def unmodified: Set[A] - import scala.collection.JavaConverters.setAsJavaSetConverter + import scala.jdk.CollectionConverters._ override def getAdded: java.util.Set[A] = added.asJava override def getChanged: java.util.Set[A] = changed.asJava override def getRemoved: java.util.Set[A] = removed.asJava override def getUnmodified: java.util.Set[A] = unmodified.asJava - override def isEmpty = added.isEmpty && removed.isEmpty && changed.isEmpty + override def isEmpty(): java.lang.Boolean = added.isEmpty && removed.isEmpty && changed.isEmpty override def toString: String = { s"""Changes(added = $added, removed = $removed, changed = $changed, unmodified = ...)""".stripMargin diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/DummyVirtualFile.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/DummyVirtualFile.scala index c1a08132b7..8be782bcc4 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/DummyVirtualFile.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/DummyVirtualFile.scala @@ -24,6 +24,8 @@ class DummyVirtualFile(encodedPath: String, path: Path) extends BasicVirtualFileRef(encodedPath) with VirtualFile { override def contentHash: Long = HashUtil.farmHash(path) + override def sizeBytes: Long = Files.size(path) + override lazy val contentHashStr: String = HashUtil.sha256HashStr(input) override def input(): InputStream = Files.newInputStream(path) } diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/Incremental.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/Incremental.scala index 5d90c4df41..1fe34c19b2 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/Incremental.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/Incremental.scala @@ -18,12 +18,12 @@ import java.nio.file.{ Files, Path, Paths } import java.{ util => ju } import ju.{ EnumSet, Optional, UUID } import ju.concurrent.atomic.AtomicBoolean -import sbt.internal.inc.Analysis.{ LocalProduct, NonLocalProduct } +import sbt.internal.inc.Analysis.{ LocalProduct, NonLocalProduct, computeBytecodeHash } import sbt.internal.inc.JavaInterfaceUtil.EnrichOption import sbt.util.{ InterfaceUtil, Level, Logger } import sbt.util.InterfaceUtil.{ jl2l, jo2o, l2jl, t2 } -import scala.collection.JavaConverters._ +import scala.jdk.CollectionConverters._ import scala.collection.mutable import scala.util.control.NonFatal import xsbti.{ FileConverter, Position, Problem, Severity, UseScope, VirtualFile, VirtualFileRef } @@ -958,7 +958,7 @@ private final class AnalysisCallback( private def getAnalysis: Analysis = { val analysis0 = addProductsAndDeps(Analysis.empty) - addUsedNames(addCompilation(analysis0)) + addUsedNames(addCompilation(addTransitiveBytecodeHash(analysis0))) } def getPostJavaAnalysis: Analysis = { @@ -977,6 +977,24 @@ private final class AnalysisCallback( ) } + private def addTransitiveBytecodeHash(base: Analysis): Analysis = { + import base.{ apis, relations } + val findUpstream = relations.memberRef.internal.forward _ + val internalAPIs = apis.internal.map { case (className, analyzedClass) => + if (!analyzedClass.hasMacro) { + (className, analyzedClass) + } else { + val upstreamClasses = + IncrementalCommon.transitiveDeps(Set(className), log, logging = false)(findUpstream) + val upstreamAnalyzedClasses = upstreamClasses.map(apis.internalAPI) + val upstreamHashes = upstreamAnalyzedClasses.map(_.bytecodeHash()) + (className, analyzedClass.withTransitiveBytecodeHash(upstreamHashes.hashCode())) + } + } + val APIs = new MAPIs(internalAPIs, apis.external) + base.copy(apis = APIs) + } + private def companionsWithHash(className: String): (Companions, HashAPI.Hash, HashAPI.Hash) = { val emptyHash = -1 val emptyClass = @@ -1004,7 +1022,7 @@ private final class AnalysisCallback( } } - private def analyzeClass(name: String): AnalyzedClass = { + private def analyzeClass(name: String, bytecodeHash: Int): AnalyzedClass = { val hasMacro: Boolean = macroClasses.contains(name) val (companions, apiHash, extraHash) = companionsWithHash(name) val nameHashes = nameHashesForCompanions(name) @@ -1017,12 +1035,14 @@ private final class AnalysisCallback( nameHashes, hasMacro, extraHash, - provenance + provenance, + bytecodeHash, + 0, ) } def addProductsAndDeps(base: Analysis): Analysis = { - import scala.collection.JavaConverters._ + import scala.jdk.CollectionConverters._ srcs.asScala.foldLeft(base) { case (a, src) => val stamp = stampReader.source(src) @@ -1030,7 +1050,6 @@ private final class AnalysisCallback( .getOrElse(src, ConcurrentHashMap.newKeySet[(String, String)]()) .asScala .map(_._1) - val analyzedApis = classesInSrc.map(analyzeClass) val info = SourceInfos.makeInfo( getOrNil(reporteds.iterator.map { case (k, v) => k -> v.asScala.toSeq }.toMap, src), getOrNil(unreporteds.iterator.map { case (k, v) => k -> v.asScala.toSeq }.toMap, src), @@ -1065,6 +1084,9 @@ private final class AnalysisCallback( ) val libDeps = libraries.map(d => (d, binaryClassName(d), stampReader.library(d))) + val bytecodeHash = computeBytecodeHash(localProds, nonLocalProds) + val analyzedApis = classesInSrc.map(analyzeClass(_, bytecodeHash)) + a.addSource( src, analyzedApis, diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalCommon.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalCommon.scala index 729a663455..8eb7d6291f 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalCommon.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalCommon.scala @@ -183,7 +183,7 @@ private[inc] abstract class IncrementalCommon( newApiChanges, recompiledClasses, cycleNum >= options.transitiveStep, - IncrementalCommon.comesFromScalaSource(previous.relations, Some(analysis.relations)) _ + IncrementalCommon.comesFromScalaSource(previous.relations, Some(analysis.relations)) ) // No matter what shouldDoIncrementalCompilation returns, we are not in fact going to @@ -305,12 +305,18 @@ private[inc] abstract class IncrementalCommon( oldAPI: String => AnalyzedClass, newAPI: String => AnalyzedClass ): APIChanges = { + def hashesMatch(a: AnalyzedClass, b: AnalyzedClass, hasMacro: Boolean): Boolean = { + (a.bytecodeHash() == b.bytecodeHash()) && + (a.apiHash == b.apiHash) && + (a.extraHash == b.extraHash) && + (!hasMacro || a.transitiveBytecodeHash() == b.transitiveBytecodeHash()) + } // log.debug(s"[zinc] detectAPIChanges(recompiledClasses = $recompiledClasses)") def classDiff(className: String, a: AnalyzedClass, b: AnalyzedClass): Option[APIChange] = { // log.debug(s"[zinc] classDiff($className, ${a.name}, ${b.name})") - if (a.compilationTimestamp() == b.compilationTimestamp() && (a.apiHash == b.apiHash)) None + val hasMacro = a.hasMacro || b.hasMacro + if (hashesMatch(a, b, hasMacro)) None else { - val hasMacro = a.hasMacro || b.hasMacro if (hasMacro && IncOptions.getRecompileOnMacroDef(options)) { Some(APIChangeDueToMacroDefinition(className)) } else if ( @@ -520,7 +526,7 @@ private[inc] abstract class IncrementalCommon( ): (Set[String], Set[VirtualFileRef]) = { def classNames(srcs: Set[VirtualFileRef]): Set[String] = srcs.flatMap(previous.classNames) def toImmutableSet(srcs: java.util.Set[VirtualFileRef]): Set[VirtualFileRef] = { - import scala.collection.JavaConverters.asScalaIteratorConverter + import scala.jdk.CollectionConverters._ srcs.iterator().asScala.toSet } @@ -539,7 +545,7 @@ private[inc] abstract class IncrementalCommon( val byLibraryDep = changes.libraryDeps.flatMap(previous.usesLibrary) val byExtSrcDep = { // Invalidate changes - val isScalaSource = IncrementalCommon.comesFromScalaSource(previous) _ + val isScalaSource = IncrementalCommon.comesFromScalaSource(previous) changes.external.apiChanges.iterator.flatMap { externalAPIChange => invalidateClassesExternally(previous, externalAPIChange, isScalaSource) }.toSet diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalNameHashing.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalNameHashing.scala index e36b185be3..a236581e51 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalNameHashing.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/IncrementalNameHashing.scala @@ -43,7 +43,7 @@ private[inc] class IncrementalNameHashingCommon( relations: Relations, apis: APIs ): Set[String] = { - val findSubclasses = relations.inheritance.internal.reverse _ + val findSubclasses = relations.inheritance.internal.reverse val invalidatedClassesAndCodefinedClasses = for { cls <- invalidatedClasses.iterator file <- relations.definesClass(cls).iterator @@ -127,7 +127,7 @@ private[inc] class IncrementalNameHashingCommon( } private def invalidateByInheritance(relations: Relations, modified: String): Set[String] = { - val inheritanceDeps = relations.inheritance.internal.reverse _ + val inheritanceDeps = relations.inheritance.internal.reverse log.debug(s"Invalidating (transitively) by inheritance from $modified...") val transitiveInheritance = transitiveDeps(Set(modified), log)(inheritanceDeps) log.debug("Invalidated by transitive inheritance dependency: " + transitiveInheritance) diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/InvalidationProfiler.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/InvalidationProfiler.scala index 8e228e0572..ca9d9caa3f 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/InvalidationProfiler.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/InvalidationProfiler.scala @@ -11,8 +11,7 @@ package sbt.internal.inc -import sbt.internal.prof.Zprof - +// import sbt.internal.prof.Zprof import xsbti.UseScope._ import xsbti.VirtualFileRef import xsbti.compile.{ APIChange => XAPIChange } @@ -20,7 +19,7 @@ import xsbti.compile.{ InitialChanges => XInitialChanges } import xsbti.compile.{ InvalidationProfiler => XInvalidationProfiler } import xsbti.compile.{ RunProfiler => XRunProfiler } -import scala.collection.JavaConverters._ +import scala.jdk.CollectionConverters._ import scala.collection.mutable import scala.collection.mutable.ArrayBuffer @@ -34,22 +33,23 @@ import scala.collection.mutable.ArrayBuffer * this class is not thread safe. */ abstract class InvalidationProfiler { - def profileRun(): RunProfiler - def registerRun(run: Zprof.ZincRun): Unit + // def profileRun(): RunProfiler + // def registerRun(run: Zprof.ZincRun): Unit } object InvalidationProfiler { final val empty: InvalidationProfiler = new InvalidationProfiler { - override def profileRun(): RunProfiler = RunProfiler.empty - override def registerRun(run: Zprof.ZincRun): Unit = () + // override def profileRun(): RunProfiler = RunProfiler.empty + // override def registerRun(run: Zprof.ZincRun): Unit = () } } +/* class ZincInvalidationProfiler extends InvalidationProfiler with XInvalidationProfiler { profiler => /* The string table contains any kind of repeated string that is likely to occur - * in the protobuf profiling data. This includes used names, class names, source - * files and class files (their paths), as well as other repeated strings. This is - * done to keep the memory overhead of the profiler to a minimum. */ + * in the protobuf profiling data. This includes used names, class names, source + * files and class files (their paths), as well as other repeated strings. This is + * done to keep the memory overhead of the profiler to a minimum. */ private final val stringTable: ArrayBuffer[String] = new ArrayBuffer[String](1000) private final val stringTableIndices: mutable.HashMap[String, Int] = new mutable.HashMap[String, Int] @@ -61,17 +61,17 @@ class ZincInvalidationProfiler extends InvalidationProfiler with XInvalidationPr def registerRun(run: Zprof.ZincRun): Unit = runs ::= run /** - * Returns an immutable zprof profile that can be serialized. - * - * It is recommended to only perform this operation when we are - * going to persist the profiled protobuf data to disk. Do not - * call this function after every compiler iteration as you will - * write a symbol table in every persisted protobuf file. It's - * better to persist this file periodically after several runs - * so that the overhead to disk is not high. - * - * @return An immutable zprof profile that can be persisted via protobuf. - */ + * Returns an immutable zprof profile that can be serialized. + * + * It is recommended to only perform this operation when we are + * going to persist the profiled protobuf data to disk. Do not + * call this function after every compiler iteration as you will + * write a symbol table in every persisted protobuf file. It's + * better to persist this file periodically after several runs + * so that the overhead to disk is not high. + * + * @return An immutable zprof profile that can be persisted via protobuf. + */ def toProfile: Zprof.Profile = Zprof.Profile.newBuilder .addAllRuns(runs.asJava) @@ -208,6 +208,7 @@ class ZincInvalidationProfiler extends InvalidationProfiler with XInvalidationPr private def listMap[A, B](xs: Iterable[A])(f: A => B) = xs.iterator.map(f).toList.asJava } } + */ /** * Defines the interface of a profiler. This interface is used in the guts of @@ -288,5 +289,7 @@ trait InvalidationProfilerUtils { final val MacroExpansionKind = "macro expansion" } +/* // So that others users from outside [[IncrementalCommon]] can use the labels object InvalidationProfilerUtils extends InvalidationProfilerUtils + */ diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/Locate.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/Locate.scala index b3b09c3bf8..6f5cafcb82 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/Locate.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/Locate.scala @@ -48,7 +48,7 @@ object Locate { case x => x } } - def find[S](name: String, gets: Stream[String => Either[Boolean, S]]): Either[Boolean, S] = + def find[S](name: String, gets: LazyList[String => Either[Boolean, S]]): Either[Boolean, S] = find[S](name, gets.iterator) /** @@ -102,7 +102,7 @@ object Locate { } private class JarDefinesClass(entry: Path) extends DefinesClass { - import collection.JavaConverters._ + import scala.jdk.CollectionConverters._ private val entries = { val jar = try { diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/Lookup.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/Lookup.scala index 284aff3abd..0f7097fee3 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/Lookup.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/Lookup.scala @@ -66,7 +66,7 @@ trait Lookup extends ExternalLookup { */ trait ExternalLookup extends ExternalHooks.Lookup { import sbt.internal.inc.JavaInterfaceUtil.EnrichOption - import scala.collection.JavaConverters._ + import scala.jdk.CollectionConverters._ /** * Find the external `AnalyzedClass` (from another analysis) given a class name and, if available, @@ -130,7 +130,7 @@ trait ExternalLookup extends ExternalHooks.Lookup { changedClasses: util.Set[String], previousAnalysis: CompileAnalysis ): Boolean = { - import scala.collection.JavaConverters._ + import scala.jdk.CollectionConverters._ shouldDoIncrementalCompilation(changedClasses.iterator().asScala.toSet, previousAnalysis) } diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/MappedVirtualFile.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/MappedVirtualFile.scala index 63d620adff..d85503ab2b 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/MappedVirtualFile.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/MappedVirtualFile.scala @@ -13,15 +13,19 @@ package sbt package internal package inc -import java.io.InputStream +import java.io.{ ByteArrayInputStream, InputStream } +import java.nio.ByteBuffer import java.nio.file.{ Files, Path, Paths } import xsbti.{ BasicVirtualFileRef, FileConverter, PathBasedFile, VirtualFile, VirtualFileRef } +import sbt.nio.file.{ FileTreeView, Glob, IsNotHidden, IsRegularFile, RecursiveGlob } class MappedVirtualFile(encodedPath: String, rootPathsMap: Map[String, Path]) extends BasicVirtualFileRef(encodedPath) with PathBasedFile { private def path: Path = MappedVirtualFile.toPath(encodedPath, rootPathsMap) override def contentHash: Long = HashUtil.farmHash(path) + override def sizeBytes: Long = Files.size(path) + override lazy val contentHashStr: String = HashUtil.sha256HashStr(input) override def input(): InputStream = Files.newInputStream(path) override def toPath: Path = path } @@ -38,8 +42,47 @@ object MappedVirtualFile { } } +class MappedDirectory( + encodedPath: String, + rootPathsMap: Map[String, Path], + items: List[VirtualFile] +) extends BasicVirtualFileRef(encodedPath) + with PathBasedFile { + private def path: Path = MappedVirtualFile.toPath(encodedPath, rootPathsMap) + override lazy val contentHash: Long = { + val buffer = ByteBuffer.allocate(java.lang.Long.BYTES * items.size) + val hashes = items.foreach { item => + buffer.putLong(item.contentHash) + } + HashUtil.farmHash(buffer.array()) + } + override lazy val sizeBytes: Long = items.map(_.sizeBytes).sum + override lazy val contentHashStr: String = { + val sb = new StringBuilder + val hashes = items.foreach { item => + sb.append(item.contentHashStr) + } + val stream = new ByteArrayInputStream(hashes.toString.getBytes("UTF-8")) + HashUtil.sha256HashStr(stream) + } + override def input(): InputStream = ??? + override def toPath: Path = path +} + +object MappedDirectory { + def apply( + encodedPath: String, + rootPaths: Map[String, Path], + items: List[VirtualFile] + ): MappedDirectory = + new MappedDirectory(encodedPath, rootPaths, items) +} + class MappedFileConverter(rootPaths: Map[String, Path], allowMachinePath: Boolean) extends FileConverter { + + import MappedFileConverter.view + val rootPaths2: Seq[(String, Path)] = rootPaths.toSeq.flatMap { case (key, rootPath) => if (rootPath.startsWith("/var/") || rootPath.startsWith("/tmp/")) { @@ -54,9 +97,15 @@ class MappedFileConverter(rootPaths: Map[String, Path], allowMachinePath: Boolea } def toVirtualFile(path: Path): VirtualFile = { + def isDirectory: Boolean = + Files.isDirectory(path) || (!Files.exists(path) && path.getFileName.toString().endsWith( + "classes" + )) rootPaths2.find { case (_, rootPath) => path.startsWith(rootPath) } match { case Some((key, rootPath)) => - MappedVirtualFile(s"$${$key}/${rootPath.relativize(path)}".replace('\\', '/'), rootPaths) + val encodedPath = s"$${$key}/${rootPath.relativize(path)}".replace('\\', '/') + if (isDirectory) toDirectory(path, encodedPath) + else MappedVirtualFile(encodedPath, rootPaths) case _ => def isCtSym = path.getFileSystem @@ -65,13 +114,26 @@ class MappedFileConverter(rootPaths: Map[String, Path], allowMachinePath: Boolea def isJrt = path.getFileSystem.provider().getScheme == "jrt" if (isJrt || path.getFileName.toString == "rt.jar" || isCtSym) DummyVirtualFile("rt.jar", path) - else if (allowMachinePath) MappedVirtualFile(s"$path".replace('\\', '/'), rootPaths) - else sys.error(s"$path cannot be mapped using the root paths $rootPaths") + else if (allowMachinePath) { + val encodedPath = s"$path".replace('\\', '/') + if (isDirectory) toDirectory(path, encodedPath) + else MappedVirtualFile(encodedPath, rootPaths) + } else sys.error(s"$path cannot be mapped using the root paths $rootPaths") } } + + def toDirectory(path: Path, encodedPath: String) = { + val list = view.list(Glob(path, RecursiveGlob), IsRegularFile && IsNotHidden) + .map(_._1) + .sortBy(x => x.toUri().toString()) + val items = list.map(toVirtualFile) + MappedDirectory(encodedPath, rootPaths, items.toList) + } } object MappedFileConverter { + private[sbt] lazy val view = FileTreeView.Ops(FileTreeView.default) + def empty: MappedFileConverter = new MappedFileConverter(Map(), true) def apply(rootPaths: Map[String, Path], allowMachinePath: Boolean): MappedFileConverter = new MappedFileConverter(rootPaths, allowMachinePath) diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/MiniSetupUtil.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/MiniSetupUtil.scala index 7e86f21747..3dc90dc017 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/MiniSetupUtil.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/MiniSetupUtil.scala @@ -102,7 +102,7 @@ object MiniSetupUtil { implicit val equivOutput: Equiv[APIOutput] = { new Equiv[APIOutput] { - implicit val outputGroupsOrdering = + implicit val outputGroupsOrdering: Ordering[OutputGroup] = Ordering.by((og: OutputGroup) => og.getSourceDirectoryAsPath) def equiv(out1: APIOutput, out2: APIOutput) = (out1, out2) match { diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/PickleJar.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/PickleJar.scala index 1657377a1a..26829fb7fc 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/PickleJar.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/PickleJar.scala @@ -16,7 +16,6 @@ package inc import java.nio.file.{ FileVisitResult, Files, Path, SimpleFileVisitor } import java.nio.file.attribute.BasicFileAttributes import sbt.util.Logger -import scala.reflect.io.RootPath import sbt.internal.io.Retry object PickleJar { diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/RootPath.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/RootPath.scala new file mode 100644 index 0000000000..cef60e870a --- /dev/null +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/RootPath.scala @@ -0,0 +1,60 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright Scala Center, Lightbend, and Mark Harrah + * + * Licensed under Apache License 2.0 + * SPDX-License-Identifier: Apache-2.0 + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package sbt.internal.inc + +import java.io.Closeable +import java.nio +import java.nio.file.Files +import java.nio.file.spi.FileSystemProvider + +import scala.jdk.CollectionConverters._ + +/** + * borrowed from scala-reflect + * [[https://github.com/scala/scala/blob/v2.13.16/src/reflect/scala/reflect/io/RootPath.scala]] + */ +private[inc] abstract class RootPath extends Closeable { + def root: nio.file.Path +} + +private[inc] object RootPath { + private lazy val jarFsProvider = FileSystemProvider.installedProviders().asScala.find( + _.getScheme == "jar" + ).getOrElse(throw new RuntimeException("No jar filesystem provider")) + def apply(path: nio.file.Path, writable: Boolean): RootPath = { + if (path.getFileName.toString.endsWith(".jar")) { + val env = new java.util.HashMap[String, String]() + if (!Files.exists(path.getParent)) + Files.createDirectories(path.getParent) + if (writable) { + env.put("create", "true") + if (Files.exists(path)) + Files.delete(path) + } + val zipfs = jarFsProvider.newFileSystem(path, env) + + new RootPath { + def root = zipfs.getRootDirectories.iterator().next() + def close(): Unit = { + zipfs.close() + } + override def toString: String = path.toString + } + } else { + new RootPath { + override def root: nio.file.Path = path + override def close(): Unit = () + override def toString: String = path.toString + } + } + } +} diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/SourceInfo.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/SourceInfo.scala index b274f4b089..247b6b0710 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/SourceInfo.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/SourceInfo.scala @@ -101,7 +101,7 @@ private final class MSourceInfos(val allInfos: Map[VirtualFileRef, SourceInfo]) allInfos.getOrElse(file, SourceInfos.emptyInfo) override def getAllSourceInfos: java.util.Map[VirtualFileRef, SourceInfo] = { - import scala.collection.JavaConverters._ + import scala.jdk.CollectionConverters._ allInfos.asJava } } diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/Stamp.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/Stamp.scala index 4b3b2205da..447a376434 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/Stamp.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/Stamp.scala @@ -23,7 +23,7 @@ import xsbti.{ FileConverter, VirtualFile, VirtualFileRef } import xsbti.compile.analysis.{ ReadStamps, Stamp => XStamp } import scala.collection.immutable.TreeMap -import scala.collection.JavaConverters._ +import scala.jdk.CollectionConverters._ import scala.util.matching.Regex /** @@ -351,13 +351,13 @@ private class MStamps( lib: VirtualFileRef => Boolean ): Stamps = new MStamps( - products.filterKeys(prod).toMap, { + products.view.filterKeys(prod).toMap, { val rs = removeSources.toSet Map(sources.toSeq.filter { case (file, stamp) => !rs(file) - }: _*) + }*) }, - libraries.filterKeys(lib).toMap + libraries.view.filterKeys(lib).toMap ) def groupBy[K]( @@ -369,9 +369,9 @@ private class MStamps( val constFalse = (f: VirtualFileRef) => false def kStamps(k: K): Stamps = new MStamps( - products.filterKeys(prod.getOrElse(k, constFalse)).toMap, + products.view.filterKeys(prod.getOrElse(k, constFalse)).toMap, sourcesMap.getOrElse(k, Map.empty[VirtualFileRef, XStamp]), - libraries.filterKeys(lib.getOrElse(k, constFalse)).toMap + libraries.view.filterKeys(lib.getOrElse(k, constFalse)).toMap ) (for (k <- prod.keySet ++ sourcesMap.keySet ++ lib.keySet) yield (k, kStamps(k))).toMap diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/UsedName.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/UsedName.scala index 01e9cf0b85..7ca3b9eacb 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/UsedName.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/UsedName.scala @@ -54,7 +54,7 @@ sealed abstract class UsedNames private { } object UsedNames { - def fromJavaMap(map: ju.Map[String, Schema.UsedNames]) = JavaUsedNames(map) + // def fromJavaMap(map: ju.Map[String, Schema.UsedNames]) = JavaUsedNames(map) def fromMultiMap(map: sc.Map[String, sc.Set[UsedName]]) = ScalaUsedNames(map) final case class ScalaUsedNames(map: sc.Map[String, sc.Set[UsedName]]) extends UsedNames { @@ -68,86 +68,4 @@ object UsedNames { def affectedNames(modifiedNames: ModifiedNames, from: String): String = map(from).iterator.filter(modifiedNames.isModified).mkString(", ") } - - final case class JavaUsedNames(map: ju.Map[String, Schema.UsedNames]) extends UsedNames { - - import scala.collection.JavaConverters._ - - private def fromUseScope(useScope: Schema.UseScope, id: Int): UseScope = useScope match { - case Schema.UseScope.DEFAULT => UseScope.Default - case Schema.UseScope.IMPLICIT => UseScope.Implicit - case Schema.UseScope.PATMAT => UseScope.PatMatTarget - case Schema.UseScope.UNRECOGNIZED => - sys.error(s"Unrecognized ${classOf[Schema.UseScope].getName} with value `$id`.") - } - - private def fromUsedName(usedName: Schema.UsedName): UsedName = { - val name = usedName.getName.intern() // ? - val useScopes = ju.EnumSet.noneOf(classOf[UseScope]) - val len = usedName.getScopesCount - for (i <- 0 to len - 1) - useScopes.add(fromUseScope(usedName.getScopes(i), usedName.getScopesValue(i))) - UsedName.make(name, useScopes) - } - - private def fromUsedNamesMap(map: ju.Map[String, Schema.UsedNames]) = - for ((k, used) <- map.asScala) - yield k -> used.getUsedNamesList.asScala.iterator.map(fromUsedName).toSet - - lazy val toMultiMap: sc.Map[String, sc.Set[UsedName]] = fromUsedNamesMap(map) - private lazy val convert: UsedNames = fromMultiMap(toMultiMap) - - def isEmpty = map.isEmpty - - def ++(other: UsedNames) = convert ++ other - - def --(classes: Iterable[String]) = convert -- classes - - def iterator = convert.iterator - - def hasAffectedNames(modifiedNames: ModifiedNames, from: String): Boolean = { - val usedNames = map.get(from) - var i = 0 - val n = usedNames.getUsedNamesCount - while (i < n) { - val usedName = usedNames.getUsedNames(i) - val name = usedName.getName - var i2 = 0 - val n2 = usedName.getScopesCount - while (i2 < n2) { - val scope = fromUseScope(usedName.getScopes(i2), usedName.getScopesValue(i2)) - if (modifiedNames.isModifiedRaw(name, scope)) { - return true - } - i2 += 1 - } - i += 1 - } - false - } - - def affectedNames(modifiedNames: ModifiedNames, from: String): String = { - val b = new StringBuilder() - val usedNames = map.get(from) - var first = true - var i = 0 - val n = usedNames.getUsedNamesCount - while (i < n) { - val usedName = usedNames.getUsedNames(i) - val name = usedName.getName - var i2 = 0 - val n2 = usedName.getScopesCount - while (i2 < n2) { - val scope = fromUseScope(usedName.getScopes(i2), usedName.getScopesValue(i2)) - if (modifiedNames.isModifiedRaw(name, scope)) { - if (first) first = false else b.append(", ") - b.append(name) - } - i2 += 1 - } - i += 1 - } - b.toString - } - } } diff --git a/internal/zinc-persist-core/src/main/protobuf/schema.proto b/internal/zinc-persist-core/src/main/protobuf/schema.proto deleted file mode 100644 index 99c2f263af..0000000000 --- a/internal/zinc-persist-core/src/main/protobuf/schema.proto +++ /dev/null @@ -1,497 +0,0 @@ -syntax = "proto3"; - -package sbt.internal.inc; - -/////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////// ANALYSIS API //////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -message Hash { - string hash = 1; -} - -message LastModified { - int64 millis = 1; -} - -message FarmHash { - int64 hash = 1; -} - -message Stamps { - message StampType { - oneof type { - Hash hash = 1; - LastModified lastModified = 2; - FarmHash farmHash = 3; - } - } - - map productStamps = 1; - map binaryStamps = 2; - map sourceStamps = 3; -} - -message OutputGroup { - string sourcePath = 1; - string targetPath = 2; -} - -message MultipleOutput { - repeated OutputGroup outputGroups = 1; -} - -message SingleOutput { - string target = 1; -} - -message Compilation { - int64 startTimeMillis = 1; - oneof Output { - SingleOutput singleOutput = 2; - MultipleOutput multipleOutput = 3; - } -} - -message Compilations { - repeated Compilation compilations = 1; -} - -enum Severity { - INFO = 0; - WARN = 1; - ERROR = 2; -} - -message Position { - sint32 line = 1; - sint32 offset = 2; - string lineContent = 3; - sint32 pointer = 4; - string pointerSpace = 5; - string sourcePath = 6; - string sourceFilepath = 7; - sint32 startOffset = 8; - sint32 endOffset = 9; - sint32 startLine = 10; - sint32 startColumn = 11; - sint32 endLine = 12; - sint32 endColumn = 13; -} - -message DiagnosticCode { - string code = 1; - string explanation = 2; -} - -message DiagnosticRelatedInformation { - Position position = 1; - string message = 2; -} - -message TextEdit { - Position position = 1; - string newText = 2; -} - -message WorkspaceEdit { - repeated TextEdit changes = 1; -} - -message Action { - string title = 1; - string description = 2; - WorkspaceEdit edit = 3; -} - -message Problem { - string category = 1; - Severity severity = 2; - string message = 3; - Position position = 4; - string rendered = 5; - DiagnosticCode diagnosticCode = 6; - repeated DiagnosticRelatedInformation diagnosticRelatedInforamation = 7 [deprecated=true]; - repeated DiagnosticRelatedInformation diagnosticRelatedInformation = 8; - repeated Action actions = 9; -} - -message SourceInfo { - repeated Problem reportedProblems = 1; - repeated Problem unreportedProblems = 2; - repeated string mainClasses = 3; -} - -message SourceInfos { - map sourceInfos = 1; -} - -message FileHash { - string path = 1; - sint32 hash = 2; -} - -enum CompileOrder { - MIXED = 0; - JAVATHENSCALA = 1; - SCALATHENJAVA = 2; -} - -message Tuple { - string first = 1; - string second = 2; -} - -message MiniOptions { - repeated FileHash classpathHash = 1; - repeated string scalacOptions = 2; - repeated string javacOptions = 3; -} - -message MiniSetup { - oneof Output { - SingleOutput singleOutput = 1; - MultipleOutput multipleOutput = 2; - } - MiniOptions miniOptions = 3; - string compilerVersion = 4; - CompileOrder compileOrder = 5; - bool storeApis = 6; - repeated Tuple extra = 7; -} - -/////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////// BRIDGE API //////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -message This {} - -message Id { - string id = 1; -} - - -message Super { - Path qualifier = 1; -} - -message Path { - message PathComponent { - oneof Component { - Id id = 1; - This this = 2; - Super super = 3; - } - } - - repeated PathComponent components = 1; -} - -message AnnotationArgument { - string name = 1; - string value = 2; -} - -enum Variance { - INVARIANT = 0; - CONTRAVARIANT = 1; - COVARIANT = 2; -} - -message ThisQualifier {} - -message Unqualified {} - -message IdQualifier { - string value = 1; -} - -message Qualifier { - oneof Type { - ThisQualifier thisQualifier = 1; - IdQualifier idQualifier = 2; - Unqualified unqualified = 3; - } -} - -message Public {} - -message Private { - Qualifier qualifier = 1; -} - -message Protected { - Qualifier qualifier = 1; -} - -message Access { - oneof Type { - Public public = 1; - Protected protected = 2; - Private private = 3; - } -} - -message Modifiers { - sfixed32 flags = 1; -} - -message Type { - message Projection { - string id = 1; - Type prefix = 2; - } - - message ParameterRef { - string id = 1; - } - - message Polymorphic { - Type baseType = 1; - repeated TypeParameter typeParameters = 2; - } - - message Parameterized { - Type baseType = 1; - repeated Type typeArguments = 2; - } - - message Existential { - Type baseType = 1; - repeated TypeParameter clause = 2; - } - - message Constant { - Type baseType = 1; - string value = 2; - } - - message Annotated { - Type baseType = 1; - repeated Annotation annotations = 2; - } - - message Structure { - repeated Type parents = 1; - repeated ClassDefinition declared = 2; - repeated ClassDefinition inherited = 3; - } - - message Singleton { - Path path = 1; - } - - message EmptyType {} - - oneof Value { - ParameterRef parameterRef = 1; - Parameterized parameterized = 2; - Structure structure = 3; - Polymorphic polymorphic = 4; - Constant constant = 5; - Existential existential = 6; - Singleton singleton = 7; - Projection projection = 8; - Annotated annotated = 9; - EmptyType emptyType = 10; - } -} - -message Annotation { - Type base = 1; - repeated AnnotationArgument arguments = 2; -} - -message TypeParameter { - string id = 1; - repeated Annotation annotations = 2; - repeated TypeParameter typeParameters = 3; - Variance variance = 4; - Type lowerBound = 5; - Type upperBound = 6; -} - -enum ParameterModifier { - PLAIN = 0; - REPEATED = 1; - BYNAME = 2; -} - -message MethodParameter { - string name = 1; - Type type = 2; - bool hasDefault = 3; - ParameterModifier modifier = 4; -} - -message ParameterList { - repeated MethodParameter parameters = 1; - bool isImplicit = 2; -} - -message ClassDefinition { - message ClassLikeDef { - repeated TypeParameter typeParameters = 1; - DefinitionType definitionType = 2; - } - - message Def { - repeated TypeParameter typeParameters = 1; - repeated ParameterList valueParameters = 2; - Type returnType = 3; - } - - message Val { - Type type = 1; - } - - message Var { - Type type = 1; - } - - message TypeAlias { - repeated TypeParameter typeParameters = 1; - Type type = 2; - } - - message TypeDeclaration { - repeated TypeParameter typeParameters = 1; - Type lowerBound = 2; - Type upperBound = 3; - } - - string name = 1; - Access access = 2; - Modifiers modifiers = 3; - repeated Annotation annotations = 4; - oneof extra { - ClassLikeDef classLikeDef = 5; - Def defDef = 6; - Val valDef = 7; - Var varDef = 8; - TypeAlias typeAlias = 9; - TypeDeclaration typeDeclaration = 10; - } -} - - -enum DefinitionType { - TRAIT = 0; - CLASSDEF = 1; - MODULE = 2; - PACKAGEMODULE = 3; -} - -message ClassLike { - string name = 1; - Access access = 2; - Modifiers modifiers = 3; - repeated Annotation annotations = 4; - - DefinitionType definitionType = 5; - Type selfType = 6; - Type.Structure structure = 7; - repeated string savedAnnotations = 8; - repeated Type childrenOfSealedClass = 9; - bool topLevel = 10; - repeated TypeParameter typeParameters = 11; -} - -message Companions { - ClassLike classApi = 1; - ClassLike objectApi = 2; -} - -enum UseScope { - DEFAULT = 0; - IMPLICIT = 1; - PATMAT = 2; -} - -message NameHash { - string name = 1; - UseScope scope = 2; - sint32 hash = 3; -} - -message AnalyzedClass { - int64 compilationTimestamp = 1; - string name = 2; - Companions api = 3; - sint32 apiHash = 4; - repeated NameHash nameHashes = 5; - bool hasMacro = 6; - sint32 extraHash = 7; - string provenance = 8; -} - -message APIs { - map internal = 1; - map external = 2; -} - -message UsedName { - string name = 1; - repeated UseScope scopes = 2; -} - -/** Defines a container for the values of maps. */ -message Values { - repeated string values = 1; -} - -message UsedNames { - repeated UsedName usedNames = 1; -} - -message ClassDependencies { - /** Keeps track of the internal name dependencies */ - map internal = 1; - /** Keeps track of the external name dependencies */ - map external = 2; -} - -message Relations { - /** Defines relation between source file paths and the generated products. */ - map srcProd = 1; - /** Defines relation between source file paths and library dependencies */ - map libraryDep = 2; - /** Defines relation between library JAR file paths and class names. */ - map libraryClassName = 3; - /** Defines relation between source file paths and their generated fully-qualified class names. */ - map classes = 4; - map productClassName = 5; - /** Defines relation between names and their used names. */ - map names = 6; - - ClassDependencies memberRef = 7; - ClassDependencies inheritance = 8; - ClassDependencies localInheritance = 9; - ClassDependencies macroExpansion = 10; -} - -message Analysis { - Stamps stamps = 1; - Relations relations = 2; - SourceInfos sourceInfos = 3; - Compilations compilations = 4; -} - -/** Defines a version that allows to have custom protobuf-based readers and writers - * in the future without sacrificing binary compatibility. For instance, this can be - * used to enable an streaming-based protobuf API to be even more performant. */ -enum Version { - V1 = 0; - V1_1 = 1; -} - -message AnalysisFile { - Version version = 1; - Analysis analysis = 2; - MiniSetup miniSetup = 3; -} - -message APIsFile { - Version version = 1; - APIs apis = 2; -} diff --git a/internal/zinc-persist-core/src/main/protobuf/zprof.proto b/internal/zinc-persist-core/src/main/protobuf/zprof.proto deleted file mode 100644 index 2a004e261e..0000000000 --- a/internal/zinc-persist-core/src/main/protobuf/zprof.proto +++ /dev/null @@ -1,72 +0,0 @@ -syntax = "proto3"; - -package sbt.internal.prof; - -/////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////// ZINC PROF /////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -// This protobuf scheme is inspired by https://github.com/google/pprof/blob/master/proto/profile.proto -// As pprof, it uses a string table and all the supposed strings in the format are represented as an -// index (int32) of that string table. This is done to minimize overhead in memory and disk. - -message Profile { - repeated ZincRun runs = 1; - repeated string string_table = 2; -} - -message ZincRun { - InitialChanges initial = 1; - repeated CycleInvalidation cycles = 3; -} - -message CycleInvalidation { - repeated int32 invalidated = 1; - repeated int32 invalidatedByPackageObjects = 2; - repeated int32 initialSources = 3; - repeated int32 invalidatedSources = 4; - repeated int32 recompiledClasses = 5; - - int64 startTimeNanos = 6; // Start time of compilation (UTC) as nanoseconds past the epoch - int64 compilationDurationNanos = 7; // Duration of the compilation profile in nanoseconds - repeated ApiChange changesAfterRecompilation = 8; - - repeated InvalidationEvent events = 9; - repeated int32 nextInvalidations = 10; - bool shouldCompileIncrementally = 11; -} - -message InvalidationEvent { - string kind = 1; - repeated int32 inputs = 2; - repeated int32 outputs = 3; - string reason = 4; -} - -message Changes { - repeated int32 added = 1; - repeated int32 removed = 2; - repeated int32 modified = 3; -} - -message ApiChange { - int32 modifiedClass = 1; - string reason = 2; - repeated UsedName usedNames = 3; // Can be empty if the change is not related to names -} - -message InitialChanges { - Changes changes = 1; - repeated int32 removedProducts = 2; - repeated int32 binaryDependencies = 3; - repeated ApiChange externalChanges = 4; -} - -message UsedName { - int32 name = 1; - repeated Scope scopes = 2; -} - -message Scope { - int32 kind = 1; -} diff --git a/internal/zinc-persist/src/main/java/xsbti/compile/FileAnalysisStore.java b/internal/zinc-persist/src/main/java/xsbti/compile/FileAnalysisStore.java index 8fc6e03c59..9fed03da26 100644 --- a/internal/zinc-persist/src/main/java/xsbti/compile/FileAnalysisStore.java +++ b/internal/zinc-persist/src/main/java/xsbti/compile/FileAnalysisStore.java @@ -16,36 +16,37 @@ import java.io.File; /** - * Defines a store interface that provides analysis **file** read and write capabilities to users. + * Defines a store interface that provides analysis **file** read and write + * capabilities to users. * - * This interface provides a backend for `AnalysisStore` to read and write from files, - * storing the analysis contents in the file system before or after every incremental compile. + * This interface provides a backend for `AnalysisStore` to read and write from + * files, storing the analysis contents in the file system before or after every + * incremental compile. */ public interface FileAnalysisStore extends AnalysisStore { - /** - * Returns the default implementation of a file-based `AnalysisStore`. - * - * This implementation is binary and based on Protobuf, which means that the content - * of the file will be binary and can be read in plain text with the Protobuf toolkit. - * - * @param analysisFile The analysis file to store. - * @return A binary file-based analysis store. - */ - static AnalysisStore getDefault(File analysisFile) { - return sbt.internal.inc.FileAnalysisStore.binary(analysisFile); - } + /** + * Returns the default implementation of a file-based `AnalysisStore`. + * + * This implementation is binary. + * + * @param analysisFile The analysis file to store. + * @return A binary file-based analysis store. + */ + static AnalysisStore getDefault(File analysisFile) { + return sbt.internal.inc.FileAnalysisStore.binary(analysisFile); + } - /** - * Returns the default implementation of a file-based `AnalysisStore`. - * - * This implementation is binary and based on Protobuf, which means that the content - * of the file will be binary and can be read in plain text with the Protobuf toolkit. - * - * @param analysisFile The analysis file to store. - * @param mappers The mappers to be used while reading and writing the analysis file. - * @return A binary file-based analysis store. - */ - static AnalysisStore getDefault(File analysisFile, ReadWriteMappers mappers) { - return sbt.internal.inc.FileAnalysisStore.binary(analysisFile, mappers); - } + /** + * Returns the default implementation of a file-based `AnalysisStore`. + * + * This implementation is binary. + * + * @param analysisFile The analysis file to store. + * @param mappers The mappers to be used while reading and writing the + * analysis file. + * @return A binary file-based analysis store. + */ + static AnalysisStore getDefault(File analysisFile, ReadWriteMappers mappers) { + return sbt.internal.inc.FileAnalysisStore.binary(analysisFile, mappers); + } } \ No newline at end of file diff --git a/internal/zinc-persist/src/main/scala-2.12/sbt/internal/inc/consistent/Compat.scala b/internal/zinc-persist/src/main/scala-2.12/sbt/internal/inc/consistent/Compat.scala deleted file mode 100644 index 7e3d6af4d2..0000000000 --- a/internal/zinc-persist/src/main/scala-2.12/sbt/internal/inc/consistent/Compat.scala +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Zinc - The incremental compiler for Scala. - * Copyright Scala Center, Lightbend, and Mark Harrah - * - * Licensed under Apache License 2.0 - * SPDX-License-Identifier: Apache-2.0 - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package sbt.internal.inc.consistent - -import java.util.Arrays -import scala.collection.{ MapLike, SetLike, SortedMap, SortedMapLike } -import scala.collection.generic.{ - CanBuildFrom, - GenericTraversableTemplate, - MapFactory, - SeqFactory, - SetFactory, - SortedMapFactory -} - -// some simple compatibility shims for 2.12 so we don't need to depend on collection-compat -object Compat { - type Factory[-A, +C] = CanBuildFrom[Nothing, A, C] - - implicit def sortedMapFactoryToCBF[CC[A, B] <: SortedMap[A, B] with SortedMapLike[ - A, - B, - CC[A, B] - ], K: Ordering, V](f: SortedMapFactory[CC]): Factory[(K, V), CC[K, V]] = - new f.SortedMapCanBuildFrom - - implicit def mapFactoryToCBF[CC[A, B] <: Map[A, B] with MapLike[A, B, CC[A, B]], K, V]( - f: MapFactory[CC] - ): Factory[(K, V), CC[K, V]] = - new f.MapCanBuildFrom - - implicit def seqFactoryToCBF[CC[X] <: Seq[X] with GenericTraversableTemplate[X, CC], E]( - f: SeqFactory[CC] - ): Factory[E, CC[E]] = - new f.GenericCanBuildFrom - - implicit def setFactoryToCBF[CC[X] <: Set[X] with SetLike[X, CC[X]], E](f: SetFactory[CC]) - : Factory[E, CC[E]] = - f.setCanBuildFrom - - implicit class FactoryOps[-A, +C](private val factory: Factory[A, C]) { - def newBuilder: scala.collection.mutable.Builder[A, C] = factory() - } - - type IterableOnce[+E] = TraversableOnce[E] - - implicit class IterableOnceOps[+E](private val it: IterableOnce[E]) { - def iterator: Iterator[E] = it match { - case it: Iterator[?] => it.asInstanceOf[Iterator[E]] - case it => it.asInstanceOf[Iterable[E]].iterator - } - } - - implicit class ArrayOps[A <: AnyRef](private val a: Array[A]) { - def sortInPlaceBy[B](f: A => B)(implicit ord: Ordering[B]): Unit = Arrays.sort(a, ord on f) - } -} diff --git a/internal/zinc-persist/src/main/scala-2.13/sbt/internal/inc/consistent/Compat.scala b/internal/zinc-persist/src/main/scala-2.13/sbt/internal/inc/consistent/Compat.scala deleted file mode 100644 index aea1a9950b..0000000000 --- a/internal/zinc-persist/src/main/scala-2.13/sbt/internal/inc/consistent/Compat.scala +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Zinc - The incremental compiler for Scala. - * Copyright Scala Center, Lightbend, and Mark Harrah - * - * Licensed under Apache License 2.0 - * SPDX-License-Identifier: Apache-2.0 - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package sbt.internal.inc.consistent - -object Compat { - type Factory[-A, +C] = scala.collection.Factory[A, C] -} diff --git a/internal/zinc-persist/src/main/scala/sbt/internal/inc/FileAnalysisStore.scala b/internal/zinc-persist/src/main/scala/sbt/internal/inc/FileAnalysisStore.scala index cbf9d7fbf0..a1975ee333 100644 --- a/internal/zinc-persist/src/main/scala/sbt/internal/inc/FileAnalysisStore.scala +++ b/internal/zinc-persist/src/main/scala/sbt/internal/inc/FileAnalysisStore.scala @@ -17,9 +17,6 @@ import java.io._ import java.nio.file.Files import java.util.Optional import java.util.zip.{ ZipEntry, ZipInputStream } - -import sbt.internal.shaded.com.google.protobuf.{ CodedInputStream, CodedOutputStream } -import sbt.internal.inc.binary.BinaryAnalysisFormat import sbt.internal.inc.text.TextAnalysisFormat import sbt.io.{ IO, Using } import xsbti.api.Companions @@ -35,13 +32,6 @@ object FileAnalysisStore { private final val companionsFileName = s"api_companions.$BinExtension" private final val defaultTmpDir = new File(System.getProperty("java.io.tmpdir")) - def binary(analysisFile: File): XAnalysisStore = - binary(analysisFile, ReadWriteMappers.getEmptyMappers()) - def binary(analysisFile: File, mappers: ReadWriteMappers): XAnalysisStore = - binary(analysisFile, mappers, defaultTmpDir) - def binary(analysisFile: File, mappers: ReadWriteMappers, tmpDir: File): XAnalysisStore = - new BinaryFileStore(analysisFile, mappers, tmpDir) - def text(file: File): XAnalysisStore = text(file, TextAnalysisFormat) def text(file: File, mappers: ReadWriteMappers): XAnalysisStore = @@ -51,62 +41,10 @@ object FileAnalysisStore { def text(file: File, format: TextAnalysisFormat, tmpDir: File): XAnalysisStore = new FileBasedStoreImpl(file, format, tmpDir) - private final class BinaryFileStore(file: File, readWriteMappers: ReadWriteMappers, tmpDir: File) - extends XAnalysisStore { - - private final val format = new BinaryAnalysisFormat(readWriteMappers) - private final val TmpEnding = ".tmp" - - /** - * Get `CompileAnalysis` and `MiniSetup` instances for current `Analysis`. - */ - override def get: Optional[AnalysisContents] = { - import JavaInterfaceUtil.EnrichOption - val nestedRead: Option[Option[AnalysisContents]] = allCatch.opt { - Using.zipInputStream(new FileInputStream(file)) { inputStream => - lookupEntry(inputStream, analysisFileName) - val reader = CodedInputStream.newInstance(inputStream) - val (analysis, miniSetup) = format.read(reader) - val analysisWithAPIs = allCatch.opt { - lookupEntry(inputStream, companionsFileName) - format.readAPIs(reader, analysis, miniSetup.storeApis) - } - - analysisWithAPIs.map(analysis => AnalysisContents.create(analysis, miniSetup)) - } - } - nestedRead.flatten.toOptional - } - - override def unsafeGet: AnalysisContents = get.get - - /** - * Write the zipped analysis contents into a temporary file before - * overwriting the old analysis file and avoiding data race conditions. - * - * See https://github.com/sbt/zinc/issues/220 for more details. - */ - override def set(contents: AnalysisContents): Unit = { - val analysis = contents.getAnalysis - val setup = contents.getMiniSetup - val tmpAnalysisFile = Files.createTempFile(tmpDir.toPath, file.getName, TmpEnding).toFile - if (!file.getParentFile.exists()) - file.getParentFile.mkdirs() - - val outputStream = new FileOutputStream(tmpAnalysisFile) - Using.zipOutputStream(outputStream) { outputStream => - val protobufWriter = CodedOutputStream.newInstance(outputStream) - outputStream.putNextEntry(new ZipEntry(analysisFileName)) - format.write(protobufWriter, analysis, setup) - outputStream.closeEntry() - - outputStream.putNextEntry(new ZipEntry(companionsFileName)) - format.writeAPIs(protobufWriter, analysis, setup.storeApis()) - outputStream.closeEntry() - } - IO.move(tmpAnalysisFile, file) - } - } + def binary(file: File): XAnalysisStore = + consistent.ConsistentFileAnalysisStore.binary(file) + def binary(file: File, mappers: ReadWriteMappers): XAnalysisStore = + consistent.ConsistentFileAnalysisStore.binary(file, mappers) private final class FileBasedStoreImpl(file: File, format: TextAnalysisFormat, tmpDir: File) extends XAnalysisStore { diff --git a/internal/zinc-persist/src/main/scala/sbt/internal/inc/binary/BinaryAnalysisFormat.scala b/internal/zinc-persist/src/main/scala/sbt/internal/inc/binary/BinaryAnalysisFormat.scala deleted file mode 100644 index 8fcef975ec..0000000000 --- a/internal/zinc-persist/src/main/scala/sbt/internal/inc/binary/BinaryAnalysisFormat.scala +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Zinc - The incremental compiler for Scala. - * Copyright Scala Center, Lightbend, and Mark Harrah - * - * Licensed under Apache License 2.0 - * SPDX-License-Identifier: Apache-2.0 - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package sbt.internal.inc.binary - -import sbt.internal.shaded.com.google.protobuf.{ CodedInputStream, CodedOutputStream } -import sbt.internal.inc.binary.converters.{ ProtobufReaders, ProtobufWriters } -import sbt.internal.inc.{ Analysis, Schema } -import xsbti.compile.analysis.ReadWriteMappers -import xsbti.compile.{ CompileAnalysis, MiniSetup } - -final class BinaryAnalysisFormat(mappers: ReadWriteMappers) { - private final val CurrentVersion = Schema.Version.V1_1 - private final val protobufWriters = new ProtobufWriters(mappers.getWriteMapper) - private final val protobufReaders = new ProtobufReaders(mappers.getReadMapper, CurrentVersion) - - def write(writer: CodedOutputStream, analysis0: CompileAnalysis, miniSetup: MiniSetup): Unit = { - val analysis = analysis0 match { case analysis: Analysis => analysis } - val protobufFile = protobufWriters.toAnalysisFile(analysis, miniSetup, CurrentVersion) - protobufFile.writeTo(writer) - writer.flush() - } - - def writeAPIs( - writer: CodedOutputStream, - analysis0: CompileAnalysis, - shouldStoreApis: Boolean - ): Unit = { - val analysis = analysis0 match { case analysis: Analysis => analysis } - val protobufAPIsFile = - protobufWriters.toApisFile(analysis.apis, CurrentVersion, shouldStoreApis: Boolean) - protobufAPIsFile.writeTo(writer) - writer.flush() - } - - def read(reader: CodedInputStream): (CompileAnalysis, MiniSetup) = { - val protobufFile = Schema.AnalysisFile.parseFrom(reader) - val (analysis, miniSetup, _) = protobufReaders.fromAnalysisFile(protobufFile) - analysis -> miniSetup - } - - def readAPIs( - reader: CodedInputStream, - analysis0: CompileAnalysis, - shouldStoreApis: Boolean - ): CompileAnalysis = { - val analysis = analysis0 match { case analysis: Analysis => analysis } - val protobufAPIsFile = Schema.APIsFile.parseFrom(reader) - val (apis, _) = protobufReaders.fromApisFile(protobufAPIsFile, shouldStoreApis) - analysis.copy(apis = apis) - } -} diff --git a/internal/zinc-persist/src/main/scala/sbt/internal/inc/binary/converters/ProtobufDefaults.scala b/internal/zinc-persist/src/main/scala/sbt/internal/inc/binary/converters/ProtobufDefaults.scala deleted file mode 100644 index 792e397de4..0000000000 --- a/internal/zinc-persist/src/main/scala/sbt/internal/inc/binary/converters/ProtobufDefaults.scala +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Zinc - The incremental compiler for Scala. - * Copyright Scala Center, Lightbend, and Mark Harrah - * - * Licensed under Apache License 2.0 - * SPDX-License-Identifier: Apache-2.0 - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package sbt.internal.inc.binary.converters - -import xsbti.api._ -import sbt.internal.inc.Schema - -object ProtobufDefaults { - final val MissingInt: Int = -1 - final val MissingString: String = "" - - object ReadersConstants { - final val This: This = xsbti.api.This.of() - final val Public: Public = xsbti.api.Public.of() - final val EmptyType: EmptyType = xsbti.api.EmptyType.of() - final val Unqualified: Unqualified = xsbti.api.Unqualified.of() - final val ThisQualifier: ThisQualifier = xsbti.api.ThisQualifier.of() - } - - object WritersConstants { - final val This: Schema.This = Schema.This.getDefaultInstance - final val PublicAccess: Schema.Public = Schema.Public.getDefaultInstance - final val Unqualified: Schema.Unqualified = Schema.Unqualified.getDefaultInstance - final val EmptyType: Schema.Type.EmptyType = Schema.Type.EmptyType.getDefaultInstance - final val ThisQualifier: Schema.ThisQualifier = Schema.ThisQualifier.getDefaultInstance - } - - object Classes { - final val Annotation = classOf[Schema.Annotation] - final val Parameterized = classOf[Schema.Type.Parameterized] - final val ParamModifier = classOf[Schema.ParameterModifier] - final val Polymorphic = classOf[Schema.Type.Polymorphic] - final val Constant = classOf[Schema.Type.Constant] - final val Existential = classOf[Schema.Type.Existential] - final val Singleton = classOf[Schema.Type.Singleton] - final val Annotated = classOf[Schema.Type.Annotated] - final val MethodParameter = classOf[Schema.MethodParameter] - final val Val = classOf[Schema.ClassDefinition.Val] - final val Var = classOf[Schema.ClassDefinition.Var] - final val TypeAlias = classOf[Schema.ClassDefinition.TypeAlias] - final val TypeDeclaration = classOf[Schema.ClassDefinition.TypeDeclaration] - final val Def = classOf[Schema.ClassDefinition.Def] - final val PathComponent = classOf[Schema.Path.PathComponent] - final val Component = classOf[Schema.Path.PathComponent.ComponentCase] - final val ClassLike = classOf[Schema.ClassLike] - final val Structure = classOf[Schema.Type.Structure] - final val ClassLikeDef = classOf[Schema.ClassDefinition.ClassLikeDef] - final val ClassDefinition = classOf[Schema.ClassDefinition] - final val TypeParameter = classOf[Schema.TypeParameter] - final val Type = classOf[Schema.Type] - final val Projection = classOf[Schema.Type.Projection] - final val Access = classOf[Schema.Access] - final val Modifiers = classOf[Schema.Modifiers] - final val Severity = classOf[Schema.Severity] - final val UseScope = classOf[Schema.UseScope] - final val CompileOrder = classOf[Schema.CompileOrder] - final val Path = classOf[Schema.Path] - final val Super = classOf[Schema.Super] - final val MiniOptions = classOf[Schema.MiniOptions] - final val MiniSetup = classOf[Schema.MiniSetup] - final val CompilationOutput = classOf[Schema.Compilation.OutputCase] - final val MiniSetupOutput = classOf[Schema.MiniSetup.OutputCase] - final val Position = classOf[Schema.Position] - final val Problem = classOf[Schema.Problem] - final val Companions = classOf[Schema.Companions] - final val Relations = classOf[Schema.Relations] - final val Stamps = classOf[Schema.Stamps] - final val Compilations = classOf[Schema.Compilations] - final val SourceInfos = classOf[Schema.SourceInfos] - final val AnalyzedClass = classOf[Schema.AnalyzedClass] - final val Analysis = classOf[Schema.Analysis] - final val APIs = classOf[Schema.APIs] - final val APIsFile = classOf[Schema.APIsFile] - } - - object EmptyLazyCompanions extends Lazy[Companions] { - override def get(): Companions = - throw new IllegalArgumentException("No companions was stored!") - } - - object Feedback { - implicit class StringToException(str: String) { - def `!!`: Nothing = sys.error(str) - } - - object Writers { - final val UnexpectedEmptyOutput = - "Expected `Output` to be either `SingleOutput` or `MultipleOutput`." - } - - object Readers { - final val ReadError: String = "Protobuf read error" - - final def expectedBaseIn(clazz: Class[?]) = - expected("base type", clazz) - final def expectedTypeIn(clazz: Class[?]) = - expected("type", clazz) - final val ExpectedReturnTypeInDef = - expected("return type", Classes.Def) - final val ExpectedUpperBoundInTypeParameter = - expected("upper bound", Classes.TypeParameter) - final val ExpectedUpperBoundInTypeDeclaration = - expected("upper bound", Classes.TypeDeclaration) - final val ExpectedLowerBoundInTypeParameter = - expected("lower bound", Classes.TypeParameter) - final val ExpectedLowerBoundInTypeDeclaration = - expected("lower bound", Classes.TypeDeclaration) - final val ExpectedNonEmptyType = - expected(s"non empty type", Classes.Type) - final val ExpectedNonEmptyDefType = - expected(s"non empty `${Classes.ClassDefinition.getName}` type", Classes.Type) - final val ExpectedPathInSingleton = - expected("path", Classes.Singleton) - final val ExpectedPrefixInProjection = - expected("prefix", Classes.Projection) - final val ExpectedQualifierInAccess = - expected("qualifier", Classes.Access) - final val MissingModifiersInDef = - expected("modifiers", Classes.ClassDefinition) - final val MissingAccessInDef = - expected("access", Classes.ClassDefinition) - final val ExpectedValidAccessType = - expected("valid access type", Classes.Access) - final val ExpectedAccessInClassLike = - expected(Classes.Access, Classes.ClassLike) - final val ExpectedNonEmptyQualifier = - expected("non-empty qualifier", Classes.Access) - final val ExpectedCompanionsInAnalyzedClass = - expected(Classes.Companions, Classes.AnalyzedClass) - final val ExpectedPathInSuper = - expected(s"qualifier of type ${Classes.Path}", Classes.Super) - final val ExpectedMiniOptionsInSetup = - expected(Classes.MiniOptions, Classes.MiniSetup) - final val ExpectedOutputInCompilationOutput = - expected("non-empty output", Classes.CompilationOutput) - final val ExpectedOutputInMiniSetupOutput = - expected("non-empty output", Classes.MiniSetupOutput) - final val ExpectedPositionInProblem: String = - expected(Classes.Position, Classes.Problem) - final val ExpectedApisInApisFile: String = - expected(Classes.APIs, Classes.APIsFile) - - final def expected(culprit: Class[?], owner: Class[?]): String = - expected(s"`${culprit.getName}`", owner) - final def expected(something: String, owner: Class[?]): String = - s"$ReadError: Expected $something in `${owner.getName}`." - - final val UnrecognizedParamModifier = - unrecognized("param modifier", Classes.MethodParameter) - final val UnrecognizedVariance = - unrecognized("variance", Classes.TypeParameter) - final val UnrecognizedDefinitionType = - unrecognized("definition type", Classes.ClassLikeDef) - final def unrecognizedSeverity(id: Int) = - unrecognized(Classes.Severity, id.toString) - final def unrecognizedUseScope(id: Int) = - unrecognized(Classes.UseScope, id.toString) - final def unrecognizedOrder(id: Int) = - unrecognized(Classes.CompileOrder, id.toString) - - final def unrecognized[T](culprit: Class[?], value: String): String = - s"$ReadError: Unrecognized ${culprit.getName} with value `$value`." - final def unrecognized(culprit: Class[?], owner: Class[?]): String = - unrecognized(s"`${culprit.getName}`", owner) - final def unrecognized(something: String, owner: Class[?]): String = - s"$ReadError: Unrecognized $something in `${owner.getName}`." - } - } -} diff --git a/internal/zinc-persist/src/main/scala/sbt/internal/inc/binary/converters/ProtobufReaders.scala b/internal/zinc-persist/src/main/scala/sbt/internal/inc/binary/converters/ProtobufReaders.scala deleted file mode 100644 index 7e55dda250..0000000000 --- a/internal/zinc-persist/src/main/scala/sbt/internal/inc/binary/converters/ProtobufReaders.scala +++ /dev/null @@ -1,876 +0,0 @@ -/* - * Zinc - The incremental compiler for Scala. - * Copyright Scala Center, Lightbend, and Mark Harrah - * - * Licensed under Apache License 2.0 - * SPDX-License-Identifier: Apache-2.0 - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package sbt.internal.inc.binary.converters - -import java.nio.file.{ Path, Paths } -import java.util.{ List => JList, Map => JMap, HashMap => JHashMap } -import sbt.internal.inc.Relations.ClassDependencies -import sbt.internal.inc._ -import sbt.internal.inc.binary.converters.ProtobufDefaults.EmptyLazyCompanions -import sbt.util.InterfaceUtil -import xsbti.{ - Action, - DiagnosticCode, - DiagnosticRelatedInformation, - Position, - Problem, - Severity, - T2, - TextEdit, - UseScope, - VirtualFileRef, - WorkspaceEdit, -} -import xsbti.compile.{ CompileOrder, FileHash, MiniOptions, MiniSetup, Output, OutputGroup } -import xsbti.compile.analysis.{ Compilation, ReadMapper, SourceInfo, Stamp } -import sbt.internal.inc.binary.converters.ProtobufDefaults.Feedback.StringToException -import sbt.internal.inc.binary.converters.ProtobufDefaults.Feedback.{ Readers => ReadersFeedback } -import sbt.internal.inc.binary.converters.ProtobufDefaults.{ Classes, ReadersConstants } -import sbt.internal.util.Relation - -import scala.collection.JavaConverters._ -import xsbti.api._ -import ProtobufDefaults.{ MissingInt, MissingString } - -final class ProtobufReaders(mapper: ReadMapper, currentVersion: Schema.Version) { - def fromPathString(path: String): Path = Paths.get(path) - def fromPathStringV(path: String): VirtualFileRef = { - VirtualFileRef.of(path) - } - - def fromStampType(stampType: Schema.Stamps.StampType): Stamp = { - import sbt.internal.inc.{ EmptyStamp, LastModified, Hash } - stampType.getTypeCase match { - case Schema.Stamps.StampType.TypeCase.TYPE_NOT_SET => EmptyStamp - case Schema.Stamps.StampType.TypeCase.FARMHASH => - FarmHash.fromLong(stampType.getFarmHash.getHash) - case Schema.Stamps.StampType.TypeCase.HASH => - Hash.unsafeFromString(stampType.getHash.getHash) // fair assumption - case Schema.Stamps.StampType.TypeCase.LASTMODIFIED => - new LastModified(stampType.getLastModified.getMillis) - } - } - - def fromStamps(stamps: Schema.Stamps): Stamps = { - // Note that boilerplate here is inteded, abstraction is expensive - def fromBinarySchemaMap( - stamps: JMap[String, Schema.Stamps.StampType] - ): Map[VirtualFileRef, Stamp] = { - stamps.asScala.iterator.map { - case (path, schemaStamp) => - val file = fromPathStringV(path) - val newFile = mapper.mapBinaryFile(file) - val stamp = fromStampType(schemaStamp) - val newStamp = mapper.mapBinaryStamp(newFile, stamp) - newFile -> newStamp - }.toMap - } - - def fromSourceSchemaMap( - stamps: JMap[String, Schema.Stamps.StampType] - ): Map[VirtualFileRef, Stamp] = { - stamps.asScala.iterator.map { - case (path, schemaStamp) => - val file = fromPathStringV(path) - val newFile = mapper.mapSourceFile(file) - val stamp = fromStampType(schemaStamp) - val newStamp = mapper.mapSourceStamp(newFile, stamp) - newFile -> newStamp - }.toMap - } - - def fromProductSchemaMap( - stamps: JMap[String, Schema.Stamps.StampType] - ): Map[VirtualFileRef, Stamp] = { - stamps.asScala.iterator.map { - case (path, schemaStamp) => - val file = fromPathStringV(path) - val newFile = mapper.mapProductFile(file) - val stamp = fromStampType(schemaStamp) - val newStamp = mapper.mapProductStamp(newFile, stamp) - newFile -> newStamp - }.toMap - } - - val libraries = fromBinarySchemaMap(stamps.getBinaryStampsMap) - val sources = fromSourceSchemaMap(stamps.getSourceStampsMap) - val products = fromProductSchemaMap(stamps.getProductStampsMap) - Stamps( - products = products, - sources = sources, - libraries = libraries, - ) - } - - def fromOutputGroup(outputGroup: Schema.OutputGroup): OutputGroup = { - val sourcePath = fromPathString(outputGroup.getSourcePath) - val sourceDir = mapper.mapSourceDir(sourcePath) - val targetPath = fromPathString(outputGroup.getTargetPath) - val targetDir = mapper.mapOutputDir(targetPath) - CompileOutput.outputGroup(sourceDir, targetDir) - } - - def fromCompilationOutput(c: Schema.Compilation): Output = { - import Schema.Compilation.{ OutputCase => CompilationOutput } - c.getOutputCase match { - case CompilationOutput.SINGLEOUTPUT => - val single = c.getSingleOutput - val target = fromPathString(single.getTarget) - if (target == Analysis.dummyOutputPath) CompileOutput.empty - else { - val outputDir = mapper.mapOutputDir(target) - CompileOutput(outputDir) - } - case CompilationOutput.MULTIPLEOUTPUT => - val multiple = c.getMultipleOutput - val groups = multiple.getOutputGroupsList.asScala.iterator.map(fromOutputGroup).toArray - CompileOutput(groups) - case CompilationOutput.OUTPUT_NOT_SET => - ReadersFeedback.ExpectedOutputInCompilationOutput.!! - } - } - - def fromCompilation(compilation: Schema.Compilation): Compilation = { - val output = fromCompilationOutput(compilation) - new sbt.internal.inc.Compilation(compilation.getStartTimeMillis, output) - } - - def fromCompilations(compilations0: Schema.Compilations): Compilations = { - val compilations = compilations0.getCompilationsList.asScala.iterator.map(fromCompilation) - val castedCompilations = (compilations.map { case c: sbt.internal.inc.Compilation => c }).toSeq - Compilations.of(castedCompilations) - } - - def fromPosition(position: Schema.Position): Position = { - InterfaceUtil.position( - line0 = fromInt(position.getLine), - content = position.getLineContent, - offset0 = fromInt(position.getOffset), - pointer0 = fromInt(position.getPointer), - pointerSpace0 = fromString(position.getPointerSpace), - sourcePath0 = fromString(position.getSourcePath), - sourceFile0 = fromString(position.getSourceFilepath).map(fromPathString).map(_.toFile), - startOffset0 = fromInt(position.getStartOffset), - endOffset0 = fromInt(position.getEndOffset), - startLine0 = fromInt(position.getStartLine), - startColumn0 = fromInt(position.getStartColumn), - endLine0 = fromInt(position.getEndLine), - endColumn0 = fromInt(position.getEndColumn), - ) - } - - def fromSeverity(severity: Schema.Severity, id: Int): Severity = { - severity match { - case Schema.Severity.INFO => Severity.Info - case Schema.Severity.WARN => Severity.Warn - case Schema.Severity.ERROR => Severity.Error - case Schema.Severity.UNRECOGNIZED => ReadersFeedback.unrecognizedSeverity(id).!! - } - } - - private def fromString(value: String): Option[String] = - if (value == MissingString) None else Some(value) - - private def fromInt(value: Int): Option[Integer] = - if (value == MissingInt) None else Some(value) - - private def fromDiagnosticCode(diagnosticCode: Schema.DiagnosticCode): DiagnosticCode = - DiagnosticsUtil.diagnosticCode( - code = diagnosticCode.getCode(), - explanation = fromString(diagnosticCode.getExplanation()), - ) - - private def fromDiagnosticRelatedInformation(info: Schema.DiagnosticRelatedInformation) - : DiagnosticRelatedInformation = - DiagnosticsUtil.diagnosticRelatedInformation( - position = fromPosition(info.getPosition()), - message = info.getMessage(), - ) - - private def fromAction(action: Schema.Action): Action = - InterfaceUtil.action( - title = action.getTitle(), - description = fromString(action.getDescription()), - edit = fromWorkspaceEdit(action.getEdit()), - ) - - private def fromWorkspaceEdit(edit: Schema.WorkspaceEdit): WorkspaceEdit = - InterfaceUtil.workspaceEdit( - changes = edit.getChangesList().asScala.iterator.map(fromTextEdit).toList - ) - - private def fromTextEdit(edit: Schema.TextEdit): TextEdit = - InterfaceUtil.textEdit( - position = fromPosition(edit.getPosition()), - newText = edit.getNewText(), - ) - - def fromProblem(problem: Schema.Problem): Problem = { - val category = problem.getCategory - val message = problem.getMessage - val severity = fromSeverity(problem.getSeverity, problem.getSeverityValue) - val position = - if (problem.hasPosition) fromPosition(problem.getPosition) - else ReadersFeedback.ExpectedPositionInProblem.!! - val rendered = fromString(problem.getRendered) - val diagnosticCode = - if (problem.hasDiagnosticCode) Some(fromDiagnosticCode(problem.getDiagnosticCode())) - else None - val infos = problem.getDiagnosticRelatedInformationList().asScala.iterator - .map(fromDiagnosticRelatedInformation).toList - val actions = problem.getActionsList().asScala.iterator - .map(fromAction).toList - InterfaceUtil.problem( - cat = category, - pos = position, - msg = message, - sev = severity, - rendered = rendered, - diagnosticCode = diagnosticCode, - diagnosticRelatedInformation = infos, - actions = actions, - ) - } - - def fromSourceInfo(sourceInfo: Schema.SourceInfo): SourceInfo = { - val mainClasses = sourceInfo.getMainClassesList.asScala.toSeq - val reportedProblems = - sourceInfo.getReportedProblemsList.asScala.iterator.map(fromProblem).toSeq - val unreportedProblems = - sourceInfo.getUnreportedProblemsList.asScala.iterator.map(fromProblem).toSeq - SourceInfos.makeInfo( - reported = reportedProblems, - unreported = unreportedProblems, - mainClasses = mainClasses - ) - } - - def fromSourceInfos(sourceInfos0: Schema.SourceInfos): SourceInfos = { - val sourceInfos = sourceInfos0.getSourceInfosMap.asScala.iterator.map { - case (path, value) => - val file = mapper.mapSourceFile(fromPathStringV(path)) - val sourceInfo = fromSourceInfo(value) - file -> sourceInfo - } - SourceInfos.of(sourceInfos.toMap) - } - - def fromClasspathFileHash(fileHash: Schema.FileHash): FileHash = { - val hash = fileHash.getHash - val classpathEntry = fromPathString(fileHash.getPath) - val newClasspathEntry = mapper.mapClasspathEntry(classpathEntry) - FileHash.of(newClasspathEntry, hash) - } - - def fromMiniOptions(miniOptions: Schema.MiniOptions): MiniOptions = { - val classpathHash = - miniOptions.getClasspathHashList.asScala.iterator.map(fromClasspathFileHash).toArray - val javacOptions = - miniOptions.getJavacOptionsList.asScala.iterator.map(mapper.mapJavacOption).toArray - val scalacOptions = - miniOptions.getScalacOptionsList.asScala.iterator.map(mapper.mapScalacOption).toArray - MiniOptions.of(classpathHash, scalacOptions, javacOptions) - } - - def fromCompileOrder(compileOrder: Schema.CompileOrder, id: Int): CompileOrder = { - compileOrder match { - case Schema.CompileOrder.MIXED => CompileOrder.Mixed - case Schema.CompileOrder.JAVATHENSCALA => CompileOrder.JavaThenScala - case Schema.CompileOrder.SCALATHENJAVA => CompileOrder.ScalaThenJava - case Schema.CompileOrder.UNRECOGNIZED => ReadersFeedback.unrecognizedOrder(id).!! - } - } - - def fromStringTuple(tuple: Schema.Tuple): T2[String, String] = { - InterfaceUtil.t2(tuple.getFirst -> tuple.getSecond) - } - - def fromMiniSetupOutput(miniSetup: Schema.MiniSetup): Output = { - import Schema.MiniSetup.{ OutputCase => MiniSetupOutput } - miniSetup.getOutputCase match { - case MiniSetupOutput.SINGLEOUTPUT => - val single = miniSetup.getSingleOutput - val target = fromPathString(single.getTarget) - if (target == Analysis.dummyOutputPath) CompileOutput.empty - else { - val outputDir = mapper.mapOutputDir(target) - CompileOutput(outputDir) - } - case MiniSetupOutput.MULTIPLEOUTPUT => - val multiple = miniSetup.getMultipleOutput - val groups = multiple.getOutputGroupsList.asScala.iterator.map(fromOutputGroup).toArray - CompileOutput(groups) - case MiniSetupOutput.OUTPUT_NOT_SET => - ReadersFeedback.ExpectedOutputInCompilationOutput.!! - } - } - - def fromMiniSetup(miniSetup: Schema.MiniSetup): MiniSetup = { - val output = fromMiniSetupOutput(miniSetup) - val miniOptions = - if (miniSetup.hasMiniOptions) fromMiniOptions(miniSetup.getMiniOptions) - else ReadersFeedback.ExpectedMiniOptionsInSetup.!! - val compilerVersion = miniSetup.getCompilerVersion - val compileOrder = fromCompileOrder(miniSetup.getCompileOrder, miniSetup.getCompileOrderValue) - val storeApis = miniSetup.getStoreApis - val extra = miniSetup.getExtraList.asScala.iterator.map(fromStringTuple).toArray - val original = - MiniSetup.of( - output, // note this is a dummy value - miniOptions, - compilerVersion, - compileOrder, - storeApis, - extra - ) - mapper.mapMiniSetup(original) - } - - implicit class EfficientTraverse[T](seq: JList[T]) { - def toZincArray[R <: AnyRef: scala.reflect.ClassTag](f: T => R): Array[R] = { - seq.stream().map[R](x => f(x)).toArray[R](new Array[R](_)) - } - } - - implicit class OptionReader[T](option: Option[T]) { - def read[R](from: T => R, errorMessage: => String): R = - option.fold(errorMessage.!!)(from) - } - - def fromPath(path: Schema.Path): xsbti.api.Path = { - def fromPathComponent(pathComponent: Schema.Path.PathComponent): PathComponent = { - import ReadersFeedback.ExpectedPathInSuper - import Schema.Path.{ PathComponent => SchemaPath } - import SchemaPath.{ ComponentCase => SchemaComponent } - import Classes.{ Component, PathComponent } - pathComponent.getComponentCase match { - case SchemaComponent.ID => - val c = pathComponent.getId - Id.of(c.getId) - case SchemaComponent.SUPER => - val c = pathComponent.getSuper - val q = - if (c.hasQualifier) fromPath(c.getQualifier) - else ExpectedPathInSuper.!! - Super.of(q) - case SchemaComponent.THIS => ReadersConstants.This - case SchemaComponent.COMPONENT_NOT_SET => - ReadersFeedback.expected(Component, PathComponent).!! - } - } - val components = path.getComponentsList.toZincArray(fromPathComponent) - xsbti.api.Path.of(components) - } - - def fromAnnotation(annotation: Schema.Annotation): Annotation = { - def fromAnnotationArgument(argument: Schema.AnnotationArgument): AnnotationArgument = { - val name = argument.getName.intern() - val value = argument.getValue - AnnotationArgument.of(name, value) - } - - val arguments = annotation.getArgumentsList.toZincArray(fromAnnotationArgument) - val b = - if (annotation.hasBase) Some(annotation.getBase) - else None - val base = b.read(fromType, ReadersFeedback.expectedBaseIn(Classes.Annotation)) - Annotation.of(base, arguments) - } - - def fromStructure(tpe: Schema.Type.Structure): Structure = { - def `lazy`[T](value: T): Lazy[T] = SafeLazyProxy.strict(value) - val parents = `lazy`(tpe.getParentsList.toZincArray(fromType)) - val declared = `lazy`(tpe.getDeclaredList.toZincArray(fromClassDefinition)) - val inherited = `lazy`(tpe.getInheritedList.toZincArray(fromClassDefinition)) - Structure.of(parents, declared, inherited) - } - - def fromType(`type`: Schema.Type): Type = { - import ReadersFeedback.expectedBaseIn - def fromParameterRef(tpe: Schema.Type.ParameterRef): ParameterRef = { - ParameterRef.of(tpe.getId) - } - - def fromParameterized(tpe: Schema.Type.Parameterized): Parameterized = { - val baseType = - if (tpe.hasBaseType) fromType(tpe.getBaseType) - else expectedBaseIn(Classes.Parameterized).!! - val typeArguments = tpe.getTypeArgumentsList.toZincArray(fromType) - Parameterized.of(baseType, typeArguments) - } - - def fromPolymorphic(tpe: Schema.Type.Polymorphic): Polymorphic = { - val baseType = - if (tpe.hasBaseType) fromType(tpe.getBaseType) - else expectedBaseIn(Classes.Polymorphic).!! - val typeParameters = tpe.getTypeParametersList.toZincArray(fromTypeParameter) - Polymorphic.of(baseType, typeParameters) - } - - def fromConstant(tpe: Schema.Type.Constant): Constant = { - val baseType = - if (tpe.hasBaseType) fromType(tpe.getBaseType) - else expectedBaseIn(Classes.Constant).!! - val value = tpe.getValue - Constant.of(baseType, value) - } - - def fromExistential(tpe: Schema.Type.Existential): Existential = { - val b = - if (tpe.hasBaseType) Some(tpe.getBaseType) - else None - val baseType = b.read(fromType, expectedBaseIn(Classes.Existential)) - val clause = tpe.getClauseList.toZincArray(fromTypeParameter) - Existential.of(baseType, clause) - } - - def fromSingleton(tpe: Schema.Type.Singleton): Singleton = { - val path = - if (tpe.hasPath) fromPath(tpe.getPath) - else ReadersFeedback.ExpectedPathInSingleton.!! - Singleton.of(path) - } - - def fromProjection(tpe: Schema.Type.Projection): Projection = { - val id = tpe.getId - val prefix = - if (tpe.hasPrefix) fromType(tpe.getPrefix) - else ReadersFeedback.ExpectedPrefixInProjection.!! - Projection.of(prefix, id) - } - - def fromAnnotated(tpe: Schema.Type.Annotated): Annotated = { - val baseType = - if (tpe.hasBaseType) fromType(tpe.getBaseType) - else expectedBaseIn(Classes.Annotated).!! - val annotations = tpe.getAnnotationsList.toZincArray(fromAnnotation) - Annotated.of(baseType, annotations) - } - import Schema.Type.ValueCase - `type`.getValueCase match { - case ValueCase.PARAMETERREF => fromParameterRef(`type`.getParameterRef) - case ValueCase.PARAMETERIZED => fromParameterized(`type`.getParameterized) - case ValueCase.STRUCTURE => fromStructure(`type`.getStructure) - case ValueCase.POLYMORPHIC => fromPolymorphic(`type`.getPolymorphic) - case ValueCase.CONSTANT => fromConstant(`type`.getConstant) - case ValueCase.EXISTENTIAL => fromExistential(`type`.getExistential) - case ValueCase.SINGLETON => fromSingleton(`type`.getSingleton) - case ValueCase.PROJECTION => fromProjection(`type`.getProjection) - case ValueCase.ANNOTATED => fromAnnotated(`type`.getAnnotated) - case ValueCase.EMPTYTYPE => ReadersConstants.EmptyType - case ValueCase.VALUE_NOT_SET => ReadersFeedback.ExpectedNonEmptyType.!! - } - } - - def fromModifiers(modifiers: Schema.Modifiers): Modifiers = - InternalApiProxy.Modifiers(modifiers.getFlags) - - def fromAccess(access: Schema.Access): Access = { - def fromQualifier(qualifier: Schema.Qualifier): Qualifier = { - import Schema.Qualifier.{ TypeCase => QualifierType } - qualifier.getTypeCase match { - case QualifierType.IDQUALIFIER => - val q = qualifier.getIdQualifier - IdQualifier.of(q.getValue) - case QualifierType.THISQUALIFIER => ReadersConstants.ThisQualifier - case QualifierType.UNQUALIFIED => ReadersConstants.Unqualified - case QualifierType.TYPE_NOT_SET => ReadersFeedback.ExpectedNonEmptyQualifier.!! - } - } - - def readQualifier(qualifier: Option[Schema.Qualifier]): Qualifier = - qualifier.read(fromQualifier, ReadersFeedback.ExpectedQualifierInAccess) - - access.getTypeCase match { - case Schema.Access.TypeCase.PUBLIC => ReadersConstants.Public - case Schema.Access.TypeCase.PROTECTED => - val a = access.getProtected - Protected.of(readQualifier(if (a.hasQualifier) Some(a.getQualifier) else None)) - case Schema.Access.TypeCase.PRIVATE => - val a = access.getPrivate - Private.of(readQualifier(if (a.hasQualifier) Some(a.getQualifier) else None)) - case Schema.Access.TypeCase.TYPE_NOT_SET => ReadersFeedback.ExpectedValidAccessType.!! - } - } - - def fromDefinitionType(definitionType: Schema.DefinitionType): DefinitionType = { - definitionType match { - case Schema.DefinitionType.CLASSDEF => DefinitionType.ClassDef - case Schema.DefinitionType.MODULE => DefinitionType.Module - case Schema.DefinitionType.TRAIT => DefinitionType.Trait - case Schema.DefinitionType.PACKAGEMODULE => DefinitionType.PackageModule - case Schema.DefinitionType.UNRECOGNIZED => ReadersFeedback.UnrecognizedDefinitionType.!! - } - } - - def fromClassDefinition(classDefinition: Schema.ClassDefinition): ClassDefinition = { - import ReadersFeedback.{ MissingModifiersInDef, MissingAccessInDef, expectedTypeIn } - import ReadersFeedback.{ - ExpectedReturnTypeInDef, - ExpectedLowerBoundInTypeDeclaration, - ExpectedUpperBoundInTypeDeclaration - } - - val name = classDefinition.getName.intern() - val access = - if (classDefinition.hasAccess) fromAccess(classDefinition.getAccess) - else MissingAccessInDef.!! - val modifiers = - if (classDefinition.hasModifiers) fromModifiers(classDefinition.getModifiers) - else MissingModifiersInDef.!! - val annotations = classDefinition.getAnnotationsList.toZincArray(fromAnnotation) - - def fromParameterList(parameterList: Schema.ParameterList): ParameterList = { - def fromMethodParameter(methodParameter: Schema.MethodParameter): MethodParameter = { - def fromParameterModifier(modifier: Schema.ParameterModifier): ParameterModifier = { - modifier match { - case Schema.ParameterModifier.PLAIN => ParameterModifier.Plain - case Schema.ParameterModifier.BYNAME => ParameterModifier.ByName - case Schema.ParameterModifier.REPEATED => ParameterModifier.Repeated - case Schema.ParameterModifier.UNRECOGNIZED => - ReadersFeedback.UnrecognizedParamModifier.!! - } - } - val name = methodParameter.getName.intern() - val hasDefault = methodParameter.getHasDefault - val `type` = - if (methodParameter.hasType) fromType(methodParameter.getType) - else expectedTypeIn(Classes.MethodParameter).!! - val modifier = fromParameterModifier(methodParameter.getModifier) - MethodParameter.of(name, `type`, hasDefault, modifier) - } - - val isImplicit = parameterList.getIsImplicit - val parameters = parameterList.getParametersList.toZincArray(fromMethodParameter) - ParameterList.of(parameters, isImplicit) - } - - def fromClassLikeDef(defDef: Schema.ClassDefinition.ClassLikeDef): ClassLikeDef = { - val definitionType = fromDefinitionType(defDef.getDefinitionType) - val typeParameters = defDef.getTypeParametersList.toZincArray(fromTypeParameter) - ClassLikeDef.of(name, access, modifiers, annotations, typeParameters, definitionType) - } - - def fromDefDef(defDef: Schema.ClassDefinition.Def): Def = { - val returnType = - if (defDef.hasReturnType) fromType(defDef.getReturnType) - else ExpectedReturnTypeInDef.!! - val typeParameters = defDef.getTypeParametersList.toZincArray(fromTypeParameter) - val valueParameters = defDef.getValueParametersList.toZincArray(fromParameterList) - Def.of(name, access, modifiers, annotations, typeParameters, valueParameters, returnType) - } - - def fromValDef(valDef: Schema.ClassDefinition.Val): Val = { - val tpe = - if (valDef.hasType) fromType(valDef.getType) - else expectedTypeIn(Classes.Val).!! - Val.of(name, access, modifiers, annotations, tpe) - } - - def fromVarDef(varDef: Schema.ClassDefinition.Var): Var = { - val tpe = - if (varDef.hasType) fromType(varDef.getType) - else expectedTypeIn(Classes.Var).!! - Var.of(name, access, modifiers, annotations, tpe) - } - - def fromTypeAlias(typeAlias: Schema.ClassDefinition.TypeAlias): TypeAlias = { - val tpe = - if (typeAlias.hasType) fromType(typeAlias.getType) - else expectedTypeIn(Classes.TypeAlias).!! - val typeParameters = typeAlias.getTypeParametersList.toZincArray(fromTypeParameter) - TypeAlias.of(name, access, modifiers, annotations, typeParameters, tpe) - } - - def fromTypeDeclaration(decl: Schema.ClassDefinition.TypeDeclaration): TypeDeclaration = { - val lowerBound = - if (decl.hasLowerBound) fromType(decl.getLowerBound) - else ExpectedLowerBoundInTypeDeclaration.!! - val upperBound = - if (decl.hasUpperBound) fromType(decl.getUpperBound) - else ExpectedUpperBoundInTypeDeclaration.!! - val typeParams = decl.getTypeParametersList.toZincArray(fromTypeParameter) - TypeDeclaration.of(name, access, modifiers, annotations, typeParams, lowerBound, upperBound) - } - - import Schema.ClassDefinition.{ ExtraCase => DefType } - classDefinition.getExtraCase match { - case DefType.CLASSLIKEDEF => fromClassLikeDef(classDefinition.getClassLikeDef) - case DefType.DEFDEF => fromDefDef(classDefinition.getDefDef) - case DefType.VALDEF => fromValDef(classDefinition.getValDef) - case DefType.VARDEF => fromVarDef(classDefinition.getVarDef) - case DefType.TYPEALIAS => fromTypeAlias(classDefinition.getTypeAlias) - case DefType.TYPEDECLARATION => fromTypeDeclaration(classDefinition.getTypeDeclaration) - case DefType.EXTRA_NOT_SET => ReadersFeedback.ExpectedNonEmptyDefType.!! - } - } - - def fromTypeParameter(typeParameter: Schema.TypeParameter): TypeParameter = { - def fromVariance(variance: Schema.Variance): Variance = { - variance match { - case Schema.Variance.INVARIANT => Variance.Invariant - case Schema.Variance.COVARIANT => Variance.Covariant - case Schema.Variance.CONTRAVARIANT => Variance.Contravariant - case Schema.Variance.UNRECOGNIZED => ReadersFeedback.UnrecognizedVariance.!! - } - } - - import ReadersFeedback.{ ExpectedLowerBoundInTypeParameter, ExpectedUpperBoundInTypeParameter } - val id = typeParameter.getId - val annotations = typeParameter.getAnnotationsList.toZincArray(fromAnnotation) - val typeParameters = typeParameter.getTypeParametersList.toZincArray(fromTypeParameter) - val variance = fromVariance(typeParameter.getVariance) - val lowerBound = - if (typeParameter.hasLowerBound) fromType(typeParameter.getLowerBound) - else ExpectedLowerBoundInTypeParameter.!! - val upperBound = - if (typeParameter.hasUpperBound) fromType(typeParameter.getUpperBound) - else ExpectedUpperBoundInTypeParameter.!! - TypeParameter.of(id, annotations, typeParameters, variance, lowerBound, upperBound) - } - - def fromClassLike(classLike: Schema.ClassLike): ClassLike = { - def expectedMsg(msg: String) = ReadersFeedback.expected(msg, Classes.ClassLike) - def expected(clazz: Class[?]) = expectedMsg(clazz.getName) - val name = classLike.getName.intern() - val access = - if (classLike.hasAccess) fromAccess(classLike.getAccess) - else expected(Classes.Access).!! - val modifiers = - if (classLike.hasModifiers) fromModifiers(classLike.getModifiers) - else expected(Classes.Modifiers).!! - val annotations = classLike.getAnnotationsList.toZincArray(fromAnnotation) - - import SafeLazyProxy.{ strict => mkLazy } - val definitionType = fromDefinitionType(classLike.getDefinitionType) - val selfType = mkLazy( - if (classLike.hasSelfType) fromType(classLike.getSelfType) else expectedMsg("self type").!! - ) - val structure = mkLazy( - if (classLike.hasStructure) fromStructure(classLike.getStructure) - else expected(Classes.Structure).!! - ) - val savedAnnotations = classLike.getSavedAnnotationsList.asScala.toArray - val childrenOfSealedClass = classLike.getChildrenOfSealedClassList.toZincArray(fromType) - val topLevel = classLike.getTopLevel - val typeParameters = classLike.getTypeParametersList.toZincArray(fromTypeParameter) - ClassLike.of( - name, - access, - modifiers, - annotations, - definitionType, - selfType, - structure, - savedAnnotations, - childrenOfSealedClass, - topLevel, - typeParameters - ) - } - - def fromUseScope(useScope: Schema.UseScope, id: Int): UseScope = { - useScope match { - case Schema.UseScope.DEFAULT => UseScope.Default - case Schema.UseScope.IMPLICIT => UseScope.Implicit - case Schema.UseScope.PATMAT => UseScope.PatMatTarget - case Schema.UseScope.UNRECOGNIZED => ReadersFeedback.unrecognizedUseScope(id).!! - } - } - - def fromAnalyzedClass( - shouldStoreApis: Boolean, - stringTable: StringTable - )(analyzedClass: Schema.AnalyzedClass): AnalyzedClass = { - def fromCompanions(companions: Schema.Companions): Companions = { - def expected(msg: String) = ReadersFeedback.expected(msg, Classes.Companions) - val classApi = - if (companions.hasClassApi) fromClassLike(companions.getClassApi) - else expected("class api").!! - val objectApi = - if (companions.hasObjectApi) fromClassLike(companions.getObjectApi) - else expected("object api").!! - Companions.of(classApi, objectApi) - } - - def fromNameHash(nameHash: Schema.NameHash): NameHash = { - val name = stringTable.lookupOrEnter(nameHash.getName) - val hash = nameHash.getHash - val scope = fromUseScope(nameHash.getScope, nameHash.getScopeValue) - NameHash.of(name, scope, hash) - } - - import SafeLazyProxy.{ strict => mkLazy } - import ReadersFeedback.ExpectedCompanionsInAnalyzedClass - val compilationTs = analyzedClass.getCompilationTimestamp - val name = analyzedClass.getName.intern() - val api = - if (!shouldStoreApis) EmptyLazyCompanions - else - mkLazy( - if (analyzedClass.hasApi) fromCompanions(analyzedClass.getApi) - else ExpectedCompanionsInAnalyzedClass.!! - ) - - val apiHash = analyzedClass.getApiHash - // Default to 0 to avoid issues when comparing hashes from two different analysis formats - val extraHash = if (currentVersion == Schema.Version.V1) 0 else analyzedClass.getExtraHash - val nameHashes = analyzedClass.getNameHashesList.toZincArray(fromNameHash) - val hasMacro = analyzedClass.getHasMacro - val provenance = analyzedClass.getProvenance.intern - AnalyzedClass.of(compilationTs, name, api, apiHash, nameHashes, hasMacro, extraHash, provenance) - } - - private final val stringId = identity[String] _ - - private final val stringToSource = (path: String) => mapper.mapSourceFile(fromPathStringV(path)) - private final val stringToLibrary = (path: String) => mapper.mapBinaryFile(fromPathStringV(path)) - private final val stringToProd = (path: String) => mapper.mapProductFile(fromPathStringV(path)) - - def fromRelations(relations: Schema.Relations): Relations = { - - def fromMap[K, V]( - map: java.util.Map[String, Schema.Values], - fk: String => K, - fv: String => V - ): Relation[K, V] = { - val builder = new RelationBuilder[K, V] - for ((kString, vs) <- map.asScala) { - if (!vs.getValuesList.isEmpty) { - val k = fk(kString) - for (vString <- vs.getValuesList.asScala) { - builder(k) = fv(vString) - } - } - } - builder.result() - } - - def fromClassDependencies(classDependencies: Schema.ClassDependencies): ClassDependencies = { - val internal = fromMap(classDependencies.getInternalMap, stringId, stringId) - val external = fromMap(classDependencies.getExternalMap, stringId, stringId) - new ClassDependencies(internal, external) - } - - def expected(msg: String) = ReadersFeedback.expected(msg, Classes.Relations) - - val srcProd = fromMap(relations.getSrcProdMap, stringToSource, stringToProd) - val libraryDep = fromMap(relations.getLibraryDepMap, stringToSource, stringToLibrary) - val libraryClassName = - fromMap(relations.getLibraryClassNameMap, stringToLibrary, stringId) - val memberRef = - if (relations.hasMemberRef) fromClassDependencies(relations.getMemberRef) - else expected("member refs").!! - val inheritance = - if (relations.hasInheritance) fromClassDependencies(relations.getInheritance) - else expected("inheritance").!! - val localInheritance = - if (relations.hasLocalInheritance) fromClassDependencies(relations.getLocalInheritance) - else expected("local inheritance").!! - val macroExpansion = - if (relations.hasMacroExpansion) fromClassDependencies(relations.getMacroExpansion) - else new ClassDependencies(Relation.empty, Relation.empty) - val classes = fromMap(relations.getClassesMap, stringToSource, stringId) - val productClassName = - fromMap(relations.getProductClassNameMap, stringId, stringId) - val names = UsedNames.fromJavaMap(relations.getNamesMap) - val internal = InternalDependencies( - Map( - DependencyContext.DependencyByMemberRef -> memberRef.internal, - DependencyContext.DependencyByInheritance -> inheritance.internal, - DependencyContext.LocalDependencyByInheritance -> localInheritance.internal, - DependencyContext.DependencyByMacroExpansion -> macroExpansion.internal, - ) - ) - val external = ExternalDependencies( - Map( - DependencyContext.DependencyByMemberRef -> memberRef.external, - DependencyContext.DependencyByInheritance -> inheritance.external, - DependencyContext.LocalDependencyByInheritance -> localInheritance.external, - DependencyContext.DependencyByMacroExpansion -> macroExpansion.external, - ) - ) - Relations.make( - srcProd, - libraryDep, - libraryClassName, - internal, - external, - classes, - names, - productClassName - ) - } - - def fromApis(shouldStoreApis: Boolean)(apis: Schema.APIs): APIs = { - val stringTable = new StringTable - val internal = - apis.getInternalMap.asScala.iterator.map { - case (k, v) => k -> fromAnalyzedClass(shouldStoreApis, stringTable)(v) - }.toMap - val external = - apis.getExternalMap.asScala.iterator.map { - case (k, v) => k -> fromAnalyzedClass(shouldStoreApis, stringTable)(v) - }.toMap - APIs(internal = internal, external = external) - } - - def fromApisFile(apisFile: Schema.APIsFile, shouldStoreApis: Boolean): (APIs, Schema.Version) = { - val apis = - if (apisFile.hasApis) fromApis(shouldStoreApis)(apisFile.getApis) - else ReadersFeedback.ExpectedApisInApisFile.!! - val version = apisFile.getVersion - apis -> version - } - - def fromAnalysis(analysis: Schema.Analysis): Analysis = { - def expected(clazz: Class[?]) = ReadersFeedback.expected(clazz, Classes.Analysis) - val stamps = - if (analysis.hasStamps) fromStamps(analysis.getStamps) - else expected(Classes.Stamps).!! - val relations = - if (analysis.hasRelations) fromRelations(analysis.getRelations) - else expected(Classes.Relations).!! - val sourceInfos = - if (analysis.hasSourceInfos) fromSourceInfos(analysis.getSourceInfos) - else expected(Classes.SourceInfos).!! - val compilations = - if (analysis.hasCompilations) fromCompilations(analysis.getCompilations) - else expected(Classes.Compilations).!! - Analysis.Empty.copy( - stamps = stamps, - relations = relations, - infos = sourceInfos, - compilations = compilations - ) - } - - def fromAnalysisFile(analysisFile: Schema.AnalysisFile): (Analysis, MiniSetup, Schema.Version) = { - val version = analysisFile.getVersion - val analysis = - if (analysisFile.hasAnalysis) fromAnalysis(analysisFile.getAnalysis) - else s"The analysis file from format ${version} could not be read.".!! - val miniSetup = - if (analysisFile.hasMiniSetup) fromMiniSetup(analysisFile.getMiniSetup) - else s"The mini setup from format ${version} could not be read.".!! - (analysis, miniSetup, version) - } - private class StringTable { - private val strings = new JHashMap[String, String]() - def lookupOrEnter(string: String): String = { - strings.putIfAbsent(string, string) match { - case null => string - case v => v - } - } - } -} diff --git a/internal/zinc-persist/src/main/scala/sbt/internal/inc/binary/converters/ProtobufWriters.scala b/internal/zinc-persist/src/main/scala/sbt/internal/inc/binary/converters/ProtobufWriters.scala deleted file mode 100644 index 9cf9d0f16f..0000000000 --- a/internal/zinc-persist/src/main/scala/sbt/internal/inc/binary/converters/ProtobufWriters.scala +++ /dev/null @@ -1,826 +0,0 @@ -/* - * Zinc - The incremental compiler for Scala. - * Copyright Scala Center, Lightbend, and Mark Harrah - * - * Licensed under Apache License 2.0 - * SPDX-License-Identifier: Apache-2.0 - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package sbt.internal.inc.binary.converters - -import java.io.File -import java.nio.file.Path - -import scala.collection.JavaConverters._ -import sbt.internal.inc._ -import xsbti.{ - Action, - DiagnosticCode, - DiagnosticRelatedInformation, - Position, - Problem, - Severity, - T2, - TextEdit, - UseScope, - VirtualFileRef, - WorkspaceEdit, -} -import xsbti.compile.analysis.{ SourceInfo, Stamp, WriteMapper } -import sbt.internal.inc.binary.converters.ProtobufDefaults.Feedback.{ Writers => WritersFeedback } -import sbt.internal.inc.binary.converters.ProtobufDefaults.WritersConstants -import xsbti.api.{ Private, _ } -import xsbti.compile.{ - CompileOrder, - FileHash, - MiniOptions, - MiniSetup, - MultipleOutput, - Output, - OutputGroup, - SingleOutput -} - -final class ProtobufWriters(mapper: WriteMapper) { - def toStringPath(file: File): String = { - file.toPath.toString - } - def toStringPath(file: Path): String = { - file.toString - } - def toStringPathV(file: VirtualFileRef): String = { - file.id - } - - def toStampType(stamp: Stamp): Schema.Stamps.StampType = { - val s0 = Schema.Stamps.StampType.newBuilder - stamp match { - case hash: FarmHash => - val x = Schema.FarmHash.newBuilder - .setHash(hash.hashValue) - .build - s0.setFarmHash(x) - case hash: Hash => - val x = Schema.Hash.newBuilder - .setHash(hash.hexHash) - .build - s0.setHash(x) - case lm: LastModified => - val x = Schema.LastModified.newBuilder - .setMillis(lm.value) - .build - s0.setLastModified(x) - case _: Stamp => s0 - } - s0.build - } - - def toStamps(stamps: Stamps): Schema.Stamps = { - // Note that boilerplate here is inteded, abstraction is expensive - def toBinarySchemaMap( - data: Map[VirtualFileRef, Stamp] - ): Iterator[(String, Schema.Stamps.StampType)] = { - data.iterator.map { - case (binaryFile, stamp) => - val newBinaryFile = mapper.mapBinaryFile(binaryFile) - val newPath = toStringPathV(newBinaryFile) - val newBinaryStamp = mapper.mapBinaryStamp(binaryFile, stamp) - val newStamp = toStampType(newBinaryStamp) - newPath -> newStamp - } - } - - def toSourceSchemaMap( - data: Map[VirtualFileRef, Stamp] - ): Iterator[(String, Schema.Stamps.StampType)] = { - data.iterator.map { - case (sourceFile, stamp) => - val newSourceFile = mapper.mapSourceFile(sourceFile) - val newPath = toStringPathV(newSourceFile) - val newSourceStamp = mapper.mapSourceStamp(sourceFile, stamp) - val newStamp = toStampType(newSourceStamp) - newPath -> newStamp - } - } - - def toProductSchemaMap( - data: Map[VirtualFileRef, Stamp] - ): Iterator[(String, Schema.Stamps.StampType)] = { - data.iterator.map { - case (productFile, stamp) => - val newProductFile = mapper.mapProductFile(productFile) - val newPath = toStringPathV(newProductFile) - val newProductStamp = mapper.mapProductStamp(productFile, stamp) - val newStamp = toStampType(newProductStamp) - newPath -> newStamp - } - } - - val binaryStamps = toBinarySchemaMap(stamps.libraries) - val sourceStamps = toSourceSchemaMap(stamps.sources) - val productStamps = toProductSchemaMap(stamps.products) - - val builder = Schema.Stamps.newBuilder - binaryStamps.foreach { case (k, v) => builder.putBinaryStamps(k, v) } - sourceStamps.foreach { case (k, v) => builder.putSourceStamps(k, v) } - productStamps.foreach { case (k, v) => builder.putProductStamps(k, v) } - builder.build - } - - def toOutputGroup(outputGroup: OutputGroup): Schema.OutputGroup = { - val newSource = mapper.mapSourceDir(outputGroup.getSourceDirectoryAsPath) - val newTarget = mapper.mapOutputDir(outputGroup.getOutputDirectoryAsPath) - val sourcePath = toStringPath(newSource) - val targetPath = toStringPath(newTarget) - Schema.OutputGroup.newBuilder - .setSourcePath(sourcePath) - .setTargetPath(targetPath) - .build - } - - def setCompilationOutput( - output: Output, - builder: Schema.Compilation.Builder - ): Schema.Compilation.Builder = { - output match { - case single0: SingleOutput => - val newOutputDir = mapper.mapOutputDir(single0.getOutputDirectoryAsPath) - val targetPath = toStringPath(newOutputDir) - val single = Schema.SingleOutput.newBuilder.setTarget(targetPath).build - builder.setSingleOutput(single) - case multiple0: MultipleOutput => - val multipleBuilder = Schema.MultipleOutput.newBuilder - multiple0.getOutputGroups.foreach(g => multipleBuilder.addOutputGroups(toOutputGroup(g))) - builder.setMultipleOutput(multipleBuilder.build) - case _ => sys.error(WritersFeedback.UnexpectedEmptyOutput) - } - } - - def toCompilation(compilation: Compilation): Schema.Compilation = { - val builder = Schema.Compilation.newBuilder - val startTimeMillis = compilation.getStartTime - setCompilationOutput(compilation.getOutput, builder) - .setStartTimeMillis(startTimeMillis) - .build - } - - def toCompilations(compilations0: Compilations): Schema.Compilations = { - val builder = Schema.Compilations.newBuilder - compilations0.allCompilations.foreach(c => builder.addCompilations(toCompilation(c))) - builder.build - } - - import ProtobufDefaults.{ MissingString, MissingInt } - import sbt.internal.inc.JavaInterfaceUtil._ - def toPosition(position: Position): Schema.Position = - Schema.Position.newBuilder - .setLine(position.line.toOption.fold(MissingInt)(_.toInt)) - .setOffset(position.offset.toOption.fold(MissingInt)(_.toInt)) - .setLineContent(position.lineContent) - .setPointer(position.pointer.toOption.fold(MissingInt)(_.toInt)) - .setPointerSpace(position.pointerSpace.toOption.getOrElse(MissingString)) - .setSourcePath(position.sourcePath.toOption.getOrElse(MissingString)) - .setSourceFilepath(position.sourceFile.toOption.fold(MissingString)(toStringPath)) - .setStartOffset(position.startOffset.toOption.fold(MissingInt)(_.toInt)) - .setEndOffset(position.endOffset.toOption.fold(MissingInt)(_.toInt)) - .setStartLine(position.startLine.toOption.fold(MissingInt)(_.toInt)) - .setStartColumn(position.startColumn.toOption.fold(MissingInt)(_.toInt)) - .setEndLine(position.endLine.toOption.fold(MissingInt)(_.toInt)) - .setEndColumn(position.endColumn.toOption.fold(MissingInt)(_.toInt)) - .build - - def toSeverity(severity: Severity): Schema.Severity = - severity match { - case Severity.Info => Schema.Severity.INFO - case Severity.Warn => Schema.Severity.WARN - case Severity.Error => Schema.Severity.ERROR - } - - def toProblem(problem: Problem): Schema.Problem = { - val category = problem.category() - val message = problem.message() - val position = toPosition(problem.position()) - val severity = toSeverity(problem.severity()) - val builder = Schema.Problem.newBuilder - .setCategory(category) - .setMessage(message) - .setPosition(position) - .setSeverity(severity) - problem.rendered.toOption.foreach(r => builder.setRendered(r)) - problem.diagnosticCode.toOption.foreach(d => builder.setDiagnosticCode(toDiagnosticCode(d))) - problem.diagnosticRelatedInformation.asScala - .foreach(d => builder.addDiagnosticRelatedInformation(toDiagnosticRelatedInformation(d))) - problem.actions.asScala.foreach(a => builder.addActions(toAction(a))) - builder.build - } - - def toAction(action: Action): Schema.Action = { - val edit = toWorkspaceEdit(action.edit()) - val builder = Schema.Action.newBuilder - .setTitle(action.title) - .setEdit(edit) - action.description.toOption.foreach(d => builder.setDescription(d)) - builder.build - } - - def toWorkspaceEdit(edit: WorkspaceEdit): Schema.WorkspaceEdit = { - val builder = Schema.WorkspaceEdit.newBuilder - edit.changes.asScala.foreach(c => builder.addChanges(toTextEdit(c))) - builder.build - } - - def toTextEdit(edit: TextEdit): Schema.TextEdit = { - val builder = Schema.TextEdit.newBuilder - .setPosition(toPosition(edit.position)) - .setNewText(edit.newText) - builder.build - } - - def toDiagnosticCode(diagnosticCode: DiagnosticCode): Schema.DiagnosticCode = { - val builder = Schema.DiagnosticCode.newBuilder - .setCode(diagnosticCode.code()) - diagnosticCode.explanation().toOption.foreach(d => builder.setExplanation(d)) - builder.build - } - - def toDiagnosticRelatedInformation(info: DiagnosticRelatedInformation) - : Schema.DiagnosticRelatedInformation = { - val builder = Schema.DiagnosticRelatedInformation.newBuilder - builder.setPosition(toPosition(info.position())) - builder.setMessage(info.message()) - builder.build - } - - def toSourceInfo(sourceInfo: SourceInfo): Schema.SourceInfo = { - val builder = Schema.SourceInfo.newBuilder - sourceInfo.getMainClasses.foreach(c => builder.addMainClasses(c)) - sourceInfo.getReportedProblems.foreach(p => builder.addReportedProblems(toProblem(p))) - sourceInfo.getUnreportedProblems.foreach(p => builder.addUnreportedProblems(toProblem(p))) - builder.build - } - - def toSourceInfos(sourceInfos0: SourceInfos): Schema.SourceInfos = { - val sourceInfos = sourceInfos0.allInfos.iterator.map { - case (file, sourceInfo0) => - toStringPathV(mapper.mapSourceFile(file)) -> toSourceInfo(sourceInfo0) - } - val builder = Schema.SourceInfos.newBuilder - sourceInfos.foreach { case (k, v) => builder.putSourceInfos(k, v) } - builder.build - } - - def toClasspathFileHash(fileHash: FileHash): Schema.FileHash = { - val newClasspathEntry = mapper.mapClasspathEntry(fileHash.file()) - val path = toStringPath(newClasspathEntry) - val hash = fileHash.hash() - Schema.FileHash.newBuilder - .setPath(path) - .setHash(hash) - .build - } - - def toMiniOptions(miniOptions: MiniOptions): Schema.MiniOptions = { - val builder = Schema.MiniOptions.newBuilder - miniOptions.classpathHash.foreach(h => builder.addClasspathHash(toClasspathFileHash(h))) - miniOptions.javacOptions().foreach(o => builder.addJavacOptions(mapper.mapJavacOption(o))) - miniOptions.scalacOptions().foreach(o => builder.addScalacOptions(mapper.mapScalacOption(o))) - builder.build - } - - def toCompileOrder(compileOrder: CompileOrder): Schema.CompileOrder = { - compileOrder match { - case CompileOrder.Mixed => Schema.CompileOrder.MIXED - case CompileOrder.JavaThenScala => Schema.CompileOrder.JAVATHENSCALA - case CompileOrder.ScalaThenJava => Schema.CompileOrder.SCALATHENJAVA - } - } - - def toStringTuple(tuple: T2[String, String]): Schema.Tuple = { - Schema.Tuple.newBuilder - .setFirst(tuple.get1()) - .setSecond(tuple.get2()) - .build - } - - def setMiniSetupOutput( - output: Output, - builder: Schema.MiniSetup.Builder - ): Schema.MiniSetup.Builder = - output match { - case single0: SingleOutput => - val newOutputDir = mapper.mapOutputDir(single0.getOutputDirectoryAsPath) - val targetPath = toStringPath(newOutputDir) - val single = Schema.SingleOutput.newBuilder.setTarget(targetPath).build - builder.setSingleOutput(single) - case multiple0: MultipleOutput => - val multipleBuilder = Schema.MultipleOutput.newBuilder - multiple0.getOutputGroups.foreach(g => multipleBuilder.addOutputGroups(toOutputGroup(g))) - builder.setMultipleOutput(multipleBuilder.build) - case CompileOutput.empty => - val dummy = - Schema.SingleOutput.newBuilder.setTarget(toStringPath(Analysis.dummyOutputPath)).build - builder.setSingleOutput(dummy) - } - - def toMiniSetup(miniSetup0: MiniSetup): Schema.MiniSetup = { - val builder = Schema.MiniSetup.newBuilder - val miniSetup = mapper.mapMiniSetup(miniSetup0) - val miniOptions = toMiniOptions(miniSetup.options()) - val compilerVersion = miniSetup.compilerVersion() - val compileOrder = toCompileOrder(miniSetup.order()) - val storeApis = miniSetup.storeApis() - val miniBuilder = setMiniSetupOutput(miniSetup.output(), builder) - .setMiniOptions(miniOptions) - .setCompilerVersion(compilerVersion) - .setCompileOrder(compileOrder) - .setStoreApis(storeApis) - miniSetup.extra().foreach(e => builder.addExtra(toStringTuple(e))) - miniBuilder.build - } - - def toPath(path: xsbti.api.Path): Schema.Path = { - def toPathComponent(pathComponent: PathComponent): Schema.Path.PathComponent = { - val builder0 = Schema.Path.PathComponent.newBuilder - val builder = pathComponent match { - case c: Id => - builder0.setId(Schema.Id.newBuilder.setId(c.id).build) - case c: Super => - builder0.setSuper(Schema.Super.newBuilder.setQualifier(toPath(c.qualifier))) - case _: This => - builder0.setThis(WritersConstants.This) - } - builder.build - } - val builder = Schema.Path.newBuilder - path.components().foreach(c => builder.addComponents(toPathComponent(c))) - builder.build - } - - def toAnnotation(annotation: Annotation): Schema.Annotation = { - def toAnnotationArgument(annotationArgument: AnnotationArgument): Schema.AnnotationArgument = - Schema.AnnotationArgument.newBuilder - .setName(annotationArgument.name()) - .setValue(annotationArgument.value()) - .build - - val base = toType(annotation.base()) - val builder = Schema.Annotation.newBuilder.setBase(base) - annotation.arguments().foreach(a => builder.addArguments(toAnnotationArgument(a))) - builder.build - } - - def toStructure(tpe: Structure): Schema.Type.Structure = { - val builder = Schema.Type.Structure.newBuilder - tpe.declared().foreach(t => builder.addDeclared(toClassDefinition(t))) - tpe.inherited().foreach(i => builder.addInherited(toClassDefinition(i))) - tpe.parents().foreach(p => builder.addParents(toType(p))) - builder.build - } - - def toType(`type`: Type): Schema.Type = { - def toExistential(tpe: Existential): Schema.Type.Existential = { - val baseType = toType(tpe.baseType()) - val builder = Schema.Type.Existential.newBuilder.setBaseType(baseType) - tpe.clause().foreach(c => builder.addClause(toTypeParameter(c))) - builder.build - } - - def toProjection(tpe: Projection): Schema.Type.Projection = { - val id = tpe.id() - val prefix = toType(tpe.prefix()) - Schema.Type.Projection.newBuilder - .setId(id) - .setPrefix(prefix) - .build - } - - def toPolymorphic(tpe: Polymorphic): Schema.Type.Polymorphic = { - val baseType = toType(tpe.baseType()) - val builder = Schema.Type.Polymorphic.newBuilder.setBaseType(baseType) - tpe.parameters().foreach(p => builder.addTypeParameters(toTypeParameter(p))) - builder.build - } - - def toParameterRef(tpe: ParameterRef): Schema.Type.ParameterRef = - Schema.Type.ParameterRef.newBuilder - .setId(tpe.id()) - .build - - def toParameterized(tpe: Parameterized): Schema.Type.Parameterized = { - val baseType = toType(tpe.baseType()) - val builder = Schema.Type.Parameterized.newBuilder.setBaseType(baseType) - tpe.typeArguments().foreach(a => builder.addTypeArguments(toType(a))) - builder.build - } - - def toSingleton(tpe: Singleton): Schema.Type.Singleton = - Schema.Type.Singleton.newBuilder - .setPath(toPath(tpe.path())) - .build - - def toConstant(tpe: Constant): Schema.Type.Constant = { - val baseType = toType(tpe.baseType()) - val value = tpe.value() - Schema.Type.Constant.newBuilder - .setBaseType(baseType) - .setValue(value) - .build - } - - def toAnnotated(tpe: Annotated): Schema.Type.Annotated = { - val baseType = toType(tpe.baseType()) - val builder = Schema.Type.Annotated.newBuilder.setBaseType(baseType) - tpe.annotations().foreach(a => builder.addAnnotations(toAnnotation(a))) - builder.build - } - - val builder = Schema.Type.newBuilder - `type` match { - case tpe: ParameterRef => builder.setParameterRef(toParameterRef(tpe)) - case tpe: Parameterized => builder.setParameterized(toParameterized(tpe)) - case tpe: Structure => builder.setStructure(toStructure(tpe)) - case tpe: Polymorphic => builder.setPolymorphic(toPolymorphic(tpe)) - case tpe: Constant => builder.setConstant(toConstant(tpe)) - case tpe: Existential => builder.setExistential(toExistential(tpe)) - case tpe: Singleton => builder.setSingleton(toSingleton(tpe)) - case tpe: Projection => builder.setProjection(toProjection(tpe)) - case tpe: Annotated => builder.setAnnotated(toAnnotated(tpe)) - case _: EmptyType => builder.setEmptyType(WritersConstants.EmptyType) - } - builder.build - } - - def toDefinitionType(definitionType: DefinitionType): Schema.DefinitionType = { - definitionType match { - case DefinitionType.ClassDef => Schema.DefinitionType.CLASSDEF - case DefinitionType.Module => Schema.DefinitionType.MODULE - case DefinitionType.Trait => Schema.DefinitionType.TRAIT - case DefinitionType.PackageModule => Schema.DefinitionType.PACKAGEMODULE - } - } - - def toAccess(access: Access): Schema.Access = { - def toQualifier(qualifier: Qualifier): Schema.Qualifier = { - import WritersConstants.{ ThisQualifier, Unqualified } - val builder = Schema.Qualifier.newBuilder - qualifier match { - case q: IdQualifier => - builder.setIdQualifier(Schema.IdQualifier.newBuilder.setValue(q.value()).build) - case _: ThisQualifier => builder.setThisQualifier(ThisQualifier) - case _: Unqualified => builder.setUnqualified(Unqualified) - } - builder.build - } - import WritersConstants.PublicAccess - val builder = Schema.Access.newBuilder - access match { - case _: Public => builder.setPublic(PublicAccess) - case qualified: Qualified => - val qualifier = toQualifier(qualified.qualifier()) - qualified match { - case _: Private => - builder.setPrivate(Schema.Private.newBuilder.setQualifier(qualifier).build) - case _: Protected => - builder.setProtected(Schema.Protected.newBuilder.setQualifier(qualifier).build) - } - } - builder.build - } - - def toModifiers(modifiers: Modifiers): Schema.Modifiers = - Schema.Modifiers.newBuilder - .setFlags(modifiers.raw().toInt) - .build - - def toClassDefinition(classDefinition: ClassDefinition): Schema.ClassDefinition = { - - def toParameterList(parameterList: ParameterList): Schema.ParameterList = { - def toMethodParameter(methodParameter: MethodParameter): Schema.MethodParameter = { - def toParameterModifier(modifier: ParameterModifier): Schema.ParameterModifier = { - modifier match { - case ParameterModifier.Plain => Schema.ParameterModifier.PLAIN - case ParameterModifier.ByName => Schema.ParameterModifier.BYNAME - case ParameterModifier.Repeated => Schema.ParameterModifier.REPEATED - } - } - val name = methodParameter.name() - val hasDefault = methodParameter.hasDefault() - val `type` = toType(methodParameter.tpe()) - val modifier = toParameterModifier(methodParameter.modifier()) - Schema.MethodParameter.newBuilder - .setName(name) - .setType(`type`) - .setHasDefault(hasDefault) - .setModifier(modifier) - .build - } - - val isImplicit = parameterList.isImplicit() - val builder = Schema.ParameterList.newBuilder.setIsImplicit(isImplicit) - parameterList.parameters().foreach(p => builder.addParameters(toMethodParameter(p))) - builder.build - } - - def toClassLikeDef(classLikeDef: ClassLikeDef): Schema.ClassDefinition.ClassLikeDef = { - val definitionType = toDefinitionType(classLikeDef.definitionType()) - val builder = Schema.ClassDefinition.ClassLikeDef.newBuilder.setDefinitionType(definitionType) - classLikeDef.typeParameters().foreach(p => builder.addTypeParameters(toTypeParameter(p))) - builder.build - } - - def toValDef(valDef: Val): Schema.ClassDefinition.Val = - Schema.ClassDefinition.Val.newBuilder - .setType(toType(valDef.tpe)) - .build - - def toVarDef(varDef: Var): Schema.ClassDefinition.Var = - Schema.ClassDefinition.Var.newBuilder - .setType(toType(varDef.tpe)) - .build - - def toDefDef(defDef: Def): Schema.ClassDefinition.Def = { - val returnType = toType(defDef.returnType) - val builder = Schema.ClassDefinition.Def.newBuilder.setReturnType(returnType) - defDef.typeParameters().foreach(p => builder.addTypeParameters(toTypeParameter(p))) - defDef.valueParameters().foreach(p => builder.addValueParameters(toParameterList(p))) - builder.build - } - - def toTypeAlias(typeAlias: TypeAlias): Schema.ClassDefinition.TypeAlias = { - val `type` = toType(typeAlias.tpe()) - val builder = Schema.ClassDefinition.TypeAlias.newBuilder.setType(`type`) - typeAlias.typeParameters().foreach(p => builder.addTypeParameters(toTypeParameter(p))) - builder.build - } - - def toTypeDeclaration( - typeDeclaration: TypeDeclaration - ): Schema.ClassDefinition.TypeDeclaration = { - val lowerBound = toType(typeDeclaration.lowerBound()) - val upperBound = toType(typeDeclaration.upperBound()) - val builder = Schema.ClassDefinition.TypeDeclaration.newBuilder - .setLowerBound(lowerBound) - .setUpperBound(upperBound) - typeDeclaration.typeParameters().foreach(p => builder.addTypeParameters(toTypeParameter(p))) - builder.build - } - - val builder = Schema.ClassDefinition.newBuilder - val name = classDefinition.name() - val access = toAccess(classDefinition.access()) - val modifiers = toModifiers(classDefinition.modifiers()) - classDefinition match { - case classLikeDef: ClassLikeDef => builder.setClassLikeDef(toClassLikeDef(classLikeDef)) - case valDef: Val => builder.setValDef(toValDef(valDef)) - case varDef: Var => builder.setVarDef(toVarDef(varDef)) - case defDef: Def => builder.setDefDef(toDefDef(defDef)) - case typeAlias: TypeAlias => builder.setTypeAlias(toTypeAlias(typeAlias)) - case typeDeclaration: TypeDeclaration => - builder.setTypeDeclaration(toTypeDeclaration(typeDeclaration)) - } - val resultBuilder = builder - .setName(name) - .setAccess(access) - .setModifiers(modifiers) - classDefinition.annotations().foreach(a => builder.addAnnotations(toAnnotation(a))) - resultBuilder.build - } - - def toTypeParameter(typeParameter: TypeParameter): Schema.TypeParameter = { - def toVariance(variance: Variance): Schema.Variance = { - variance match { - case Variance.Invariant => Schema.Variance.INVARIANT - case Variance.Covariant => Schema.Variance.COVARIANT - case Variance.Contravariant => Schema.Variance.CONTRAVARIANT - } - } - - val id = typeParameter.id() - val variance = toVariance(typeParameter.variance()) - val lowerBound = toType(typeParameter.lowerBound()) - val upperBound = toType(typeParameter.upperBound()) - val builder = Schema.TypeParameter.newBuilder - .setId(id) - .setVariance(variance) - .setLowerBound(lowerBound) - .setUpperBound(upperBound) - typeParameter.annotations().foreach(a => builder.addAnnotations(toAnnotation(a))) - typeParameter.typeParameters().foreach(p => builder.addTypeParameters(toTypeParameter(p))) - builder.build - } - - def toClassLike(classLike: ClassLike): Schema.ClassLike = { - val name = classLike.name() - val access = toAccess(classLike.access()) - val modifiers = toModifiers(classLike.modifiers()) - - val definitionType = toDefinitionType(classLike.definitionType()) - val selfType = toType(classLike.selfType()) - val structure = toStructure(classLike.structure()) - val savedAnnotations = classLike.savedAnnotations() - val topLevel = classLike.topLevel() - val builder = Schema.ClassLike.newBuilder - .setName(name) - .setAccess(access) - .setModifiers(modifiers) - .setDefinitionType(definitionType) - .setSelfType(selfType) - .setStructure(structure) - .setTopLevel(topLevel) - classLike.annotations().foreach(a => builder.addAnnotations(toAnnotation(a))) - savedAnnotations.foreach(a => builder.addSavedAnnotations(a)) - classLike.childrenOfSealedClass().foreach(c => builder.addChildrenOfSealedClass(toType(c))) - classLike.typeParameters().foreach(p => builder.addTypeParameters(toTypeParameter(p))) - builder.build - } - - def toUseScope(useScope: UseScope): Schema.UseScope = { - useScope match { - case UseScope.Default => Schema.UseScope.DEFAULT - case UseScope.Implicit => Schema.UseScope.IMPLICIT - case UseScope.PatMatTarget => Schema.UseScope.PATMAT - } - } - - def toAnalyzedClass( - shouldStoreApis: Boolean - )(analyzedClass: AnalyzedClass): Schema.AnalyzedClass = { - def toCompanions(companions: Companions): Schema.Companions = { - val classApi = toClassLike(companions.classApi()) - val objectApi = toClassLike(companions.objectApi()) - Schema.Companions.newBuilder - .setClassApi(classApi) - .setObjectApi(objectApi) - .build - } - - def toNameHash(nameHash: NameHash): Schema.NameHash = { - val name = nameHash.name() - val hash = nameHash.hash() - val scope = toUseScope(nameHash.scope()) - Schema.NameHash.newBuilder - .setName(name) - .setScope(scope) - .setHash(hash) - .build - } - - val apiHash = analyzedClass.apiHash() - val extraHash = analyzedClass.extraHash() - val compilationTimestamp = analyzedClass.compilationTimestamp() - val hasMacro = analyzedClass.hasMacro - val name = analyzedClass.name() - val provenance = analyzedClass.provenance - - val builder1 = Schema.AnalyzedClass.newBuilder - val builder0 = - if (shouldStoreApis) builder1.setApi(toCompanions(analyzedClass.api())) - else builder1 - val builder = builder0 - .setCompilationTimestamp(compilationTimestamp) - .setName(name) - .setApiHash(apiHash) - .setHasMacro(hasMacro) - .setExtraHash(extraHash) - .setProvenance(provenance) - - analyzedClass.nameHashes().foreach(h => builder.addNameHashes(toNameHash(h))) - builder.build - } - - private final val sourceToString = (f: VirtualFileRef) => toStringPathV(mapper.mapSourceFile(f)) - private final val libraryToString = (f: VirtualFileRef) => toStringPathV(mapper.mapBinaryFile(f)) - private final val prodToString = (f: VirtualFileRef) => toStringPathV(mapper.mapProductFile(f)) - - private final val stringId = identity[String] _ - def toRelations(relations: Relations): Schema.Relations = { - import sbt.internal.util.Relation - - def toUsedName(usedName: UsedName): Schema.UsedName = { - val name = usedName.name - val builder = Schema.UsedName.newBuilder - .setName(name) - val it = usedName.scopes.iterator - while (it.hasNext) builder.addScopes(toUseScope(it.next)) - builder.build - } - - def toUsedNamesMap(map: Relations.UsedNames): Iterator[(String, Schema.UsedNames)] = { - map.iterator.map { - case (k, names) => - val builder = Schema.UsedNames.newBuilder - names.foreach(name => builder.addUsedNames(toUsedName(name))) - k -> builder.build - } - } - - def toMap[K, V]( - relation: Relation[K, V], - fk: K => String, - fv: V => String - ): Iterator[(String, Schema.Values)] = { - relation.forwardMap.iterator.map { - case (k, vs) => - val builder = Schema.Values.newBuilder - vs.foreach(v => builder.addValues(fv(v))) - fk(k) -> builder.build - } - } - - val srcProd = toMap(relations.srcProd, sourceToString, prodToString) - val libraryDep = toMap(relations.libraryDep, sourceToString, libraryToString) - val libraryClassName = toMap(relations.libraryClassName, libraryToString, stringId) - val memberRefInternal = toMap(relations.memberRef.internal, stringId, stringId) - val memberRefExternal = toMap(relations.memberRef.external, stringId, stringId) - val inheritanceInternal = toMap(relations.inheritance.internal, stringId, stringId) - val inheritanceExternal = toMap(relations.inheritance.external, stringId, stringId) - val localInheritanceInternal = toMap(relations.localInheritance.internal, stringId, stringId) - val localInheritanceExternal = toMap(relations.localInheritance.external, stringId, stringId) - val macroExpansionInternal = toMap(relations.macroExpansion.internal, stringId, stringId) - val macroExpansionExternal = toMap(relations.macroExpansion.external, stringId, stringId) - val classes = toMap(relations.classes, sourceToString, stringId) - val productClassName = toMap(relations.productClassName, stringId, stringId) - val names = toUsedNamesMap(relations.names) - val memberRef = { - val builder = Schema.ClassDependencies.newBuilder - memberRefInternal.foreach { case (k, v) => builder.putInternal(k, v) } - memberRefExternal.foreach { case (k, v) => builder.putExternal(k, v) } - builder.build - } - - val inheritance = { - val builder = Schema.ClassDependencies.newBuilder - inheritanceInternal.foreach { case (k, v) => builder.putInternal(k, v) } - inheritanceExternal.foreach { case (k, v) => builder.putExternal(k, v) } - builder.build - } - - val localInheritance = { - val builder = Schema.ClassDependencies.newBuilder - localInheritanceInternal.foreach { case (k, v) => builder.putInternal(k, v) } - localInheritanceExternal.foreach { case (k, v) => builder.putExternal(k, v) } - builder.build - } - - val macroExpansion = { - val builder = Schema.ClassDependencies.newBuilder - macroExpansionInternal.foreach { case (k, v) => builder.putInternal(k, v) } - macroExpansionExternal.foreach { case (k, v) => builder.putExternal(k, v) } - builder.build - } - - val builder = Schema.Relations.newBuilder - srcProd.foreach { case (k, v) => builder.putSrcProd(k, v) } - libraryDep.foreach { case (k, v) => builder.putLibraryDep(k, v) } - libraryClassName.foreach { case (k, v) => builder.putLibraryClassName(k, v) } - classes.foreach { case (k, v) => builder.putClasses(k, v) } - productClassName.foreach { case (k, v) => builder.putProductClassName(k, v) } - names.foreach { case (k, v) => builder.putNames(k, v) } - builder - .setMemberRef(memberRef) - .setInheritance(inheritance) - .setLocalInheritance(localInheritance) - .setMacroExpansion(macroExpansion) - .build - } - - def toApis(apis: APIs, shouldStoreApis: Boolean): Schema.APIs = { - val toAnalyzedClassSchema = toAnalyzedClass(shouldStoreApis) _ - val builder = Schema.APIs.newBuilder - apis.internal.foreach { case (k, v) => builder.putInternal(k, toAnalyzedClassSchema(v)) } - apis.external.foreach { case (k, v) => builder.putExternal(k, toAnalyzedClassSchema(v)) } - builder.build - } - - def toApisFile( - apis0: APIs, - version: Schema.Version, - shouldStoreApis: Boolean - ): Schema.APIsFile = - Schema.APIsFile.newBuilder - .setVersion(version) - .setApis(toApis(apis0, shouldStoreApis)) - .build - - def toAnalysis(analysis: Analysis): Schema.Analysis = - Schema.Analysis.newBuilder - .setStamps(toStamps(analysis.stamps)) - .setRelations(toRelations(analysis.relations)) - .setSourceInfos(toSourceInfos(analysis.infos)) - .setCompilations(toCompilations(analysis.compilations)) - .build - - def toAnalysisFile( - analysis0: Analysis, - miniSetup0: MiniSetup, - version: Schema.Version - ): Schema.AnalysisFile = - Schema.AnalysisFile.newBuilder - .setVersion(version) - .setAnalysis(toAnalysis(analysis0)) - .setMiniSetup(toMiniSetup(miniSetup0)) - .build -} diff --git a/internal/zinc-persist/src/main/scala/sbt/internal/inc/cached/CompilationCache.scala b/internal/zinc-persist/src/main/scala/sbt/internal/inc/cached/CompilationCache.scala index 029eeb784b..a37a2fb28e 100644 --- a/internal/zinc-persist/src/main/scala/sbt/internal/inc/cached/CompilationCache.scala +++ b/internal/zinc-persist/src/main/scala/sbt/internal/inc/cached/CompilationCache.scala @@ -28,7 +28,7 @@ trait CompilationCache { case class ProjectRebasedCache(remoteRoot: Path, cacheLocation: Path) extends CompilationCache { override def loadCache(projectLocation: File): Option[(CompileAnalysis, MiniSetup)] = { import JavaInterfaceUtil.EnrichOptional - import scala.collection.JavaConverters._ + import scala.jdk.CollectionConverters._ val projectLocationPath = projectLocation.toPath val readMapper = new RebaseReadWriteMapper(remoteRoot, projectLocationPath) val writeMapper = new RebaseReadWriteMapper(projectLocationPath, remoteRoot) diff --git a/internal/zinc-persist/src/main/scala/sbt/internal/inc/consistent/ConsistentAnalysisFormat.scala b/internal/zinc-persist/src/main/scala/sbt/internal/inc/consistent/ConsistentAnalysisFormat.scala index 271de3492f..b217c47997 100644 --- a/internal/zinc-persist/src/main/scala/sbt/internal/inc/consistent/ConsistentAnalysisFormat.scala +++ b/internal/zinc-persist/src/main/scala/sbt/internal/inc/consistent/ConsistentAnalysisFormat.scala @@ -22,8 +22,8 @@ import xsbti.compile._ import xsbti.compile.analysis.{ ReadWriteMappers, SourceInfo, Stamp } import scala.collection.immutable.TreeMap +import scala.collection.immutable.ArraySeq import sbt.internal.inc.binary.converters.InternalApiProxy -import Compat._ /** A new implementation of zinc's incremental state serialization. * - Full structural serialization (like the existing protobuf format), no shortcuts with sbinary @@ -162,6 +162,8 @@ class ConsistentAnalysisFormat(val mappers: ReadWriteMappers, reproducible: Bool out.bool(ac.hasMacro) out.string(ac.provenance()) out.int(ac.extraHash()) + out.long(ac.bytecodeHash()) + out.long(ac.transitiveBytecodeHash()) val nh0 = ac.nameHashes() val nh = if (nh0.length > 1 && reproducible) { val nh = nh0.clone() @@ -187,6 +189,8 @@ class ConsistentAnalysisFormat(val mappers: ReadWriteMappers, reproducible: Bool val hm = in.bool() val p = in.string() val eh = in.int() + val bh = in.long() + val ebh = in.long() val nhNames = in.readStringArray() val nhScopes = in.readArray[UseScope]() { UseScope.values()(in.byte().toInt) } val nhHashes = in.readArray[Int]() { in.int() } @@ -199,7 +203,7 @@ class ConsistentAnalysisFormat(val mappers: ReadWriteMappers, reproducible: Bool val comp = if (storeApis) Companions.of(readClassLike(in), readClassLike(in)) else APIs.emptyCompanions - AnalyzedClass.of(ts, name, SafeLazyProxy.strict(comp), ah, nameHashes, hm, eh, p) + AnalyzedClass.of(ts, name, SafeLazyProxy.strict(comp), ah, nameHashes, hm, eh, p, bh, ebh) } } @@ -292,8 +296,8 @@ class ConsistentAnalysisFormat(val mappers: ReadWriteMappers, reproducible: Bool ) { val file = readMapper.mapSourceFile(VirtualFileRef.of(in.string())) val mainClasses = in.readStringSeq() - val reportedProblems = in.readArray()(readProblem()).toIndexedSeq - val unreportedProblems = in.readArray()(readProblem()).toIndexedSeq + val reportedProblems = ArraySeq.unsafeWrapArray(in.readArray()(readProblem())) + val unreportedProblems = ArraySeq.unsafeWrapArray(in.readArray()(readProblem())) val info = SourceInfos.makeInfo(reportedProblems, unreportedProblems, mainClasses) (file, info) }) @@ -447,11 +451,12 @@ class ConsistentAnalysisFormat(val mappers: ReadWriteMappers, reproducible: Bool } private[this] def readUsedNameSet(in: Deserializer): Set[UsedName] = { + import scala.jdk.CollectionConverters.* in.readBlock { val data = in.readColl[Vector[UsedName], Vector[Vector[UsedName]]](Vector, 2) { val i = in.byte().toInt val names = in.readStringSeq() - names.iterator.map { n => UsedName(n, useScopes(i)) }.toVector + names.iterator.map { n => UsedName(n, useScopes(i).asScala) }.toVector } data.flatten.toSet } diff --git a/internal/zinc-persist/src/main/scala/sbt/internal/inc/consistent/Serializer.scala b/internal/zinc-persist/src/main/scala/sbt/internal/inc/consistent/Serializer.scala index 709d53380e..70f5496ff7 100644 --- a/internal/zinc-persist/src/main/scala/sbt/internal/inc/consistent/Serializer.scala +++ b/internal/zinc-persist/src/main/scala/sbt/internal/inc/consistent/Serializer.scala @@ -28,7 +28,7 @@ import scala.annotation.tailrec import scala.collection.mutable.ArrayBuffer import scala.collection.mutable import scala.reflect.ClassTag -import Compat._ +import scala.collection.Factory /** Structural serialization for text and binary formats. */ abstract class Serializer { diff --git a/internal/zinc-persist/src/main/scala/sbt/internal/inc/text/AnalysisMappers.scala b/internal/zinc-persist/src/main/scala/sbt/internal/inc/text/AnalysisMappers.scala index 1bc2196ce6..cb3069a01f 100644 --- a/internal/zinc-persist/src/main/scala/sbt/internal/inc/text/AnalysisMappers.scala +++ b/internal/zinc-persist/src/main/scala/sbt/internal/inc/text/AnalysisMappers.scala @@ -17,6 +17,7 @@ import java.nio.file.{ Path, Paths } import sbt.internal.inc.UsedName import xsbti.{ UseScope, VirtualFileRef } import xsbti.compile.analysis.Stamp +import scala.jdk.CollectionConverters._ case class Mapper[V](read: String => V, write: V => String) case class ContextAwareMapper[C, V](read: (C, String) => V, write: (C, V) => String) @@ -34,7 +35,7 @@ object Mapper { def serialize(usedName: UsedName): String = s"${enumSetSerializer.serialize(usedName.scopes)}${usedName.name}" - def deserialize(s: String) = UsedName(s.tail, enumSetSerializer.deserialize(s.head)) + def deserialize(s: String) = UsedName(s.tail, enumSetSerializer.deserialize(s.head).asScala) Mapper(deserialize, serialize) } diff --git a/internal/zinc-persist/src/main/scala/sbt/internal/inc/text/FormatCommons.scala b/internal/zinc-persist/src/main/scala/sbt/internal/inc/text/FormatCommons.scala index 20d28cd06b..7b008050d8 100644 --- a/internal/zinc-persist/src/main/scala/sbt/internal/inc/text/FormatCommons.scala +++ b/internal/zinc-persist/src/main/scala/sbt/internal/inc/text/FormatCommons.scala @@ -56,20 +56,20 @@ object FormatCommons extends FormatCommons /** Various helper functions. */ trait FormatCommons { - val fileToString: File => String = { f: File => + val fileToString: File => String = { (f: File) => f.toPath.toString } - val stringToFile: String => File = { s: String => + val stringToFile: String => File = { (s: String) => try { Paths.get(s).toFile } catch { case e: Exception => sys.error(e.getMessage + ": " + s) } } - val fileVToString: VirtualFileRef => String = { f: VirtualFileRef => + val fileVToString: VirtualFileRef => String = { (f: VirtualFileRef) => f.id } - val stringToFileV: String => VirtualFileRef = { s: String => + val stringToFileV: String => VirtualFileRef = { (s: String) => VirtualFileRef.of(s) } @@ -99,7 +99,7 @@ trait FormatCommons { val fmtStr = "%%0%dd".format(numDigits) // We only use this for relatively short seqs, so creating this extra map won't be a performance hit. val m: Map[String, T] = s.zipWithIndex.map(x => fmtStr.format(x._2) -> x._1).toMap - writeMap(out)(header, m, identity[String] _, t2s) + writeMap(out)(header, m, identity[String], t2s) } protected def writeMap[K, V]( diff --git a/internal/zinc-persist/src/main/scala/sbt/internal/inc/text/TextAnalysisFormat.scala b/internal/zinc-persist/src/main/scala/sbt/internal/inc/text/TextAnalysisFormat.scala index 22a1a9e1d2..4051a060b3 100644 --- a/internal/zinc-persist/src/main/scala/sbt/internal/inc/text/TextAnalysisFormat.scala +++ b/internal/zinc-persist/src/main/scala/sbt/internal/inc/text/TextAnalysisFormat.scala @@ -31,6 +31,7 @@ import xsbti.api._ import xsbti.compile._ import xsbti.compile.analysis.{ ReadWriteMappers, SourceInfo, Stamp } import scala.collection.Seq +import scala.collection.immutable.ArraySeq // A text-based serialization format for Analysis objects. // This code has been tuned for high performance, and therefore has non-idiomatic areas. @@ -190,7 +191,7 @@ class TextAnalysisFormat(val mappers: ReadWriteMappers) val currentVersion = "7" def write(out: Writer): Unit = { - out.write("format version: %s\n".format(currentVersion)) + out.write(s"format version: $currentVersion\n") } private val versionPattern = """format version: (\w+)""".r @@ -206,8 +207,7 @@ class TextAnalysisFormat(val mappers: ReadWriteMappers) // TODO: Support backwards compatibility? if (version != currentVersion) { throw new ReadException( - "File uses format version %s, but we are compatible with version %s only." - .format(version, currentVersion) + s"File uses format version $version, but we are compatible with version $currentVersion only." ) } } @@ -288,7 +288,7 @@ class TextAnalysisFormat(val mappers: ReadWriteMappers) keyMapper: Mapper[File], valueMapper: ContextAwareMapper[File, Stamp] ): TreeMap[File, Stamp] = { - TreeMap(readMappedPairs(in)(expectedHeader, keyMapper.read, valueMapper.read).toSeq: _*) + TreeMap(readMappedPairs(in)(expectedHeader, keyMapper.read, valueMapper.read).toSeq*) } def doReadMapV( expectedHeader: String, @@ -296,7 +296,7 @@ class TextAnalysisFormat(val mappers: ReadWriteMappers) valueMapper: ContextAwareMapper[VirtualFileRef, Stamp] ): TreeMap[VirtualFileRef, Stamp] = { import VirtualFileUtil._ - TreeMap(readMappedPairs(in)(expectedHeader, keyMapper.read, valueMapper.read).toSeq: _*) + TreeMap(readMappedPairs(in)(expectedHeader, keyMapper.read, valueMapper.read).toSeq*) } val products = doReadMapV(Headers.products, productsMapper, productsStampsMapper) @@ -313,8 +313,8 @@ class TextAnalysisFormat(val mappers: ReadWriteMappers) val external = "external apis" } - val stringToAnalyzedClass = ObjectStringifier.stringToObj[AnalyzedClass] _ - val analyzedClassToString = ObjectStringifier.objToString[AnalyzedClass] _ + val stringToAnalyzedClass = ObjectStringifier.stringToObj[AnalyzedClass] + val analyzedClassToString = ObjectStringifier.objToString[AnalyzedClass] def write(out: Writer, apis: APIs): Unit = { writeMap(out)( @@ -363,8 +363,8 @@ class TextAnalysisFormat(val mappers: ReadWriteMappers) val external = "external companions" } - val stringToCompanions = ObjectStringifier.stringToObj[Companions] _ - val companionsToString = ObjectStringifier.objToString[Companions] _ + val stringToCompanions = ObjectStringifier.stringToObj[Companions] + val companionsToString = ObjectStringifier.objToString[Companions] def write(out: Writer, apis: APIs): Unit = { val internal = apis.internal map { case (k, v) => k -> v.api } @@ -406,8 +406,8 @@ class TextAnalysisFormat(val mappers: ReadWriteMappers) val infos = "source infos" } - val stringToSourceInfo = ObjectStringifier.stringToObj[SourceInfo] _ - val sourceInfoToString = ObjectStringifier.objToString[SourceInfo] _ + val stringToSourceInfo = ObjectStringifier.stringToObj[SourceInfo] + val sourceInfoToString = ObjectStringifier.objToString[SourceInfo] def write(out: Writer, infos: SourceInfos): Unit = writeMap(out)( @@ -427,8 +427,8 @@ class TextAnalysisFormat(val mappers: ReadWriteMappers) val compilations = "compilations" } - val stringToCompilation = ObjectStringifier.stringToObj[Compilation] _ - val compilationToString = ObjectStringifier.objToString[Compilation] _ + val stringToCompilation = ObjectStringifier.stringToObj[Compilation] + val compilationToString = ObjectStringifier.objToString[Compilation] def write(out: Writer, compilations: Compilations): Unit = writeSeq(out)(Headers.compilations, Nil, compilationToString) @@ -452,8 +452,8 @@ class TextAnalysisFormat(val mappers: ReadWriteMappers) private[this] val singleOutputMode = "single" private[this] val multipleOutputMode = "multiple" - val stringToFileHash = ObjectStringifier.stringToObj[FileHash] _ - val fileHashToString = ObjectStringifier.objToString[FileHash] _ + val stringToFileHash = ObjectStringifier.stringToObj[FileHash] + val fileHashToString = ObjectStringifier.objToString[FileHash] final val sourceDirMapper = Mapper( (str: String) => readMapper.mapSourceDir(Mapper.forPath.read(str)), @@ -486,17 +486,17 @@ class TextAnalysisFormat(val mappers: ReadWriteMappers) writeMap(out)(Headers.outputDir, outputAsMap, sourceDirMapper.write, outputDirMapper.write) writeSeq(out)( Headers.classpathHash, - mappedClasspathHash.toIndexedSeq, + ArraySeq.unsafeWrapArray(mappedClasspathHash), fileHashToString ) writeSeq(out)( Headers.compileOptions, - setup.options.scalacOptions.toIndexedSeq, + ArraySeq.unsafeWrapArray(setup.options.scalacOptions), soptionsMapper.write ) writeSeq(out)( Headers.javacOptions, - setup.options.javacOptions.toIndexedSeq, + ArraySeq.unsafeWrapArray(setup.options.javacOptions), joptionsMapper.write ) writeSeq(out)(Headers.compilerVersion, setup.compilerVersion :: Nil, identity[String]) diff --git a/internal/zinc-persist/src/test/scala/sbt/inc/AnalysisGenerators.scala b/internal/zinc-persist/src/test/scala/sbt/inc/AnalysisGenerators.scala index bcd6b83330..2273d2bbad 100644 --- a/internal/zinc-persist/src/test/scala/sbt/inc/AnalysisGenerators.scala +++ b/internal/zinc-persist/src/test/scala/sbt/inc/AnalysisGenerators.scala @@ -79,7 +79,7 @@ object AnalysisGenerators { import VirtualFileUtil._ def stamp(xs: Iterable[VirtualFileRef]) = - for (stamps <- listOfN(xs.size, genStamp)) yield TreeMap(xs.toList.zip(stamps): _*) + for (stamps <- listOfN(xs.size, genStamp)) yield TreeMap(xs.toList.zip(stamps)*) for { prods <- stamp(rel.allProducts) @@ -147,11 +147,11 @@ object AnalysisGenerators { entries <- listOfN(srcs.length, containerOfN[Set, T](n, g)) } yield Relation.reconstruct(zipMap(srcs, entries)) - val genStringRelation = genVirtualFileRefRelation(unique(identifier)) _ - val genFileVORefRelation = genVirtualFileRefRelation(unique(genFileVRef)) _ + val genStringRelation = genVirtualFileRefRelation(unique(identifier)) + val genFileVORefRelation = genVirtualFileRefRelation(unique(genFileVRef)) def rel[A, B](a: Seq[A], b: Seq[B]): Relation[A, B] = - Relation.reconstruct(zipMap(a, b).mapValues(Set(_)).toMap) + Relation.reconstruct(zipMap(a, b).view.mapValues(Set(_)).toMap) def genStringStringRelation(num: Int): Gen[Relation[String, String]] = for { diff --git a/internal/zinc-persist/src/test/scala/sbt/inc/consistent/ConsistentAnalysisFormatIntegrationSuite.scala b/internal/zinc-persist/src/test/scala/sbt/inc/consistent/ConsistentAnalysisFormatIntegrationSuite.scala index efb1e61597..05a224d433 100644 --- a/internal/zinc-persist/src/test/scala/sbt/inc/consistent/ConsistentAnalysisFormatIntegrationSuite.scala +++ b/internal/zinc-persist/src/test/scala/sbt/inc/consistent/ConsistentAnalysisFormatIntegrationSuite.scala @@ -20,6 +20,9 @@ import sbt.io.{ IO, Using } import xsbti.compile.{ AnalysisContents, AnalysisStore } import xsbti.compile.analysis.ReadWriteMappers +// $ cp $HOME/work/scala-modules/scala/target/library/zinc/inc_compile.zip test-data/library.zip +// $ cp $HOME/work/scala-modules/scala/target/reflect/zinc/inc_compile.zip test-data/reflect.zip +// $ cp $HOME/work/scala-modules/scala/target/compiler/zinc/inc_compile.zip test-data/compiler.zip class ConsistentAnalysisFormatIntegrationSuite extends AnyFunSuite { val data = Seq("compiler.zip", "library.zip", "reflect.zip").map(f => new File("../../../test-data", f)) @@ -27,7 +30,7 @@ class ConsistentAnalysisFormatIntegrationSuite extends AnyFunSuite { test("Consistent output") { for (d <- data) { assert(d.exists()) - val api = read(FileAnalysisStore.binary(d)) + val api = read(FileAnalysisStore.text(d)) val f1 = write("cbin1.zip", api) val f2 = write("cbin2.zip", api) assert(Arrays.equals(IO.readBytes(f1), IO.readBytes(f2)), s"same output for $d") @@ -37,7 +40,7 @@ class ConsistentAnalysisFormatIntegrationSuite extends AnyFunSuite { test("Roundtrip") { for (d <- data) { assert(d.exists()) - val api = read(FileAnalysisStore.binary(d)) + val api = read(FileAnalysisStore.text(d)) val f1 = write("cbin1.zip", api) val api2 = read(ConsistentFileAnalysisStore.binary(f1, ReadWriteMappers.getEmptyMappers)) val f2 = write("cbin2.zip", api2) @@ -48,7 +51,7 @@ class ConsistentAnalysisFormatIntegrationSuite extends AnyFunSuite { test("Unsorted roundtrip") { for (d <- data) { assert(d.exists()) - val api = read(FileAnalysisStore.binary(d)) + val api = read(FileAnalysisStore.text(d)) val f1 = write("cbin1.zip", api) val api2 = read(ConsistentFileAnalysisStore.binary(f1, ReadWriteMappers.getEmptyMappers)) val f2 = write("cbin2.zip", api2, sort = false) @@ -61,7 +64,7 @@ class ConsistentAnalysisFormatIntegrationSuite extends AnyFunSuite { test("compression ratio") { for (d <- data) { assert(d.exists()) - val api = read(FileAnalysisStore.binary(d)) + val api = read(FileAnalysisStore.text(d)) val file = write("cbin1.zip", api) val uncompressedSize = Using.gzipInputStream(new FileInputStream(file)) { in => val content = IO.readBytes(in) diff --git a/internal/zinc-persist/src/test/scala/sbt/inc/consistent/ConsistentAnalysisFormatSuite.scala b/internal/zinc-persist/src/test/scala/sbt/inc/consistent/ConsistentAnalysisFormatSuite.scala index be417c4fc0..2b1c78ecaa 100644 --- a/internal/zinc-persist/src/test/scala/sbt/inc/consistent/ConsistentAnalysisFormatSuite.scala +++ b/internal/zinc-persist/src/test/scala/sbt/inc/consistent/ConsistentAnalysisFormatSuite.scala @@ -12,9 +12,8 @@ package sbt.inc.consistent import org.scalatest.funsuite.AnyFunSuite -import sbt.internal.inc.consistent._ -import Compat._ -import java.io._ +import sbt.internal.inc.consistent.* +import java.io.* class ConsistentAnalysisFormatSuite extends AnyFunSuite { diff --git a/internal/zinc-persist/src/test/scala/sbt/inc/consistent/ParallelGzipOutputStreamSpecification.scala b/internal/zinc-persist/src/test/scala/sbt/inc/consistent/ParallelGzipOutputStreamSpecification.scala index 5330115d00..f990e7caea 100644 --- a/internal/zinc-persist/src/test/scala/sbt/inc/consistent/ParallelGzipOutputStreamSpecification.scala +++ b/internal/zinc-persist/src/test/scala/sbt/inc/consistent/ParallelGzipOutputStreamSpecification.scala @@ -21,10 +21,11 @@ import sbt.io.IO import sbt.io.Using import java.util.Arrays +import collection.parallel.CollectionConverters.* import scala.util.Random import scala.concurrent.{ Await, Future } import scala.concurrent.ExecutionContext.Implicits.global -import scala.concurrent.duration._ +import scala.concurrent.duration.* class ParallelGzipOutputStreamSpecification extends AnyFlatSpec with Matchers { val defaultSize: Int = 64 * 1024 @@ -70,7 +71,6 @@ class ParallelGzipOutputStreamSpecification extends AnyFlatSpec with Matchers { } val path = outputDir.resolve(fileName) Files.write(path, data, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING) - () } // Need this in windows to produce valid windows filename diff --git a/internal/zinc-scripted/src/test/scala/sbt/inc/ScriptedMain.scala b/internal/zinc-scripted/src/test/scala/sbt/inc/ScriptedMain.scala index 78e3a3707f..956ee7d467 100644 --- a/internal/zinc-scripted/src/test/scala/sbt/inc/ScriptedMain.scala +++ b/internal/zinc-scripted/src/test/scala/sbt/inc/ScriptedMain.scala @@ -31,12 +31,12 @@ object ScriptedMain { def detectScriptedTests(scriptedBase: File): Map[String, Set[String]] = { val scriptedFiles: NameFilter = ("test": NameFilter) | "pending" - val pairs = (scriptedBase * AllPassFilter * AllPassFilter * scriptedFiles).get.map { f => + val pairs = (scriptedBase * AllPassFilter * AllPassFilter * scriptedFiles).get().map { f => val p = f.getParentFile (p.getParentFile.getName, p.getName) } - pairs.groupBy(_._1).mapValues(_.map(_._2).toSet) + pairs.groupBy(_._1).view.mapValues(_.map(_._2).toSet).toMap } private def parseScripted( diff --git a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala index b3324c59a7..ea3add5768 100644 --- a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala +++ b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala @@ -54,7 +54,6 @@ import sbt.internal.scripted.{ StatementHandler, TestFailed } import sbt.internal.util.ManagedLogger import sjsonnew.support.scalajson.unsafe.{ Converter, Parser => JsonParser } -import scala.{ PartialFunction => ?=> } import scala.collection.mutable import scala.concurrent.{ blocking, Await, Future, Promise } import scala.concurrent.duration._ @@ -144,11 +143,19 @@ class IncHandler(directory: Path, cacheDir: Path, scriptedLog: ManagedLogger, co def initBuild: Build = { if (Files.exists(directory / "build.json")) { - import sjsonnew._, BasicJsonProtocol._ - implicit val pathFormat = IsoString.iso[Path](_.toString, Paths.get(_)) - implicit val projectFormat = - caseClass(Project.apply _, Project.unapply _)("name", "dependsOn", "in", "scalaVersion") - implicit val buildFormat = caseClass(Build.apply _, Build.unapply _)("projects") + import sjsonnew.{ IsoString, JsonFormat } + import sjsonnew.BasicJsonProtocol._ + given pathISOString: IsoString[Path] = IsoString.iso[Path](_.toString, Paths.get(_)) + given pathFormat: JsonFormat[Path] = isoStringFormat[Path](using pathISOString) + given projectFormat: JsonFormat[Project] = + caseClass4(Project.apply, p => Some(p.name, p.dependsOn, p.in, p.scalaVersion))( + "name", + "dependsOn", + "in", + "scalaVersion", + ) + given buildFormat: JsonFormat[Build] = + caseClass1(Build.apply, b => Some(b.projects))("projects") // Do not parseFromFile as it leaves file open, causing problems on Windows. val json = { val channel = Files.newByteChannel(directory / "build.json") @@ -228,9 +235,6 @@ class IncHandler(directory: Path, cacheDir: Path, scriptedLog: ManagedLogger, co onArgs("checkNumberOfLibraries") { case (p, x :: Nil, i) => p.checkNumberOfLibraries(i, x.toInt) }, - onArgs("checkCycles") { - case (p, x :: Nil, i) => p.checkNumberOfCycles(i, x.toInt) - }, // note that this can only tell us the *last* round a class got compiled in. // it can't tell us *every* round something got compiled in, since only // still-extant classfiles are available for inspection @@ -276,20 +280,21 @@ class IncHandler(directory: Path, cacheDir: Path, scriptedLog: ManagedLogger, co private def dropRightColon(s: String) = if (s endsWith ":") s.dropRight(1) else s private def onArgs(commandName: String)( - pf: (ProjectStructure, List[String], IncState) ?=> Future[Unit] + pf: PartialFunction[(ProjectStructure, List[String], IncState), Future[Unit]] ): (String, IncCommand) = commandName -> ((p, xs, i) => applyOrElse(pf, (p, xs, i), p.unrecognizedArguments(commandName, xs))) private def noArgs(commandName: String)( - pf: (ProjectStructure, IncState) ?=> Future[Unit] + pf: PartialFunction[(ProjectStructure, IncState), Future[Unit]] ): (String, IncCommand) = commandName -> ((p, xs, i) => { applyOrElse(pf, (p, i), p.acceptsNoArguments(commandName, xs)) }) - private def applyOrElse[A, B](pf: A ?=> B, x: A, fb: => B): B = pf.applyOrElse(x, (_: A) => fb) + private def applyOrElse[A, B](pf: PartialFunction[A, B], x: A, fb: => B): B = + pf.applyOrElse(x, (_: A) => fb) } case class ProjectStructure( @@ -321,12 +326,12 @@ case class ProjectStructure( val javaSourceDirectory = baseDirectory / "src" / "main" / "java" def scalaSources: List[Path] = - ((scalaSourceDirectory.toFile ** "*.scala").get ++ (baseDirectory.toFile * "*.scala").get) + ((scalaSourceDirectory.toFile ** "*.scala").get() ++ (baseDirectory.toFile * "*.scala").get()) .map(_.toPath) .toList def javaSources: List[Path] = - ((javaSourceDirectory.toFile ** "*.java").get ++ (baseDirectory.toFile * "*.java").get) + ((javaSourceDirectory.toFile ** "*.java").get() ++ (baseDirectory.toFile * "*.java").get()) .map(_.toPath) .toList @@ -337,7 +342,7 @@ case class ProjectStructure( val earlyCacheFile = baseDirectory / "target" / "early" / "inc_compile.zip" val earlyAnalysisStore = FileAnalysisStore.binary(earlyCacheFile.toFile) // val earlyCachedStore = AnalysisStore.cached(fileStore) - val profiler = new ZincInvalidationProfiler + // val profiler = new ZincInvalidationProfiler // We specify the class file manager explicitly even though it's noew possible // to specify it in the incremental option property file (this is the default for sbt) @@ -379,7 +384,7 @@ case class ProjectStructure( } def unmanagedJars: List[Path] = - ((baseDirectory / "lib").toFile ** "*.jar").get.toList.map(_.toPath) + ((baseDirectory / "lib").toFile ** "*.jar").get().toList.map(_.toPath) def dependsOnRef: Vector[ProjectStructure] = dependsOn.map(lookupProject(_)) @@ -434,14 +439,14 @@ case class ProjectStructure( () } - def checkNumberOfCycles(i: IncState, expected: Int): Future[Unit] = - compile(i).map { _ => - import scala.collection.JavaConverters._ - val count = profiler.toProfile.getRunsList.asScala.map(_.getCyclesList.size).sum - val msg = s"Expected $expected cycles, got $count" - assert(count == expected, msg) - () - } + // def checkNumberOfCycles(i: IncState, expected: Int): Future[Unit] = + // compile(i).map { _ => + // import scala.collection.JavaConverters._ + // val count = profiler.toProfile.getRunsList.asScala.map(_.getCyclesList.size).sum + // val msg = s"Expected $expected cycles, got $count" + // assert(count == expected, msg) + // () + // } def checkClasses(i: IncState, src: String, expected: List[String]): Future[Unit] = compile(i).map { analysis => @@ -492,14 +497,14 @@ case class ProjectStructure( assert( missing.isEmpty, s"""Missing ${missing.size} products:${missing.map("\n " + _).mkString} - |Generated:${generatedClassFiles.get.toList.map("\n " + _).mkString}""".stripMargin + |Generated:${generatedClassFiles.get().toList.map("\n " + _).mkString}""".stripMargin ) () } def checkNoGeneratedClassFiles(): Future[Unit] = Future { - val allPlainClassFiles = generatedClassFiles.get.toList.map(_.toString) + val allPlainClassFiles = generatedClassFiles.get().toList.map(_.toString) val allClassesInJar: List[String] = outputJar.toList.filter(Files.exists(_)).flatMap(p => JarUtils.listClassFiles(p.toFile)) if (allPlainClassFiles.nonEmpty || allClassesInJar.nonEmpty) { @@ -738,7 +743,7 @@ case class ProjectStructure( IO.copy(Seq(currentJar.toFile -> targetJar.toFile)) () case None => - val sources = (classesDir.toFile ** -DirectoryFilter).get.flatMap { f => + val sources = (classesDir.toFile ** -DirectoryFilter).get().flatMap { f => IO.relativize(classesDir.toFile, f) match { case Some(path) => List((f, path)) case _ => Nil @@ -807,14 +812,13 @@ case class ProjectStructure( } def loadIncOptions(properties: Properties): (IncOptions, Array[String]) = { - import scala.collection.JavaConverters._ + import scala.jdk.CollectionConverters._ val map = new java.util.HashMap[String, String] properties.asScala foreach { case (k: String, v: String) => map.put(k, v) } val externalHooks = new DefaultExternalHooks( Optional.empty[ExternalHooks.Lookup], Optional.empty[XClassFileManager] ) - .withInvalidationProfiler(profiler) val base = IncOptions .of() .withPipelining(defaultPipelining) diff --git a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncScriptedRunner.scala b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncScriptedRunner.scala index c21ec2c67a..b3f9305029 100644 --- a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncScriptedRunner.scala +++ b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncScriptedRunner.scala @@ -19,6 +19,7 @@ import sbt.io.IO import sbt.util.{ Level, Logger } import scala.collection.parallel.ParSeq +import collection.parallel.CollectionsHaveToParArray import sbt.inc.ScriptedMain._ object ScriptedRunnerImpl { diff --git a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/ScriptedTests.scala b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/ScriptedTests.scala index 78e57d9786..49a015e3e6 100644 --- a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/ScriptedTests.scala +++ b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/ScriptedTests.scala @@ -53,8 +53,8 @@ final class ScriptedTests( // Test group and names may be file filters (like '*') val groupAndNameDirs = for { ScriptedTest(group, name) <- tests - groupDir <- resourceBaseDirectory.toFile.glob(group).get.map(_.toPath) - testDir <- groupDir.toFile.*(name).get.map(_.toPath) + groupDir <- resourceBaseDirectory.toFile.glob(group).get().map(_.toPath) + testDir <- groupDir.toFile.*(name).get().map(_.toPath) } yield (groupDir, testDir) val labelsAndDirs = groupAndNameDirs.map { @@ -157,7 +157,7 @@ final class ScriptedTests( // Run the test and delete files (except global that holds local scala jars) val runTest = () => commonRunTest(label, batchTmpDir, handlers, runner, states, logger) val result = runOrHandleDisabled(label, batchTmpDir, runTest, logger) - IO.delete(batchTmpDir.toFile.*("*" -- "global").get) + IO.delete(batchTmpDir.toFile.*("*" -- "global").get()) result } finally runner.cleanUpHandlers(seqHandlers, states) diff --git a/internal/zinc-testing/src/main/scala/xsbti/TestCallback.scala b/internal/zinc-testing/src/main/scala/xsbti/TestCallback.scala index 8ccc840a7f..da67307423 100644 --- a/internal/zinc-testing/src/main/scala/xsbti/TestCallback.scala +++ b/internal/zinc-testing/src/main/scala/xsbti/TestCallback.scala @@ -37,7 +37,7 @@ class TestCallback extends AnalysisCallback3 { val apis: scala.collection.mutable.Map[VirtualFileRef, Set[ClassLike]] = scala.collection.mutable.Map.empty - def usedNames = usedNamesAndScopes.mapValues(_.map(_.name)) + def usedNames = usedNamesAndScopes.view.mapValues(_.map(_.name)) override def startSource(source: File): Unit = ??? override def startSource(source: VirtualFile): Unit = { @@ -152,7 +152,7 @@ class TestCallback extends AnalysisCallback3 { override def isPickleJava: Boolean = false - override def getPickleJarPair = Optional.empty() + override def getPickleJarPair: Optional[T2[Path, Path]] = Optional.empty() override def toVirtualFile(path: Path): VirtualFile = { throw new UnsupportedOperationException("This method should not be called in tests") @@ -195,7 +195,7 @@ object TestCallback { } } // convert all collections to immutable variants - multiMap.toMap.mapValues(_.toSet).toMap.withDefaultValue(Set.empty) + multiMap.toMap.view.mapValues(_.toSet).toMap.withDefaultValue(Set.empty) } } } diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 93bd50cc5c..d9a94464a9 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -9,14 +9,16 @@ object Dependencies { val scala211 = "2.11.12" val scala212 = "2.12.20" val scala213 = "2.13.16" + val scala3 = "3.7.2" val scala3ForBridge = "3.3.4" val scala213ForBridge = "2.13.16" - val defaultScalaVersion = scala212 + val defaultScalaVersion = scala3 val compilerBridgeVersions = Seq(scala212, scala210, scala211, scala213) val scala212_213 = Seq(defaultScalaVersion, scala213) + val scala3_only = Seq(scala3) private val ioVersion = nightlyVersion.getOrElse("1.10.5") - private val utilVersion = nightlyVersion.getOrElse("1.11.2") + private val utilVersion = nightlyVersion.getOrElse("2.0.0-RC3") private val sbtIO = "org.scala-sbt" %% "io" % ioVersion @@ -72,17 +74,20 @@ object Dependencies { val scalaLibrary = Def.setting { "org.scala-lang" % "scala-library" % scalaVersion.value } val scalaCompiler = Def.setting { "org.scala-lang" % "scala-compiler" % scalaVersion.value } - val parserCombinator = "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2" + val parserCombinator = "org.scala-lang.modules" %% "scala-parser-combinators" % "2.1.0" + // sbinary 0.5.2 uses 2.13 build of scala-xml, so use 0.5.1 val sbinary = "org.scala-sbt" %% "sbinary" % "0.5.1" + val junit = "junit" % "junit" % "4.12" + val sjsonNewVersion = "0.14.0-M1" val scalaXml = "org.scala-lang.modules" %% "scala-xml" % "2.3.0" val scalaCheck = "org.scalacheck" %% "scalacheck" % "1.18.1" val scalatest = "org.scalatest" %% "scalatest" % "3.2.19" - val verify = "com.eed3si9n.verify" %% "verify" % "2.0.1" + val verify = "com.eed3si9n.verify" %% "verify" % "1.0.0" val sjsonnew = Def.setting { - "com.eed3si9n" %% "sjson-new-core" % contrabandSjsonNewVersion.value + "com.eed3si9n" %% "sjson-new-core" % sjsonNewVersion } val sjsonnewScalaJson = Def.setting { - "com.eed3si9n" %% "sjson-new-scalajson" % contrabandSjsonNewVersion.value + "com.eed3si9n" %% "sjson-new-scalajson" % sjsonNewVersion } val zeroAllocationHashing = "net.openhft" % "zero-allocation-hashing" % "0.16" val scala2BinaryBridge = "org.scala-lang" % "scala2-sbt-bridge" % scala213ForBridge diff --git a/project/HouseRulesPlugin.scala b/project/HouseRulesPlugin.scala index f69495cfd0..ac2b86ad43 100644 --- a/project/HouseRulesPlugin.scala +++ b/project/HouseRulesPlugin.scala @@ -11,11 +11,11 @@ object HouseRulesPlugin extends AutoPlugin { lazy val baseSettings: Seq[Def.Setting[?]] = Seq( scalacOptions ++= Seq("-encoding", "utf8"), - scalacOptions ++= Seq("-deprecation", "-feature", "-unchecked", "-Xlint"), + scalacOptions ++= Seq("-deprecation", "-feature", "-unchecked"), scalacOptions += "-language:higherKinds", scalacOptions += "-language:implicitConversions", scalacOptions ++= "-Xfuture".ifScala212OrMinus.value.toList, - scalacOptions += "-Xlint", + scalacOptions ++= "-Xlint".ifScala213OrMinus.value, scalacOptions ++= "-Xfatal-warnings" .ifScala(v => { sys.props.get("sbt.build.fatal") match { @@ -27,9 +27,9 @@ object HouseRulesPlugin extends AutoPlugin { .toList, scalacOptions ++= "-Yinline-warnings".ifScala211OrMinus.value.toList, scalacOptions ++= "-Yno-adapted-args".ifScala212OrMinus.value.toList, - scalacOptions += "-Ywarn-dead-code", - scalacOptions += "-Ywarn-numeric-widen", - scalacOptions += "-Ywarn-value-discard", + scalacOptions ++= "-Ywarn-dead-code".ifScala213OrMinus.value, + scalacOptions ++= "-Ywarn-numeric-widen".ifScala213OrMinus.value, + scalacOptions ++= "-Ywarn-value-discard".ifScala213OrMinus.value, scalacOptions ++= "-Ywarn-unused-import".ifScala(v => 11 <= v && v <= 12).value.toList ) ++ Seq(Compile, Test).flatMap(c => (c / console / scalacOptions) --= Seq("-Ywarn-unused-import", "-Xlint") diff --git a/project/plugins.sbt b/project/plugins.sbt index 6fcbf8f1c5..b34627050b 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,14 +1,13 @@ scalacOptions += "-feature" -addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.0") +addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.1") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.4") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.5") addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.7.0") addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7") addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.10.0") -addSbtPlugin("com.github.sbt" % "sbt-protobuf" % "0.8.2") addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "1.1.4") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.13.1") addSbtPlugin("com.eed3si9n" % "sbt-projectmatrix" % "0.11.0") -addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.2.0") +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.3.1") addSbtPlugin("org.jetbrains.scala" % "sbt-ide-settings" % "1.1.3") diff --git a/test-data/compiler.zip b/test-data/compiler.zip index 618df99c73..e5850997ab 100644 Binary files a/test-data/compiler.zip and b/test-data/compiler.zip differ diff --git a/test-data/library.zip b/test-data/library.zip index d8c11bb8d9..8d421e4949 100644 Binary files a/test-data/library.zip and b/test-data/library.zip differ diff --git a/test-data/reflect.zip b/test-data/reflect.zip index c028058e10..97d81cc041 100644 Binary files a/test-data/reflect.zip and b/test-data/reflect.zip differ diff --git a/zinc-compile/src/main/scala/sbt/inc/Doc.scala b/zinc-compile/src/main/scala/sbt/inc/Doc.scala deleted file mode 100644 index f0bbaadb4b..0000000000 --- a/zinc-compile/src/main/scala/sbt/inc/Doc.scala +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Zinc - The incremental compiler for Scala. - * Copyright Scala Center, Lightbend, and Mark Harrah - * - * Licensed under Apache License 2.0 - * SPDX-License-Identifier: Apache-2.0 - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package sbt.inc - -import java.io.File -import java.nio.file.{ Files, Path } - -import sbt.io.syntax._ -import sbt.util.Logger -import xsbti.{ FileConverter, VirtualFile } -import xsbti.compile.{ IncToolOptions, JavaTools } -import sbt.internal.inc.{ CompileOutput, PlainVirtualFile, PlainVirtualFileConverter } -import sbt.internal.inc.javac.JavaCompilerArguments -import sbt.util.Tracked.inputChanged -import sbt.util.{ CacheStoreFactory, FileInfo, FilesInfo, ModifiedFileInfo, PlainFileInfo } -import sbt.util.CacheImplicits._ -import sbt.io.IO -import sjsonnew._ -import xsbti.Reporter - -object Doc { - private[this] implicit val IsoInputs = LList.iso( - (in: Inputs) => ("getOutputDirectory", in.outputDirectory.toFile) :*: LNil, - (in: File :*: LNil) => Inputs(Nil, Nil, Nil, in.head.toPath, Nil) - ) - - def cachedJavadoc(label: String, storeFactory: CacheStoreFactory, doc: JavaTools): JavaDoc = - cached( - storeFactory, - prepare( - s"$label Java API documentation", - (sources, classpath, _, outputDirectory, options, incToolOptions, log, reporter) => { - val success = doc.javadoc.run( - sources.filter(javaSourcesOnly).toArray, - JavaCompilerArguments(Nil, classpath, options).toArray, - CompileOutput(outputDirectory), - incToolOptions, - reporter, - log - ) - if (!success) - throw new JavadocGenerationFailed() - } - ) - ) - - private[sbt] def prepare(description: String, doDoc: JavaDoc): JavaDoc = - (sources, cp, converter, outputDirectory, options, incToolOptions, log, reporter) => { - if (sources.isEmpty) - log.info(s"No sources available, skipping $description...") - else { - log.info(s"${description.capitalize} to ${outputDirectory.toAbsolutePath}...") - doDoc.run(sources, cp, converter, outputDirectory, options, incToolOptions, log, reporter) - log.info(s"${description.capitalize} successful.") - } - } - - private[sbt] def cached(storeFactory: CacheStoreFactory, doDoc: JavaDoc): JavaDoc = - (sources, classpath, converter, outDir, options, incToolOptions, log, reporter) => { - def go() = { - if (Files.exists(outDir)) - IO.delete(outDir.toFile) - Files.createDirectories(outDir) - doDoc.run(sources, classpath, converter, outDir, options, incToolOptions, log, reporter) - } - val srcs = sources.map(x => VHashFileInfo(x, x.contentHash)) - val cp0 = classpath.map(converter.toPath(_).toFile) - val cp = filesInfoToList(FileInfo.lastModified(cp0.toSet)) - val inputs = Inputs(srcs, cp, classpath, outDir, options) - val outputs = filesInfoToList(FileInfo.exists(outDir.toFile.allPaths.get().toSet)) - inputChanged(storeFactory.make("inputs")) { (inChanged, _: Inputs) => - inputChanged(storeFactory.make("output")) { (outChanged, _: List[PlainFileInfo]) => - if (inChanged || outChanged) go() - else log.debug(s"Doc uptodate: ${outDir.toAbsolutePath}") - } - }.apply(inputs)(outputs) - } - - private[this] final case class VHashFileInfo(file: VirtualFile, contentHash: Long) - - private[this] final case class Inputs( - hfi: List[VHashFileInfo], - mfi: List[ModifiedFileInfo], - classpaths: List[VirtualFile], - outputDirectory: Path, - options: List[String] - ) - - private[sbt] def filesInfoToList[A <: FileInfo](info: FilesInfo[A]): List[A] = - info.files.toList.sortBy(x => x.file.getAbsolutePath) - - private[sbt] val javaSourcesOnly: VirtualFile => Boolean = _.id.endsWith(".java") - - class JavadocGenerationFailed extends Exception - - trait JavaDoc { - - /** @throws JavadocGenerationFailed when generating javadoc fails */ - @deprecated("Use variant that takes VirtualFiles", "1.4.0") - def run( - sources: List[File], - classpath: List[File], - outputDirectory: File, - options: List[String], - incToolOptions: IncToolOptions, - log: Logger, - reporter: Reporter - ): Unit = { - run( - sources.map(s => PlainVirtualFile(s.toPath)), - classpath.map(s => PlainVirtualFile(s.toPath)), - PlainVirtualFileConverter.converter, - outputDirectory.toPath, - options, - incToolOptions, - log, - reporter - ) - } - - /** @throws JavadocGenerationFailed when generating javadoc fails */ - def run( - sources: List[VirtualFile], - classpath: List[VirtualFile], - converter: FileConverter, - outputDirectory: Path, - options: List[String], - incToolOptions: IncToolOptions, - log: Logger, - reporter: Reporter - ): Unit - - } -} diff --git a/zinc-compile/src/test/scala/inc/DocSpec.scala b/zinc-compile/src/test/scala/inc/DocSpec.scala deleted file mode 100644 index 8d244e690d..0000000000 --- a/zinc-compile/src/test/scala/inc/DocSpec.scala +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Zinc - The incremental compiler for Scala. - * Copyright Scala Center, Lightbend, and Mark Harrah - * - * Licensed under Apache License 2.0 - * SPDX-License-Identifier: Apache-2.0 - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package sbt -package inc - -import java.io.File -import java.nio.file.{ Path, Paths } - -import sbt.inc.Doc.JavadocGenerationFailed -import sbt.io.IO -import sbt.internal.inc.javac.{ JavaCompiler, JavaTools, Javadoc } -import sbt.internal.inc.javac.JavaCompilerSpec -import sbt.internal.inc.ManagedLoggedReporter -import sbt.internal.inc.PlainVirtualFile -import sbt.internal.inc.PlainVirtualFileConverter.converter -import sbt.internal.inc.UnitSpec -import xsbti.compile.IncToolOptionsUtil -import sbt.util.CacheStoreFactory - -import org.scalatest.{ Assertion, Succeeded } - -class DocSpec extends UnitSpec { - behavior of "Doc.cachedJavadoc" - - it should "generate Javadoc" in { - docAndAssert(knownSampleGoodFile) { (_, out) => - assert((new File(out, "index.html")).exists) - assert((new File(out, "good.html")).exists) - } - } - - it should "generate cache input" in { - docAndAssert(knownSampleGoodFile) { (cacheDir, _) => - assert((new File(cacheDir, "inputs")).exists) - } - } - - it should "throw when generating javadoc fails" in { - assertThrows[JavadocGenerationFailed] { - docAndAssert(knownSampleBadFile)((_, _) => Succeeded) - } - } - - def docAndAssert(file: Path)(assert: (File, File) => Assertion): Assertion = { - IO.withTemporaryDirectory { cacheDir => - IO.withTemporaryDirectory { out => - val opts = IncToolOptionsUtil.defaultIncToolOptions() - Doc - .cachedJavadoc("Foo", CacheStoreFactory(cacheDir), JavaTools(javac, javadoc)) - .run(List(PlainVirtualFile(file)), Nil, converter, out.toPath, Nil, opts, log, reporter) - assert(cacheDir, out) - } - } - } - - def javac = JavaCompiler.local.getOrElse(sys.error("Need a JDK, cannot run on a JRE")) - def javadoc = Javadoc.local.getOrElse(Javadoc.fork()) - lazy val reporter = new ManagedLoggedReporter(10, log) - def cls = classOf[JavaCompilerSpec] - def knownSampleGoodFile = Paths.get(cls.getResource("good.java").toURI) - def knownSampleBadFile = Paths.get(cls.getResource("bad.java").toURI) -} diff --git a/zinc/src/main/scala/sbt/internal/inc/IncrementalCompilerImpl.scala b/zinc/src/main/scala/sbt/internal/inc/IncrementalCompilerImpl.scala index bef4b8983c..c41e01cb0d 100644 --- a/zinc/src/main/scala/sbt/internal/inc/IncrementalCompilerImpl.scala +++ b/zinc/src/main/scala/sbt/internal/inc/IncrementalCompilerImpl.scala @@ -440,7 +440,7 @@ class IncrementalCompilerImpl extends IncrementalCompiler { val outputJars = outputs.flatMap(out => (JarUtils.getOutputJar(out): Option[Path]).toList) val classpathPaths = classpath.map(converter.toPath) val outputJarsOnCp = outputJars.exists { outputJar => - classpathPaths.exists { x: Path => + classpathPaths.exists { (x: Path) => x.toAbsolutePath == outputJar.toAbsolutePath } } @@ -548,8 +548,11 @@ class IncrementalCompilerImpl extends IncrementalCompiler { val equiv = equivCompileSetup(mixedCompiler.log, equivOpts) previousSetup match { // The dummy output needs to be changed to .jar for this to work again. - case _ if compileToJarSwitchedOn(config) => Analysis.empty - case Some(prev) if equiv.equiv(prev, currentSetup) => previousAnalysis + case _ if compileToJarSwitchedOn(config) => + log.debug(s"prevAnalysis: compileToJar has changed") + Analysis.empty + case Some(prev) if equiv.equiv(prev, currentSetup) => + previousAnalysis case Some(prev) if !equivPairs.equiv(prev.extra, currentSetup.extra) => import sbt.internal.inc.ClassFileManager val classFileManager = @@ -663,7 +666,7 @@ class IncrementalCompilerImpl extends IncrementalCompiler { private[sbt] def foldMappers[A](mappers: Array[JavaFunction[A, Optional[A]]]) = { mappers.foldRight(InterfaceUtil.toJavaFunction[A, A](identity)) { (mapper, mappers) => - InterfaceUtil.toJavaFunction[A, A]({ p: A => + InterfaceUtil.toJavaFunction[A, A]({ (p: A) => mapper(p).toOption.getOrElse(mappers(p)) }) } diff --git a/zinc/src/main/scala/sbt/internal/inc/MixedAnalyzingCompiler.scala b/zinc/src/main/scala/sbt/internal/inc/MixedAnalyzingCompiler.scala index 5a934a91e7..ea57f8b4f7 100644 --- a/zinc/src/main/scala/sbt/internal/inc/MixedAnalyzingCompiler.scala +++ b/zinc/src/main/scala/sbt/internal/inc/MixedAnalyzingCompiler.scala @@ -89,7 +89,7 @@ final class MixedAnalyzingCompiler( ) putJavacOutputInJar(outputJar.toFile, outputDir.toFile) case _ => - JarUtils.withPreviousJar(output) { extraClasspath: Seq[Path] => + JarUtils.withPreviousJar(output) { (extraClasspath: Seq[Path]) => javac.compile( javaSrcs, extraClasspath map toVirtualFile, @@ -146,24 +146,38 @@ final class MixedAnalyzingCompiler( val pickleJava = Incremental.isPickleJava(config.currentSetup.options.scalacOptions.toIndexedSeq) + def convertToPath(value: String): String = + if (!value.contains("$")) value + else { + val vf = VirtualFileRef.of(value) + val p = config.converter.toPath(vf) + p.toString() + } + // Compile Scala sources. def compileScala(): Unit = if (scalaSrcs.nonEmpty || pickleJava) { val pickleJarPair = callback.getPickleJarPair.toOption.map(t2 => (t2.get1, t2.get2)) - val scalacOpts = pickleJarPair match { + val scalacOpts0 = config.currentSetup.options.scalacOptions.toVector + val scalacOpts1: Vector[String] = scalacOpts0.map { x => + if (!x.contains("$")) x + else (x.split(":").toVector.map { y => + y.split(",").toVector.map(convertToPath).mkString(",") + }).mkString(":") + } + val scalacOpts: Vector[String] = pickleJarPair match { case Some((originalJar, updatesJar)) => val path = originalJar.toString // ^ Path#toString uses '\' on Windows // but the path could've been specified with '/' in scalacOptions val fwdSlashPath = path.replace('\\', '/') - config.currentSetup.options.scalacOptions.map { + scalacOpts1.map { case s if s == path || s == fwdSlashPath => updatesJar.toString case s => s } - case _ => config.currentSetup.options.scalacOptions + case _ => scalacOpts1 } - - JarUtils.withPreviousJar(output) { extraClasspath: Seq[Path] => + JarUtils.withPreviousJar(output) { (extraClasspath: Seq[Path]) => val sources = if (config.currentSetup.order == Mixed) incSrc else scalaSrcs diff --git a/zinc/src/main/scala/sbt/internal/inc/javac/AnalyzingJavaCompiler.scala b/zinc/src/main/scala/sbt/internal/inc/javac/AnalyzingJavaCompiler.scala index 6aa73c711b..0ffedcb05f 100644 --- a/zinc/src/main/scala/sbt/internal/inc/javac/AnalyzingJavaCompiler.scala +++ b/zinc/src/main/scala/sbt/internal/inc/javac/AnalyzingJavaCompiler.scala @@ -168,7 +168,8 @@ final class AnalyzingJavaCompiler private[sbt] ( ).toArray val javaSources: Array[VirtualFile] = sources.sortBy(_.id).toArray - log.debug(InterfaceUtil.toSupplier(prettyPrintCompilationArguments(args))) + // TODO: https://github.com/sbt/sbt/issues/7883 + // log.debug(InterfaceUtil.toSupplier(prettyPrintCompilationArguments(args))) val success = javac.run(javaSources, args, output, incToolOptions, reporter, log) if (!success) { @@ -209,7 +210,7 @@ final class AnalyzingJavaCompiler private[sbt] ( } { val classes = classFinder.classes try { - val newClasses = Set(classes.paths: _*) -- oldClasses + val newClasses = Set(classes.paths*) -- oldClasses JavaAnalyze(newClasses.toSeq, srcs, log, output, finalJarOutput)( callback, loader, diff --git a/zinc/src/sbt-test/profiler/check-cycles-no-pipelining/test b/zinc/src/sbt-test/profiler/check-cycles-no-pipelining/pending similarity index 100% rename from zinc/src/sbt-test/profiler/check-cycles-no-pipelining/test rename to zinc/src/sbt-test/profiler/check-cycles-no-pipelining/pending diff --git a/zinc/src/sbt-test/profiler/check-cycles/test b/zinc/src/sbt-test/profiler/check-cycles/pending similarity index 100% rename from zinc/src/sbt-test/profiler/check-cycles/test rename to zinc/src/sbt-test/profiler/check-cycles/pending diff --git a/zinc/src/test/scala/sbt/inc/BaseCompilerSpec.scala b/zinc/src/test/scala/sbt/inc/BaseCompilerSpec.scala index 7597740103..2d950e5af0 100644 --- a/zinc/src/test/scala/sbt/inc/BaseCompilerSpec.scala +++ b/zinc/src/test/scala/sbt/inc/BaseCompilerSpec.scala @@ -52,7 +52,7 @@ class BaseCompilerSpec extends BridgeProviderSpecification { implicit class ProjectSetupOps(setup: ProjectSetup) { def createCompiler(): CompilerSetup = setup.createCompiler(scalaVersion, incOptions) - private def createCompiler(sv: String, incOptions: IncOptions): CompilerSetup = { + def createCompiler(sv: String, incOptions: IncOptions): CompilerSetup = { val si = scalaInstance(sv, setup.baseDir, Logger.Null) val bridge = getCompilerBridge(setup.baseDir, Logger.Null, sv) setup.createCompiler(sv, si, bridge, incOptions, log) diff --git a/zinc/src/test/scala/sbt/inc/IncrementalCompilerSpec.scala b/zinc/src/test/scala/sbt/inc/IncrementalCompilerSpec.scala index 1ca060a877..b99ac36cc4 100644 --- a/zinc/src/test/scala/sbt/inc/IncrementalCompilerSpec.scala +++ b/zinc/src/test/scala/sbt/inc/IncrementalCompilerSpec.scala @@ -194,7 +194,7 @@ class IncrementalCompilerSpec extends BaseCompilerSpec { ) ) } - comp.doCompileWithStore(newInputs = incrementalJavaInputs(sources: _*)) + comp.doCompileWithStore(newInputs = incrementalJavaInputs(sources*)) } val res1 = compileJava(f1, f2, f3) diff --git a/zinc/src/test/scala/sbt/inc/MultiProjectIncrementalSpec.scala b/zinc/src/test/scala/sbt/inc/MultiProjectIncrementalSpec.scala index 8f369ce29d..a481e8421c 100644 --- a/zinc/src/test/scala/sbt/inc/MultiProjectIncrementalSpec.scala +++ b/zinc/src/test/scala/sbt/inc/MultiProjectIncrementalSpec.scala @@ -121,8 +121,13 @@ class MultiProjectIncrementalSpec extends BaseCompilerSpec { c1.compile(f1) val result = c2.compileBoth(f2, f3) - assert(startTimes(result) == startTimes(c2.compileBoth(f2, f3))) - assert(startTimes(result) != startTimes(c2.compileBoth(f2, f4))) + val noopResult = c2.compileBoth(f2, f3) + // comparing startTime is no longer a good test + assert(!noopResult.hasModified()) + + // comparing startTime is no longer a good test + val changedResult = c2.compileBoth(f2, f4) + assert(changedResult.hasModified()) } finally { c1.close() c2.close() diff --git a/zinc/src/test/scala/sbt/inc/TestProjectSetup.scala b/zinc/src/test/scala/sbt/inc/TestProjectSetup.scala index 8eb3a143d8..dfab070f5a 100644 --- a/zinc/src/test/scala/sbt/inc/TestProjectSetup.scala +++ b/zinc/src/test/scala/sbt/inc/TestProjectSetup.scala @@ -12,6 +12,7 @@ package sbt package inc +import java.io.FileNotFoundException import java.net.URLClassLoader import java.nio.file.{ Files, Path, Paths } import java.util.Optional @@ -125,8 +126,8 @@ case class CompilerSetup( } def compileBoth(sources: VirtualFile*) = { - val res = compile(sources: _*) - if (res.hasModified) compileAllJava(sources: _*) else res + val res = compile(sources*) + if (res.hasModified) compileAllJava(sources*) else res } def withSrcs(vs: Array[VirtualFile]) = (in: Inputs) => in.withOptions(in.options.withSources(vs)) @@ -136,7 +137,14 @@ case class CompilerSetup( store: AnalysisStore, newInputs: Inputs => Inputs, ): CompileResult = { - val prevRes = store.get().toOption.fold(zinc.emptyPreviousResult)(zinc.previousResult(_)) + // only allow FileNotFoundException to silently use empty previous result + val prevRes = + try { + zinc.previousResult(store.unsafeGet()) + } catch { + case _: FileNotFoundException => zinc.emptyPreviousResult + case _: NoSuchElementException => zinc.emptyPreviousResult + } val newResult = doCompile(inputs => newInputs(inputs.withPreviousResult(prevRes))) store.set(AnalysisContents.create(newResult.analysis, newResult.setup)) newResult diff --git a/zinc/src/test/scala/sbt/inc/cached/CachedHashingSpec.scala b/zinc/src/test/scala/sbt/inc/cached/CachedHashingSpec.scala index abe63a3138..642f435371 100644 --- a/zinc/src/test/scala/sbt/inc/cached/CachedHashingSpec.scala +++ b/zinc/src/test/scala/sbt/inc/cached/CachedHashingSpec.scala @@ -22,7 +22,7 @@ import sbt.internal.inc.{ } import sbt.io.IO -import scala.collection.JavaConverters.asScalaIteratorConverter +import scala.jdk.CollectionConverters._ class CachedHashingSpec extends BaseCompilerSpec { lazy val isWindows: Boolean =