diff --git a/main/src/main/java/sbt/internal/MetaBuildLoader.java b/main/src/main/java/sbt/internal/MetaBuildLoader.java
index 26e10afd3..f9cc8b9c7 100644
--- a/main/src/main/java/sbt/internal/MetaBuildLoader.java
+++ b/main/src/main/java/sbt/internal/MetaBuildLoader.java
@@ -66,7 +66,7 @@ public final class MetaBuildLoader extends URLClassLoader {
public static MetaBuildLoader makeLoader(final AppProvider appProvider) throws IOException {
final String jlineJars = "jline-?[0-9.]+-sbt-.*|jline-terminal(-(jna|jansi))?-[0-9.]+";
final String testInterfaceJars = "test-interface-[0-9.]+";
- final String compilerInterfaceJars = "compiler-interface-[0-9.]+(-.*)?";
+ final String compilerInterfaceJars = "compiler-interface(-.*)?";
final String jansiJars = "jansi-[0-9.]+";
final String jnaJars = "jna-(platform-)?[0-9.]+";
final String fullPattern =
diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala
index 19c5525b2..757772ab1 100644
--- a/main/src/main/scala/sbt/Defaults.scala
+++ b/main/src/main/scala/sbt/Defaults.scala
@@ -88,6 +88,7 @@ import sbt.util.InterfaceUtil.{ t2, toJavaFunction => f1 }
import sbt.util._
import sjsonnew._
import sjsonnew.support.scalajson.unsafe.Converter
+import xsbti.compile.TastyFiles
import xsbti.{ FileConverter, Position }
import scala.collection.immutable.ListMap
@@ -668,15 +669,21 @@ object Defaults extends BuildCommon {
),
cleanIvy := IvyActions.cleanCachedResolutionCache(ivyModule.value, streams.value.log),
clean := clean.dependsOn(cleanIvy).value,
- scalaCompilerBridgeBinaryJar := None,
- scalaCompilerBridgeSource := ZincLmUtil.getDefaultBridgeModule(scalaVersion.value),
- consoleProject / scalaCompilerBridgeSource := ZincLmUtil.getDefaultBridgeModule(
+ scalaCompilerBridgeBinaryJar := Def.settingDyn {
+ val sv = scalaVersion.value
+ if (ScalaArtifacts.isScala3(sv)) fetchBridgeBinaryJarTask(sv)
+ else Def.task[Option[File]](None)
+ }.value,
+ scalaCompilerBridgeSource := ZincLmUtil.getDefaultBridgeSourceModule(scalaVersion.value),
+ consoleProject / scalaCompilerBridgeBinaryJar := None,
+ consoleProject / scalaCompilerBridgeSource := ZincLmUtil.getDefaultBridgeSourceModule(
appConfiguration.value.provider.scalaProvider.version
),
)
// must be a val: duplication detected by object identity
private[this] lazy val compileBaseGlobal: Seq[Setting[_]] = globalDefaults(
Seq(
+ auxiliaryClassFiles := Nil,
incOptions := IncOptions.of(),
classpathOptions :== ClasspathOptionsUtil.boot,
classpathOptions in console :== ClasspathOptionsUtil.repl,
@@ -736,6 +743,18 @@ object Defaults extends BuildCommon {
if (plugin) scalaBase / ("sbt-" + sbtv) else scalaBase
}
+ private def fetchBridgeBinaryJarTask(scalaVersion: String): Initialize[Task[Option[File]]] =
+ Def.task {
+ val bridgeJar = ZincLmUtil.fetchDefaultBridgeModule(
+ scalaVersion,
+ dependencyResolution.value,
+ updateConfiguration.value,
+ (update / unresolvedWarningConfiguration).value,
+ streams.value.log
+ )
+ Some(bridgeJar)
+ }
+
def compilersSetting = {
compilers := {
val st = state.value
@@ -860,9 +879,14 @@ object Defaults extends BuildCommon {
compileAnalysisTargetRoot.value / compileAnalysisFilename.value
},
externalHooks := IncOptions.defaultExternal,
+ auxiliaryClassFiles ++= {
+ if (ScalaArtifacts.isScala3(scalaVersion.value)) List(TastyFiles.instance)
+ else Nil
+ },
incOptions := {
val old = incOptions.value
old
+ .withAuxiliaryClassFiles(auxiliaryClassFiles.value.toArray)
.withExternalHooks(externalHooks.value)
.withClassfileManagerType(
Option(
@@ -1034,21 +1058,22 @@ object Defaults extends BuildCommon {
}
def scalaInstanceFromUpdate: Initialize[Task[ScalaInstance]] = Def.task {
+ val sv = scalaVersion.value
val toolReport = update.value.configuration(Configurations.ScalaTool) getOrElse
sys.error(noToolConfiguration(managedScalaInstance.value))
def files(id: String) =
for {
- m <- toolReport.modules if m.module.name == id;
+ m <- toolReport.modules if m.module.name.startsWith(id)
(art, file) <- m.artifacts if art.`type` == Artifact.DefaultType
} yield file
- def file(id: String) = files(id).headOption getOrElse sys.error(s"Missing ${id}.jar")
+ def file(id: String) = files(id).headOption getOrElse sys.error(s"Missing $id jar file")
val allJars = toolReport.modules.flatMap(_.artifacts.map(_._2))
- val libraryJar = file(ScalaArtifacts.LibraryID)
- val compilerJar = file(ScalaArtifacts.CompilerID)
+ val libraryJars = ScalaArtifacts.libraryIds(sv).map(file)
+ val compilerJar = file(ScalaArtifacts.compilerId(sv))
mkScalaInstance(
- scalaVersion.value,
+ sv,
allJars,
- Array(libraryJar),
+ libraryJars,
compilerJar,
state.value.extendedClassLoaderCache,
scalaInstanceTopLoader.value,
@@ -3820,7 +3845,7 @@ object Classpaths {
version: String
): Seq[ModuleID] =
if (auto)
- modifyForPlugin(plugin, ModuleID(org, ScalaArtifacts.LibraryID, version)) :: Nil
+ modifyForPlugin(plugin, ScalaArtifacts.libraryDependency(org, version)) :: Nil
else
Nil
diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala
index 2df1d1e3f..540648454 100644
--- a/main/src/main/scala/sbt/Keys.scala
+++ b/main/src/main/scala/sbt/Keys.scala
@@ -248,6 +248,7 @@ object Keys {
val aggregate = settingKey[Boolean]("Configures task aggregation.").withRank(BMinusSetting)
val sourcePositionMappers = taskKey[Seq[xsbti.Position => Option[xsbti.Position]]]("Maps positions in generated source files to the original source it was generated from").withRank(DTask)
private[sbt] val externalHooks = taskKey[ExternalHooks]("The external hooks used by zinc.")
+ val auxiliaryClassFiles = taskKey[Seq[AuxiliaryClassFiles]]("The auxiliary class files that must be managed by Zinc (for instance the TASTy files)")
val fileConverter = settingKey[FileConverter]("The file converter used to convert between Path and VirtualFile")
val allowMachinePath = settingKey[Boolean]("Allow machine-specific paths during conversion.")
val reportAbsolutePath = settingKey[Boolean]("Report absolute paths during compilation.")
diff --git a/main/src/main/scala/sbt/coursierint/LMCoursier.scala b/main/src/main/scala/sbt/coursierint/LMCoursier.scala
index b7281a62e..7bd0b6302 100644
--- a/main/src/main/scala/sbt/coursierint/LMCoursier.scala
+++ b/main/src/main/scala/sbt/coursierint/LMCoursier.scala
@@ -173,6 +173,7 @@ object LMCoursier {
}
def coursierConfigurationTask: Def.Initialize[Task[CoursierConfiguration]] = Def.task {
+ val sv = scalaVersion.value
coursierConfiguration(
csrRecursiveResolvers.value,
csrInterProjectDependencies.value.toVector,
@@ -182,9 +183,9 @@ object LMCoursier {
None,
csrMavenProfiles.value,
scalaOrganization.value,
- scalaVersion.value,
+ sv,
scalaBinaryVersion.value,
- autoScalaLibrary.value,
+ autoScalaLibrary.value && !ScalaArtifacts.isScala3(sv),
scalaModuleInfo.value,
allExcludeDependencies.value,
CoursierInputsTasks.credentialsTask.value,
@@ -200,6 +201,7 @@ object LMCoursier {
}
def updateClassifierConfigurationTask: Def.Initialize[Task[CoursierConfiguration]] = Def.task {
+ val sv = scalaVersion.value
coursierConfiguration(
csrRecursiveResolvers.value,
csrInterProjectDependencies.value.toVector,
@@ -209,9 +211,9 @@ object LMCoursier {
Some(transitiveClassifiers.value.map(Classifier(_))),
csrMavenProfiles.value,
scalaOrganization.value,
- scalaVersion.value,
+ sv,
scalaBinaryVersion.value,
- autoScalaLibrary.value,
+ autoScalaLibrary.value && !ScalaArtifacts.isScala3(sv),
scalaModuleInfo.value,
allExcludeDependencies.value,
CoursierInputsTasks.credentialsTask.value,
@@ -227,6 +229,7 @@ object LMCoursier {
}
def updateSbtClassifierConfigurationTask: Def.Initialize[Task[CoursierConfiguration]] = Def.task {
+ val sv = scalaVersion.value
coursierConfiguration(
csrSbtResolvers.value,
Vector(),
@@ -236,9 +239,9 @@ object LMCoursier {
None,
csrMavenProfiles.value,
scalaOrganization.value,
- scalaVersion.value,
+ sv,
scalaBinaryVersion.value,
- autoScalaLibrary.value,
+ autoScalaLibrary.value && !ScalaArtifacts.isScala3(sv),
scalaModuleInfo.value,
allExcludeDependencies.value,
CoursierInputsTasks.credentialsTask.value,
@@ -254,6 +257,7 @@ object LMCoursier {
}
def scalaCompilerBridgeConfigurationTask: Def.Initialize[Task[CoursierConfiguration]] = Def.task {
+ val sv = scalaVersion.value
coursierConfiguration(
csrResolvers.value,
Vector(),
@@ -263,9 +267,9 @@ object LMCoursier {
None,
csrMavenProfiles.value,
scalaOrganization.value,
- scalaVersion.value,
+ sv,
scalaBinaryVersion.value,
- autoScalaLibrary.value,
+ autoScalaLibrary.value && !ScalaArtifacts.isScala3(sv),
scalaModuleInfo.value,
allExcludeDependencies.value,
CoursierInputsTasks.credentialsTask.value,
diff --git a/main/src/main/scala/sbt/internal/Load.scala b/main/src/main/scala/sbt/internal/Load.scala
index a502e2364..ac969a4ba 100755
--- a/main/src/main/scala/sbt/internal/Load.scala
+++ b/main/src/main/scala/sbt/internal/Load.scala
@@ -85,7 +85,7 @@ private[sbt] object Load {
componentProvider = app.provider.components,
secondaryCacheDir = Option(zincDir),
dependencyResolution = dependencyResolution,
- compilerBridgeSource = ZincLmUtil.getDefaultBridgeModule(scalaProvider.version),
+ compilerBridgeSource = ZincLmUtil.getDefaultBridgeSourceModule(scalaProvider.version),
scalaJarsTarget = zincDir,
state.get(BasicKeys.classLoaderCache),
log = log
diff --git a/sbt/src/sbt-test/compiler-project/scala3-tasty-management/build.sbt b/sbt/src/sbt-test/compiler-project/scala3-tasty-management/build.sbt
new file mode 100644
index 000000000..208b8c684
--- /dev/null
+++ b/sbt/src/sbt-test/compiler-project/scala3-tasty-management/build.sbt
@@ -0,0 +1,3 @@
+ThisBuild / scalaVersion := "3.0.0-M2"
+
+lazy val root = project.in(file("."))
diff --git a/sbt/src/sbt-test/compiler-project/scala3-tasty-management/src/main/scala/A.scala b/sbt/src/sbt-test/compiler-project/scala3-tasty-management/src/main/scala/A.scala
new file mode 100644
index 000000000..c52c45808
--- /dev/null
+++ b/sbt/src/sbt-test/compiler-project/scala3-tasty-management/src/main/scala/A.scala
@@ -0,0 +1,3 @@
+class A {
+ def initialized: Boolean = false
+}
diff --git a/sbt/src/sbt-test/compiler-project/scala3-tasty-management/src/main/scala/B.scala b/sbt/src/sbt-test/compiler-project/scala3-tasty-management/src/main/scala/B.scala
new file mode 100644
index 000000000..066d5fc59
--- /dev/null
+++ b/sbt/src/sbt-test/compiler-project/scala3-tasty-management/src/main/scala/B.scala
@@ -0,0 +1,3 @@
+class B {
+ def foo(a: A): Boolean = a.initialized
+}
diff --git a/sbt/src/sbt-test/compiler-project/scala3-tasty-management/test b/sbt/src/sbt-test/compiler-project/scala3-tasty-management/test
new file mode 100644
index 000000000..3efda69bb
--- /dev/null
+++ b/sbt/src/sbt-test/compiler-project/scala3-tasty-management/test
@@ -0,0 +1,11 @@
+> compile
+
+$ exists target/scala-3.0.0-M2/classes/A.tasty
+$ exists target/scala-3.0.0-M2/classes/B.tasty
+
+$ delete src/main/scala/B.scala
+
+> compile
+
+$ exists target/scala-3.0.0-M2/classes/A.tasty
+-$ exists target/scala-3.0.0-M2/classes/B.tasty
diff --git a/sbt/src/sbt-test/dependency-management/artifact/build.sbt b/sbt/src/sbt-test/dependency-management/artifact/build.sbt
index bc8d53abd..d0d5afc46 100644
--- a/sbt/src/sbt-test/dependency-management/artifact/build.sbt
+++ b/sbt/src/sbt-test/dependency-management/artifact/build.sbt
@@ -1,4 +1,5 @@
import sbt.internal.inc.classpath.ClasspathUtilities
+import xsbti.AppConfiguration
lazy val checkFull = taskKey[Unit]("")
lazy val check = taskKey[Unit]("")
@@ -19,7 +20,8 @@ lazy val root = (project in file("."))
.settings(
ivyPaths := IvyPaths(baseDirectory.value, Some(target.value / "ivy-cache")),
publishTo := Some(Resolver.file("Test Publish Repo", file("test-repo"))),
- resolvers += (baseDirectory { base => "Test Repo" at (base / "test-repo").toURI.toString }).value,
+ scalaCompilerBridgeResolvers += userLocalFileResolver(appConfiguration.value),
+ resolvers += baseDirectory { base => "Test Repo" at (base / "test-repo").toURI.toString }.value,
moduleName := artifactID,
projectID := (if (baseDirectory.value / "retrieve" exists) retrieveID else publishedID),
artifact in (Compile, packageBin) := mainArtifact,
@@ -67,3 +69,9 @@ def checkTask(classpath: TaskKey[Classpath]) = Def.task {
try { Class.forName("test.Test", false, loader); () }
catch { case _: ClassNotFoundException | _: NoClassDefFoundError => sys.error(s"Dependency not retrieved properly: $deps, $cp") }
}
+
+// use the user local resolver to fetch the SNAPSHOT version of the compiler-bridge
+def userLocalFileResolver(appConfig: AppConfiguration): Resolver = {
+ val ivyHome = appConfig.provider.scalaProvider.launcher.ivyHome
+ Resolver.file("User Local", ivyHome / "local")(Resolver.defaultIvyPatterns)
+}
diff --git a/sbt/src/sbt-test/dependency-management/cache-classifiers/multi.sbt b/sbt/src/sbt-test/dependency-management/cache-classifiers/multi.sbt
index 4e22c07f8..69771b0b8 100644
--- a/sbt/src/sbt-test/dependency-management/cache-classifiers/multi.sbt
+++ b/sbt/src/sbt-test/dependency-management/cache-classifiers/multi.sbt
@@ -1,3 +1,5 @@
+import xsbti.AppConfiguration
+
ThisBuild / scalaVersion := "2.12.12"
// TTL of Coursier is 24h
@@ -11,6 +13,7 @@ val b = project
.settings(
localCache,
libraryDependencies += "org.example" %% "artifacta" % "1.0.0-SNAPSHOT" withSources() classifier("tests"),
+ scalaCompilerBridgeResolvers += userLocalFileResolver(appConfiguration.value),
externalResolvers := Vector(
MavenCache("demo", ((baseDirectory in ThisBuild).value / "demo-repo")),
DefaultMavenRepository
@@ -26,3 +29,9 @@ val a = project
publishArtifact in (Test,packageBin) := true,
publishTo := Some(MavenCache("demo", ((baseDirectory in ThisBuild).value / "demo-repo")))
)
+
+// use the user local resolver to fetch the SNAPSHOT version of the compiler-bridge
+def userLocalFileResolver(appConfig: AppConfiguration): Resolver = {
+ val ivyHome = appConfig.provider.scalaProvider.launcher.ivyHome
+ Resolver.file("User Local", ivyHome / "local")(Resolver.defaultIvyPatterns)
+}
diff --git a/sbt/src/sbt-test/dependency-management/cached-resolution-configurations/build.sbt b/sbt/src/sbt-test/dependency-management/cached-resolution-configurations/build.sbt
index d52b9e114..018bab537 100644
--- a/sbt/src/sbt-test/dependency-management/cached-resolution-configurations/build.sbt
+++ b/sbt/src/sbt-test/dependency-management/cached-resolution-configurations/build.sbt
@@ -1,3 +1,5 @@
+import xsbti.AppConfiguration
+
ThisBuild / csrCacheDirectory := (ThisBuild / baseDirectory).value / "coursier-cache"
def commonSettings: Vector[Def.Setting[_]] =
@@ -5,6 +7,7 @@ def commonSettings: Vector[Def.Setting[_]] =
organization := "com.example",
ivyPaths := IvyPaths( (baseDirectory in ThisBuild).value, Some((baseDirectory in LocalRootProject).value / "ivy-cache")),
dependencyCacheDirectory := (baseDirectory in LocalRootProject).value / "dependency",
+ scalaCompilerBridgeResolvers += userLocalFileResolver(appConfiguration.value),
resolvers += Resolver.file("buggy", (baseDirectory in LocalRootProject).value / "repo")(
Patterns(
ivyPatterns = Vector("[organization]/[module]/[revision]/ivy.xml"),
@@ -28,3 +31,9 @@ lazy val b = project dependsOn(a) settings(
updateOptions := updateOptions.value.withCachedResolution(true), //comment this line to make ws compile
libraryDependencies += "a" % "b" % "1.0.1" % "compile->runtime"
)
+
+// use the user local resolver to fetch the SNAPSHOT version of the compiler-bridge
+def userLocalFileResolver(appConfig: AppConfiguration): Resolver = {
+ val ivyHome = appConfig.provider.scalaProvider.launcher.ivyHome
+ Resolver.file("User Local", ivyHome / "local")(Resolver.defaultIvyPatterns)
+}
diff --git a/sbt/src/sbt-test/dependency-management/evicted-semver-spec/build.sbt b/sbt/src/sbt-test/dependency-management/evicted-semver-spec/build.sbt
index 6d1caf3a7..9460b811d 100644
--- a/sbt/src/sbt-test/dependency-management/evicted-semver-spec/build.sbt
+++ b/sbt/src/sbt-test/dependency-management/evicted-semver-spec/build.sbt
@@ -1,3 +1,5 @@
+import xsbti.AppConfiguration
+// ThisBuild / useCoursier := false
ThisBuild / organization := "com.example"
ThisBuild / scalaVersion := "2.13.3"
ThisBuild / versionScheme := Some("semver-spec")
@@ -7,6 +9,7 @@ def commonSettings: Seq[Def.Setting[_]] =
Seq(
fullResolvers := fullResolvers.value.filterNot(_.name == "inter-project"),
publishTo := Some(MavenCache("local-maven", (LocalRootProject / target).value / "local-maven")),
+ scalaCompilerBridgeResolvers += userLocalFileResolver(appConfiguration.value),
resolvers += MavenCache("local-maven", (LocalRootProject / target).value / "local-maven"),
)
@@ -65,3 +68,8 @@ val use2 = project
"org.typelevel" %% "cats-effect" % "3.0.0-M4",
),
)
+// use the user local resolver to fetch the SNAPSHOT version of the compiler-bridge
+def userLocalFileResolver(appConfig: AppConfiguration): Resolver = {
+ val ivyHome = appConfig.provider.scalaProvider.launcher.ivyHome
+ Resolver.file("User Local", ivyHome / "local")(Resolver.defaultIvyPatterns)
+}
diff --git a/sbt/src/sbt-test/dependency-management/scala-organization/build.sbt b/sbt/src/sbt-test/dependency-management/scala-organization/build.sbt
index 42d335c4d..068fe0611 100644
--- a/sbt/src/sbt-test/dependency-management/scala-organization/build.sbt
+++ b/sbt/src/sbt-test/dependency-management/scala-organization/build.sbt
@@ -52,5 +52,5 @@ checkDependencies := {
if !m.evicted
} yield m.module.withExtraAttributes(Map.empty)).toSet
- assert(resolved == expected)
+ assert(resolved == expected, s"$resolved != $expected")
}
diff --git a/sbt/src/sbt-test/dependency-management/scala3-auto-scala-library/build.sbt b/sbt/src/sbt-test/dependency-management/scala3-auto-scala-library/build.sbt
new file mode 100644
index 000000000..9478d98dd
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-auto-scala-library/build.sbt
@@ -0,0 +1,19 @@
+autoScalaLibrary := false
+scalaVersion := "3.0.0-M2"
+libraryDependencies += "com.chuusai" % "shapeless_2.13" % "2.3.3"
+
+val checkScalaLibrary = TaskKey[Unit]("checkScalaLibrary")
+
+checkScalaLibrary := {
+ val scalaLibsJars = (Compile / managedClasspath).value
+ .map(_.data.getName)
+ .filter(name => name.startsWith("scala-library") || name.startsWith("scala3-library"))
+ .sorted
+ val expectedScalaLibsJars = Seq(
+ "scala-library-2.13.0.jar"
+ )
+ assert(
+ scalaLibsJars == expectedScalaLibsJars,
+ s"$scalaLibsJars != $expectedScalaLibsJars"
+ )
+}
diff --git a/sbt/src/sbt-test/dependency-management/scala3-auto-scala-library/test b/sbt/src/sbt-test/dependency-management/scala3-auto-scala-library/test
new file mode 100644
index 000000000..f56f5a75e
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-auto-scala-library/test
@@ -0,0 +1 @@
+> checkScalaLibrary
diff --git a/sbt/src/sbt-test/dependency-management/scala3-compiler-bridge-binary/A.scala b/sbt/src/sbt-test/dependency-management/scala3-compiler-bridge-binary/A.scala
new file mode 100644
index 000000000..c3ab8e5cc
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-compiler-bridge-binary/A.scala
@@ -0,0 +1 @@
+val A = "A"
diff --git a/sbt/src/sbt-test/dependency-management/scala3-compiler-bridge-binary/build.sbt b/sbt/src/sbt-test/dependency-management/scala3-compiler-bridge-binary/build.sbt
new file mode 100644
index 000000000..998afcca4
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-compiler-bridge-binary/build.sbt
@@ -0,0 +1,8 @@
+ThisBuild / scalaVersion := "3.0.0-M2"
+
+lazy val check = taskKey[Unit]("")
+
+check := {
+ val bridge = scalaCompilerBridgeBinaryJar.value
+ bridge.getOrElse(sys.error(s"bridge JAR is missing"))
+}
diff --git a/sbt/src/sbt-test/dependency-management/scala3-compiler-bridge-binary/test b/sbt/src/sbt-test/dependency-management/scala3-compiler-bridge-binary/test
new file mode 100644
index 000000000..5f1fbe2c5
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-compiler-bridge-binary/test
@@ -0,0 +1,2 @@
+> check
+> compile
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-home/build.sbt b/sbt/src/sbt-test/dependency-management/scala3-scala-home/build.sbt
new file mode 100644
index 000000000..e3dcd92e1
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-scala-home/build.sbt
@@ -0,0 +1,9 @@
+scalaVersion := "3.0.0-M2"
+
+val makeHome = taskKey[Unit]("Populates the 'home/lib' directory with Scala jars from the default ScalaInstance")
+
+makeHome := {
+ val lib = baseDirectory.value / "home" / "lib"
+ for(jar <- scalaInstance.value.allJars)
+ IO.copyFile(jar, lib / jar.getName)
+}
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-home/changes/real-build.sbt b/sbt/src/sbt-test/dependency-management/scala3-scala-home/changes/real-build.sbt
new file mode 100644
index 000000000..876da64cf
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-scala-home/changes/real-build.sbt
@@ -0,0 +1,11 @@
+scalaVersion := "3.0.0-M2"
+scalaHome := Some(baseDirectory.value / "home")
+
+val checkUpdate = taskKey[Unit]("Ensures that resolved Scala artifacts are replaced with ones from the configured Scala home directory")
+
+checkUpdate := {
+ val report = update.value
+ val lib = (scalaHome.value.get / "lib").getCanonicalFile
+ for(f <- report.allFiles)
+ assert(f.getParentFile == lib, "Artifact not in Scala home directory: " + f.getAbsolutePath)
+}
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-home/test b/sbt/src/sbt-test/dependency-management/scala3-scala-home/test
new file mode 100644
index 000000000..7eadb9215
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-scala-home/test
@@ -0,0 +1,4 @@
+> makeHome
+$ copy-file changes/real-build.sbt build.sbt
+> reload
+> checkUpdate
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-organization/build.sbt b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/build.sbt
new file mode 100644
index 000000000..dfd1b73e5
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/build.sbt
@@ -0,0 +1,48 @@
+ThisBuild / useCoursier := false
+
+scalaOrganization := "org.other"
+scalaVersion := "3.0.0-M2"
+
+resolvers += Resolver.file("buggy", (baseDirectory in LocalRootProject).value / "repo")(
+ Patterns(
+ ivyPatterns = Vector("[organization]/[module]/[revision]/ivy.xml"),
+ artifactPatterns = Vector("[organization]/[module]/[revision]/dummy.jar"),
+ isMavenCompatible = false,
+ descriptorOptional = true,
+ skipConsistencyCheck = true
+ )
+)
+
+libraryDependencies += "org.typelevel" %% "cats-core" % "2.3.0"
+
+val checkDependencies = taskKey[Unit]("Checks that dependencies are correct.")
+
+checkDependencies := {
+ val expected: Set[ModuleID] = Set(
+ "org.scala-lang.modules" % "scala-asm" % "7.3.1-scala-1",
+ "org.jline" % "jline-reader" % "3.15.0",
+ "com.google.protobuf" % "protobuf-java" % "3.7.0",
+ "org.typelevel" % "cats-kernel_3.0.0-M2" % "2.3.0",
+ "org.jline" % "jline-terminal-jna" % "3.15.0",
+ "org.jline" % "jline-terminal" % "3.15.0",
+ "org.scala-sbt" % "compiler-interface" % "1.3.5",
+ "net.java.dev.jna" % "jna" % "5.3.1",
+ "org.other" % "scala-library" % "2.13.4",
+ "org.other" % "scala3-library_3.0.0-M2" % "3.0.0-M2",
+ "org.typelevel" % "simulacrum-scalafix-annotations_3.0.0-M2" % "0.5.1",
+ "org.other" % "scala3-compiler_3.0.0-M2" % "3.0.0-M2",
+ "org.other" % "scala3-interfaces" % "3.0.0-M2",
+ "org.other" % "tasty-core_3.0.0-M2" % "3.0.0-M2",
+ "org.typelevel" % "cats-core_3.0.0-M2" % "2.3.0",
+ "org.scala-sbt" % "util-interface" % "1.3.0"
+ )
+
+ val resolved: Set[ModuleID] =
+ (for {
+ c <- update.value.configurations
+ m <- c.modules
+ if !m.evicted
+ } yield m.module.withExtraAttributes(Map.empty)).toSet
+
+ assert(resolved == expected, s"$resolved != $expected")
+}
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala-library/2.13.4/dummy.jar b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala-library/2.13.4/dummy.jar
new file mode 100644
index 000000000..e69de29bb
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala-library/2.13.4/ivy.xml b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala-library/2.13.4/ivy.xml
new file mode 100644
index 000000000..6ef3dce02
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala-library/2.13.4/ivy.xml
@@ -0,0 +1,28 @@
+
+
+
+ Scala Standard Library
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-compiler_3.0.0-M2/3.0.0-M2/dummy.jar b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-compiler_3.0.0-M2/3.0.0-M2/dummy.jar
new file mode 100644
index 000000000..e69de29bb
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-compiler_3.0.0-M2/3.0.0-M2/ivy.xml b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-compiler_3.0.0-M2/3.0.0-M2/ivy.xml
new file mode 100644
index 000000000..5b6236f36
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-compiler_3.0.0-M2/3.0.0-M2/ivy.xml
@@ -0,0 +1,39 @@
+
+
+
+ scala3-compiler
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-interfaces/3.0.0-M2/dummy.jar b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-interfaces/3.0.0-M2/dummy.jar
new file mode 100644
index 000000000..e69de29bb
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-interfaces/3.0.0-M2/ivy.xml b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-interfaces/3.0.0-M2/ivy.xml
new file mode 100644
index 000000000..cab483d67
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-interfaces/3.0.0-M2/ivy.xml
@@ -0,0 +1,29 @@
+
+
+
+ scala3-interfaces
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-library_3.0.0-M2/3.0.0-M2/dummy.jar b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-library_3.0.0-M2/3.0.0-M2/dummy.jar
new file mode 100644
index 000000000..e69de29bb
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-library_3.0.0-M2/3.0.0-M2/ivy.xml b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-library_3.0.0-M2/3.0.0-M2/ivy.xml
new file mode 100644
index 000000000..593d39bb4
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/scala3-library_3.0.0-M2/3.0.0-M2/ivy.xml
@@ -0,0 +1,30 @@
+
+
+
+ scala3-library-bootstrapped
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/tasty-core_3.0.0-M2/3.0.0-M2/dummy.jar b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/tasty-core_3.0.0-M2/3.0.0-M2/dummy.jar
new file mode 100644
index 000000000..e69de29bb
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/tasty-core_3.0.0-M2/3.0.0-M2/ivy.xml b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/tasty-core_3.0.0-M2/3.0.0-M2/ivy.xml
new file mode 100644
index 000000000..5716a9b6e
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/repo/org.other/tasty-core_3.0.0-M2/3.0.0-M2/ivy.xml
@@ -0,0 +1,30 @@
+
+
+
+ tasty-core-bootstrapped
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sbt/src/sbt-test/dependency-management/scala3-scala-organization/test b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/test
new file mode 100644
index 000000000..6e1b1a750
--- /dev/null
+++ b/sbt/src/sbt-test/dependency-management/scala3-scala-organization/test
@@ -0,0 +1,3 @@
+# this test is pending because the IvyDependencyResolution is not yet able
+# to override the Scala 3 artifacts
+> checkDependencies
diff --git a/sbt/src/sbt-test/project/scala3-console-project/build.sbt b/sbt/src/sbt-test/project/scala3-console-project/build.sbt
new file mode 100644
index 000000000..208b8c684
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-console-project/build.sbt
@@ -0,0 +1,3 @@
+ThisBuild / scalaVersion := "3.0.0-M2"
+
+lazy val root = project.in(file("."))
diff --git a/sbt/src/sbt-test/project/scala3-console-project/test b/sbt/src/sbt-test/project/scala3-console-project/test
new file mode 100644
index 000000000..b80db65f1
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-console-project/test
@@ -0,0 +1 @@
+> consoleProject
diff --git a/sbt/src/sbt-test/project/scala3-example-project/LICENSE b/sbt/src/sbt-test/project/scala3-example-project/LICENSE
new file mode 100644
index 000000000..728844ee3
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-example-project/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2015 The dotty-example-project contributors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/sbt/src/sbt-test/project/scala3-example-project/README.md b/sbt/src/sbt-test/project/scala3-example-project/README.md
new file mode 100644
index 000000000..daa544226
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-example-project/README.md
@@ -0,0 +1 @@
+Cut-n-pasted from https://github.com/scala/scala3-example-project/tree/353ccef820699f20eb012420a9deb28814481031
diff --git a/sbt/src/sbt-test/project/scala3-example-project/build.sbt b/sbt/src/sbt-test/project/scala3-example-project/build.sbt
new file mode 100644
index 000000000..14f3f6017
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-example-project/build.sbt
@@ -0,0 +1 @@
+ThisBuild / scalaVersion := "3.0.0-M3"
diff --git a/sbt/src/sbt-test/project/scala3-example-project/src/main/scala-3/Main.scala b/sbt/src/sbt-test/project/scala3-example-project/src/main/scala-3/Main.scala
new file mode 100644
index 000000000..8a44ae4ef
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-example-project/src/main/scala-3/Main.scala
@@ -0,0 +1,16 @@
+
+object Main {
+
+ def main(args: Array[String]): Unit = {
+
+ runExample("Trait Params")(TraitParams.test)
+
+ }
+
+ private def runExample(name: String)(f: => Unit) = {
+ println(Console.MAGENTA + s"$name example:" + Console.RESET)
+ f
+ println()
+ }
+
+}
diff --git a/sbt/src/sbt-test/project/scala3-example-project/src/main/scala-3/TraitParams.scala b/sbt/src/sbt-test/project/scala3-example-project/src/main/scala-3/TraitParams.scala
new file mode 100644
index 000000000..1ca8d7c42
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-example-project/src/main/scala-3/TraitParams.scala
@@ -0,0 +1,21 @@
+/**
+ * Trait Parameters: https://dotty.epfl.ch/docs/reference/other-new-features/trait-parameters.html
+ */
+object TraitParams {
+
+ trait Base(val msg: String)
+ class A extends Base("Hello")
+ class B extends Base("Dotty!")
+
+ // Union types only exist in Dotty, so there's no chance that this will accidentally be compiled with Scala 2
+ private def printMessages(msgs: (A | B)*) = println(msgs.map(_.msg).mkString(" "))
+
+ def test: Unit = {
+
+ printMessages(new A, new B)
+
+ // Sanity check the classpath: this won't run if the dotty jar is not present.
+ val x: Int => Int = z => z
+ x(1)
+ }
+}
diff --git a/sbt/src/sbt-test/project/scala3-example-project/test b/sbt/src/sbt-test/project/scala3-example-project/test
new file mode 100644
index 000000000..62ea636c1
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-example-project/test
@@ -0,0 +1 @@
+> run
diff --git a/sbt/src/sbt-test/project/scala3-instance-loader/build.sbt b/sbt/src/sbt-test/project/scala3-instance-loader/build.sbt
new file mode 100644
index 000000000..53bf8a0d3
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-instance-loader/build.sbt
@@ -0,0 +1,13 @@
+ThisBuild / scalaVersion := "3.0.0-M3"
+
+lazy val check = taskKey[Unit]("check the Scala 3 instance class loader")
+
+lazy val xsbtiClass = classOf[xsbti.compile.Compilers]
+
+check := {
+ val scala3Loader = scalaInstance.value.loader
+ assert(
+ scala3Loader.loadClass(xsbtiClass.getCanonicalName) == xsbtiClass,
+ "The Scala 3 instance classloader does not load the same `xsbti` classes than sbt"
+ )
+}
\ No newline at end of file
diff --git a/sbt/src/sbt-test/project/scala3-instance-loader/test b/sbt/src/sbt-test/project/scala3-instance-loader/test
new file mode 100644
index 000000000..15675b169
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-instance-loader/test
@@ -0,0 +1 @@
+> check
diff --git a/sbt/src/sbt-test/project/scala3-sandwich-sjs/app/src/main/scala/app/Main.scala b/sbt/src/sbt-test/project/scala3-sandwich-sjs/app/src/main/scala/app/Main.scala
new file mode 100644
index 000000000..e3a0fa2ce
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-sandwich-sjs/app/src/main/scala/app/Main.scala
@@ -0,0 +1,9 @@
+package app
+
+import mylib._
+
+object Main {
+ def main(args: Array[String]): Unit = {
+ println(MyLib.square(5))
+ }
+}
diff --git a/sbt/src/sbt-test/project/scala3-sandwich-sjs/build.sbt b/sbt/src/sbt-test/project/scala3-sandwich-sjs/build.sbt
new file mode 100644
index 000000000..01e81e167
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-sandwich-sjs/build.sbt
@@ -0,0 +1,15 @@
+ThisBuild / scalaVersion := "2.13.4"
+ThisBuild / scalacOptions += "-Ytasty-reader"
+
+lazy val scala3code = project
+ .enablePlugins(ScalaJSPlugin)
+ .settings(scalaVersion := "3.0.0-M1")
+
+lazy val app = project
+ .enablePlugins(ScalaJSPlugin)
+ .dependsOn(scala3code)
+ .settings(
+ scalaVersion := "2.13.4",
+ scalacOptions += "-Ytasty-reader",
+ scalaJSUseMainModuleInitializer := true
+ )
diff --git a/sbt/src/sbt-test/project/scala3-sandwich-sjs/project/plugins.sbt b/sbt/src/sbt-test/project/scala3-sandwich-sjs/project/plugins.sbt
new file mode 100644
index 000000000..8f1d0ac9b
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-sandwich-sjs/project/plugins.sbt
@@ -0,0 +1 @@
+addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.3.1")
diff --git a/sbt/src/sbt-test/project/scala3-sandwich-sjs/scala3code/src/main/scala/mylib/MyLib.scala b/sbt/src/sbt-test/project/scala3-sandwich-sjs/scala3code/src/main/scala/mylib/MyLib.scala
new file mode 100644
index 000000000..ae2f3af75
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-sandwich-sjs/scala3code/src/main/scala/mylib/MyLib.scala
@@ -0,0 +1,5 @@
+package mylib
+
+object MyLib {
+ def square(x: Int): Int = x * x
+}
diff --git a/sbt/src/sbt-test/project/scala3-sandwich-sjs/test b/sbt/src/sbt-test/project/scala3-sandwich-sjs/test
new file mode 100644
index 000000000..63092ffa4
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-sandwich-sjs/test
@@ -0,0 +1 @@
+> app/run
diff --git a/sbt/src/sbt-test/project/scala3-sandwich/bar-app/D.scala b/sbt/src/sbt-test/project/scala3-sandwich/bar-app/D.scala
new file mode 100644
index 000000000..b937ae06c
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-sandwich/bar-app/D.scala
@@ -0,0 +1,5 @@
+package example
+
+object D {
+ val x = C.x
+}
diff --git a/sbt/src/sbt-test/project/scala3-sandwich/bar-core/C.scala b/sbt/src/sbt-test/project/scala3-sandwich/bar-core/C.scala
new file mode 100644
index 000000000..4d4fcc6df
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-sandwich/bar-core/C.scala
@@ -0,0 +1,5 @@
+package example
+
+object C {
+ val x = 1
+}
diff --git a/sbt/src/sbt-test/project/scala3-sandwich/build.sbt b/sbt/src/sbt-test/project/scala3-sandwich/build.sbt
new file mode 100644
index 000000000..69a2ca58f
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-sandwich/build.sbt
@@ -0,0 +1,23 @@
+ThisBuild / scalaVersion := "3.0.0-M1"
+
+lazy val scala213 = "2.13.4"
+
+lazy val root = (project in file("."))
+ .aggregate(fooApp, fooCore, barApp, barCore)
+
+lazy val fooApp = (project in file("foo-app"))
+ .dependsOn(fooCore)
+
+lazy val fooCore = (project in file("foo-core"))
+ .settings(
+ scalaVersion := scala213,
+ )
+
+lazy val barApp = (project in file("bar-app"))
+ .dependsOn(barCore)
+ .settings(
+ scalaVersion := scala213,
+ scalacOptions += "-Ytasty-reader"
+ )
+
+lazy val barCore = (project in file("bar-core"))
diff --git a/sbt/src/sbt-test/project/scala3-sandwich/foo-app/B.scala b/sbt/src/sbt-test/project/scala3-sandwich/foo-app/B.scala
new file mode 100644
index 000000000..ed82c07d1
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-sandwich/foo-app/B.scala
@@ -0,0 +1,5 @@
+package example
+
+object B {
+ val x = A.x
+}
diff --git a/sbt/src/sbt-test/project/scala3-sandwich/foo-core/A.scala b/sbt/src/sbt-test/project/scala3-sandwich/foo-core/A.scala
new file mode 100644
index 000000000..be4b82a9f
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-sandwich/foo-core/A.scala
@@ -0,0 +1,5 @@
+package example
+
+object A {
+ val x = 1
+}
diff --git a/sbt/src/sbt-test/project/scala3-sandwich/test b/sbt/src/sbt-test/project/scala3-sandwich/test
new file mode 100644
index 000000000..19ccc5787
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-sandwich/test
@@ -0,0 +1,3 @@
+> fooApp/compile
+
+> barApp/compile
diff --git a/sbt/src/sbt-test/project/scala3-semanticdb/LICENSE b/sbt/src/sbt-test/project/scala3-semanticdb/LICENSE
new file mode 100644
index 000000000..728844ee3
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-semanticdb/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2015 The dotty-example-project contributors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/sbt/src/sbt-test/project/scala3-semanticdb/README.md b/sbt/src/sbt-test/project/scala3-semanticdb/README.md
new file mode 100644
index 000000000..daa544226
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-semanticdb/README.md
@@ -0,0 +1 @@
+Cut-n-pasted from https://github.com/scala/scala3-example-project/tree/353ccef820699f20eb012420a9deb28814481031
diff --git a/sbt/src/sbt-test/project/scala3-semanticdb/build.sbt b/sbt/src/sbt-test/project/scala3-semanticdb/build.sbt
new file mode 100644
index 000000000..7b302985e
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-semanticdb/build.sbt
@@ -0,0 +1,13 @@
+ThisBuild / scalaVersion := "3.0.0-M2"
+ThisBuild / semanticdbEnabled := true
+
+lazy val check = taskKey[Unit]("check the Scala 3 semanticdb files")
+
+Compile / check := checkTask("Main.semanticdb")
+Test / check := checkTask("Test.semanticdb")
+
+def checkTask(fileName: String): Def.Initialize[Task[Unit]] = Def.task {
+ val _ = compile.value
+ val dir = semanticdbTargetRoot.value
+ assert(IO.listFiles(dir).exists(_.getName == fileName), s"$fileName is missing")
+}
\ No newline at end of file
diff --git a/sbt/src/sbt-test/project/scala3-semanticdb/src/main/scala/Main.scala b/sbt/src/sbt-test/project/scala3-semanticdb/src/main/scala/Main.scala
new file mode 100644
index 000000000..9deb66d0b
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-semanticdb/src/main/scala/Main.scala
@@ -0,0 +1,8 @@
+
+object Main {
+ val msg = "Hello, World!"
+
+ def main(args: Array[String]): Unit = {
+ println(msg)
+ }
+}
diff --git a/sbt/src/sbt-test/project/scala3-semanticdb/src/test/scala/Test.scala b/sbt/src/sbt-test/project/scala3-semanticdb/src/test/scala/Test.scala
new file mode 100644
index 000000000..f197443c9
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-semanticdb/src/test/scala/Test.scala
@@ -0,0 +1,3 @@
+object Test {
+ assert(Main.msg == "Hello, World!")
+}
\ No newline at end of file
diff --git a/sbt/src/sbt-test/project/scala3-semanticdb/test b/sbt/src/sbt-test/project/scala3-semanticdb/test
new file mode 100644
index 000000000..699323992
--- /dev/null
+++ b/sbt/src/sbt-test/project/scala3-semanticdb/test
@@ -0,0 +1,3 @@
+> Compile / check
+> Test / check
+
diff --git a/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala b/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala
index 6adc67505..3ca2d2ab0 100644
--- a/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala
+++ b/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala
@@ -9,48 +9,34 @@ package sbt
package internal
package inc
-import java.io.File
-import java.nio.file.{ Files, Path }
-import java.util.concurrent.Callable
-
import sbt.internal.inc.classpath.ClasspathUtil
-import sbt.io.IO
import sbt.internal.librarymanagement._
import sbt.internal.util.{ BufferedLogger, FullLogger }
+import sbt.io.IO
import sbt.librarymanagement._
import sbt.librarymanagement.syntax._
import sbt.util.InterfaceUtil.{ toSupplier => f0 }
import xsbti.ArtifactInfo._
+import xsbti.compile.{
+ ClasspathOptionsUtil,
+ CompilerBridgeProvider,
+ ScalaInstance => XScalaInstance
+}
import xsbti.{ ComponentProvider, GlobalLock, Logger }
-import xsbti.compile.{ ClasspathOptionsUtil, CompilerBridgeProvider }
+
+import java.io.File
+import java.nio.file.{ Files, Path }
+import java.util.concurrent.Callable
private[sbt] object ZincComponentCompiler {
- import xsbti.compile.ScalaInstance
-
final val binSeparator = "-bin_"
final val javaClassVersion = System.getProperty("java.class.version")
private[inc] final val sbtOrgTemp = JsonUtil.sbtOrgTemp
private[inc] final val modulePrefixTemp = "temp-module-"
- private[sbt] final lazy val incrementalVersion: String = ZincComponentManager.version
-
- private val CompileConf = Some(Configurations.Compile.name)
private val lock: AnyRef = new {}
- private[sbt] def getDefaultBridgeModule(scalaVersion: String): ModuleID = {
- val compilerBridgeId = scalaVersion match {
- case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10"
- case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11"
- case sc if (sc startsWith "2.12.") => "compiler-bridge_2.12"
- case "2.13.0-M1" => "compiler-bridge_2.12"
- case _ => "compiler-bridge_2.13"
- }
- ModuleID(SbtOrganization, compilerBridgeId, incrementalVersion)
- .withConfigurations(CompileConf)
- .sources()
- }
-
/** Defines the internal implementation of a bridge provider. */
private class ZincCompilerBridgeProvider(
userProvidedBridgeSources: Option[ModuleID],
@@ -67,7 +53,7 @@ private[sbt] object ZincComponentCompiler {
*/
def compiledBridge(
bridgeSources: ModuleID,
- scalaInstance: ScalaInstance,
+ scalaInstance: XScalaInstance,
logger: Logger,
): File = lock.synchronized {
val raw = new RawCompiler(scalaInstance, ClasspathOptionsUtil.auto, logger)
@@ -77,9 +63,10 @@ private[sbt] object ZincComponentCompiler {
zinc.compiledBridgeJar
}
- override def fetchCompiledBridge(scalaInstance: ScalaInstance, logger: Logger): File = {
+ override def fetchCompiledBridge(scalaInstance: XScalaInstance, logger: Logger): File = {
val scalaVersion = scalaInstance.actualVersion()
- val bridgeSources = userProvidedBridgeSources.getOrElse(getDefaultBridgeModule(scalaVersion))
+ val bridgeSources = userProvidedBridgeSources
+ .getOrElse(ZincLmUtil.getDefaultBridgeSourceModule(scalaVersion))
compiledBridge(bridgeSources, scalaInstance, logger)
}
@@ -125,7 +112,7 @@ private[sbt] object ZincComponentCompiler {
ScalaArtifacts(scalaCompilerJar, Vector(scalaLibraryJar), others)
}
- override def fetchScalaInstance(scalaVersion: String, logger: Logger): ScalaInstance = {
+ override def fetchScalaInstance(scalaVersion: String, logger: Logger): XScalaInstance = {
val scalaArtifacts = getScalaArtifacts(scalaVersion, logger)
val scalaCompilerJar = scalaArtifacts.compilerJar
val scalaLibraryJars = scalaArtifacts.libraryJars
@@ -141,7 +128,7 @@ private[sbt] object ZincComponentCompiler {
val properties = ResourceLoader.getSafePropertiesFor("compiler.properties", loader)
val loaderVersion = Option(properties.getProperty("version.number"))
val scalaV = loaderVersion.getOrElse("unknown")
- new inc.ScalaInstance(
+ new ScalaInstance(
scalaV,
loader,
loaderLibraryOnly,
diff --git a/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincLmUtil.scala b/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincLmUtil.scala
index e0d0d4722..3205052ef 100644
--- a/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincLmUtil.scala
+++ b/zinc-lm-integration/src/main/scala/sbt/internal/inc/ZincLmUtil.scala
@@ -8,14 +8,21 @@
package sbt.internal.inc
import java.io.File
-
import sbt.internal.inc.classpath.ClassLoaderCache
-import sbt.librarymanagement.{ DependencyResolution, ModuleID }
+import sbt.internal.util.MessageOnlyException
+import sbt.librarymanagement.{
+ DependencyResolution,
+ ModuleID,
+ ScalaArtifacts,
+ UnresolvedWarningConfiguration,
+ UpdateConfiguration
+}
+import sbt.librarymanagement.syntax._
+import xsbti.ArtifactInfo.SbtOrganization
import xsbti._
-import xsbti.compile._
+import xsbti.compile.{ ClasspathOptions, ScalaInstance => XScalaInstance }
object ZincLmUtil {
- import xsbti.compile.ScalaInstance
/**
* Instantiate a Scala compiler that is instrumented to analyze dependencies.
@@ -23,7 +30,7 @@ object ZincLmUtil {
* compilation.
*/
def scalaCompiler(
- scalaInstance: ScalaInstance,
+ scalaInstance: XScalaInstance,
classpathOptions: ClasspathOptions,
globalLock: GlobalLock,
componentProvider: ComponentProvider,
@@ -49,6 +56,48 @@ object ZincLmUtil {
)
}
- def getDefaultBridgeModule(scalaVersion: String): ModuleID =
- ZincComponentCompiler.getDefaultBridgeModule(scalaVersion)
+ def fetchDefaultBridgeModule(
+ scalaVersion: String,
+ dependencyResolution: DependencyResolution,
+ updateConfiguration: UpdateConfiguration,
+ warningConfig: UnresolvedWarningConfiguration,
+ logger: Logger
+ ): File = {
+ val bridgeModule = getDefaultBridgeModule(scalaVersion)
+ val descriptor = dependencyResolution.wrapDependencyInModule(bridgeModule)
+ dependencyResolution
+ .update(descriptor, updateConfiguration, warningConfig, logger)
+ .toOption
+ .flatMap { report =>
+ val jars = report.select(
+ configurationFilter(Compile.name),
+ moduleFilter(bridgeModule.organization, bridgeModule.name, bridgeModule.revision),
+ artifactFilter(`extension` = "jar", classifier = "")
+ )
+ if (jars.size > 1)
+ sys.error(s"There should be only one jar for $bridgeModule but found $jars")
+ else jars.headOption
+ }
+ .getOrElse(throw new MessageOnlyException(s"Missing $bridgeModule"))
+ }
+
+ def getDefaultBridgeModule(scalaVersion: String): ModuleID = {
+ if (ScalaArtifacts.isScala3(scalaVersion)) {
+ ModuleID(ScalaArtifacts.Organization, "scala3-sbt-bridge", scalaVersion)
+ .withConfigurations(Some(Compile.name))
+ } else {
+ val compilerBridgeId = scalaVersion match {
+ case sc if sc startsWith "2.10." => "compiler-bridge_2.10"
+ case sc if sc startsWith "2.11." => "compiler-bridge_2.11"
+ case sc if sc startsWith "2.12." => "compiler-bridge_2.12"
+ case "2.13.0-M1" => "compiler-bridge_2.12"
+ case _ => "compiler-bridge_2.13"
+ }
+ ModuleID(SbtOrganization, compilerBridgeId, ZincComponentManager.version)
+ .withConfigurations(Some(Compile.name))
+ }
+ }
+
+ def getDefaultBridgeSourceModule(scalaVersion: String): ModuleID =
+ getDefaultBridgeModule(scalaVersion).sources()
}
diff --git a/zinc-lm-integration/src/test/scala/sbt/internal/inc/IvyBridgeProviderSpecification.scala b/zinc-lm-integration/src/test/scala/sbt/internal/inc/IvyBridgeProviderSpecification.scala
index 7d4720420..a4c30bf0c 100644
--- a/zinc-lm-integration/src/test/scala/sbt/internal/inc/IvyBridgeProviderSpecification.scala
+++ b/zinc-lm-integration/src/test/scala/sbt/internal/inc/IvyBridgeProviderSpecification.scala
@@ -62,7 +62,7 @@ abstract class IvyBridgeProviderSpecification
case Some(v: String) => v
case _ => throw new IllegalStateException("No zinc version specified")
}
- val bridge0 = ZincComponentCompiler.getDefaultBridgeModule(scalaVersion)
+ val bridge0 = ZincLmUtil.getDefaultBridgeSourceModule(scalaVersion)
// redefine the compiler bridge version
// using the version of zinc used during testing
// this way when building with zinc as a source dependency