mirror of https://github.com/sbt/sbt.git
[1.x] Add Scala 3.8 REPL support
**Problem** Scala 3.8 REPL won't work since they've split the repl artifact into another JAR. **Solution** This works around it by creating a yet-another sandbox configuration ScalaReplTool (similar to ScalaTool and ScalaDocTool) and a separate scalaInstance for console task, so when Zinc is invoked we'll be able to conjure the right array of JARs.
This commit is contained in:
parent
ed7da85ef0
commit
840b851445
|
|
@ -11,7 +11,7 @@ import scala.util.Try
|
|||
// ThisBuild settings take lower precedence,
|
||||
// but can be shared across the multi projects.
|
||||
ThisBuild / version := {
|
||||
val v = "1.11.8-SNAPSHOT"
|
||||
val v = "1.12.0-SNAPSHOT"
|
||||
nightlyVersion.getOrElse(v)
|
||||
}
|
||||
ThisBuild / version2_13 := "2.0.0-SNAPSHOT"
|
||||
|
|
|
|||
|
|
@ -671,7 +671,12 @@ object Defaults extends BuildCommon {
|
|||
)
|
||||
|
||||
// This is included into JvmPlugin.projectSettings
|
||||
def compileBase = inTask(console)(compilersSetting :: Nil) ++ compileBaseGlobal ++ Seq(
|
||||
def compileBase =
|
||||
inTask(console)(
|
||||
Seq(
|
||||
scalaInstance := Compiler.scalaInstanceTask(Some(Configurations.ScalaReplTool)).value,
|
||||
) ++ compilersSetting
|
||||
) ++ compileBaseGlobal ++ Seq(
|
||||
useScalaReplJLine :== false,
|
||||
scalaInstanceTopLoader := {
|
||||
val topLoader = if (!useScalaReplJLine.value) {
|
||||
|
|
@ -689,7 +694,7 @@ object Defaults extends BuildCommon {
|
|||
}
|
||||
else topLoader
|
||||
},
|
||||
scalaInstance := Compiler.scalaInstanceTask.value,
|
||||
scalaInstance := Compiler.scalaInstanceTask(None).value,
|
||||
crossVersion := (if (crossPaths.value) CrossVersion.binary else CrossVersion.disabled),
|
||||
pluginCrossBuild / sbtBinaryVersion := binarySbtVersion(
|
||||
(pluginCrossBuild / sbtVersion).value
|
||||
|
|
@ -1140,7 +1145,7 @@ object Defaults extends BuildCommon {
|
|||
}
|
||||
|
||||
@deprecated("Use Compiler.scalaInstanceTask", "1.12.0")
|
||||
def scalaInstanceTask: Initialize[Task[ScalaInstance]] = Compiler.scalaInstanceTask
|
||||
def scalaInstanceTask: Initialize[Task[ScalaInstance]] = Compiler.scalaInstanceTask(None)
|
||||
|
||||
// Returns the ScalaInstance only if it was not constructed via `update`
|
||||
// This is necessary to prevent cycles between `update` and `scalaInstance`
|
||||
|
|
@ -1149,8 +1154,9 @@ object Defaults extends BuildCommon {
|
|||
if (scalaHome.value.isDefined) Def.task(Some(scalaInstance.value)) else Def.task(None)
|
||||
}
|
||||
|
||||
@deprecated("Use Compiler.scalaInstanceFromUpdate", "1.12.0")
|
||||
def scalaInstanceFromUpdate: Initialize[Task[ScalaInstance]] =
|
||||
Compiler.scalaInstanceFromUpdate
|
||||
Compiler.scalaInstanceFromUpdate(None)
|
||||
|
||||
def makeScalaInstance(
|
||||
version: String,
|
||||
|
|
@ -2062,6 +2068,7 @@ object Defaults extends BuildCommon {
|
|||
def docTaskSettings(key: TaskKey[File] = doc): Seq[Setting[_]] =
|
||||
inTask(key)(
|
||||
Seq(
|
||||
scalaInstance := Compiler.scalaInstanceTask(Some(Configurations.ScalaDocTool)).value,
|
||||
apiMappings ++= {
|
||||
val dependencyCp = dependencyClasspath.value
|
||||
val log = streams.value.log
|
||||
|
|
@ -2139,7 +2146,7 @@ object Defaults extends BuildCommon {
|
|||
}
|
||||
out
|
||||
}
|
||||
)
|
||||
) ++ compilersSetting
|
||||
)
|
||||
|
||||
def mainBgRunTask = mainBgRunTaskForConfig(Select(Runtime))
|
||||
|
|
@ -3189,7 +3196,7 @@ object Classpaths {
|
|||
ivyConfigurations ++= Configurations.auxiliary,
|
||||
ivyConfigurations ++= {
|
||||
if (managedScalaInstance.value && scalaHome.value.isEmpty)
|
||||
Configurations.ScalaTool :: Configurations.ScalaDocTool :: Nil
|
||||
Configurations.ScalaTool :: Configurations.ScalaDocTool :: Configurations.ScalaReplTool :: Nil
|
||||
else Nil
|
||||
},
|
||||
// Coursier needs these
|
||||
|
|
@ -3385,17 +3392,18 @@ object Classpaths {
|
|||
val pluginAdjust =
|
||||
if (isPlugin) sbtdeps +: base
|
||||
else base
|
||||
val sbtOrg = scalaOrganization.value
|
||||
val scalaOrg = scalaOrganization.value
|
||||
val version = scalaVersion.value
|
||||
val extResolvers = externalResolvers.value
|
||||
val isScala3M123 = ScalaArtifacts.isScala3M123(version)
|
||||
val allToolDeps =
|
||||
if (scalaHome.value.isDefined || scalaModuleInfo.value.isEmpty || !managedScalaInstance.value)
|
||||
Nil
|
||||
else if (!isScala3M123 || extResolvers.contains(Resolver.JCenterRepository)) {
|
||||
ScalaArtifacts.toolDependencies(sbtOrg, version) ++
|
||||
ScalaArtifacts.docToolDependencies(sbtOrg, version)
|
||||
} else ScalaArtifacts.toolDependencies(sbtOrg, version)
|
||||
else if (isScala3M123)
|
||||
ScalaArtifacts.toolDependencies(scalaOrg, version)
|
||||
else
|
||||
ScalaArtifacts.toolDependencies(scalaOrg, version) ++
|
||||
ScalaArtifacts.docToolDependencies(scalaOrg, version) ++
|
||||
ScalaArtifacts.replToolDependencies(scalaOrg, version)
|
||||
allToolDeps ++ pluginAdjust
|
||||
},
|
||||
// in case of meta build, exclude all sbt modules from the dependency graph, so we can use the sbt resolved by the launcher
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2011 - 2018, Lightbend, Inc.
|
||||
* Copyright 2023, Scala center
|
||||
* Copyright 2011 - 2022, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
|
@ -12,16 +13,23 @@ import java.io.File
|
|||
import sbt.internal.inc.ScalaInstance
|
||||
import sbt.librarymanagement.{
|
||||
Artifact,
|
||||
Configuration,
|
||||
Configurations,
|
||||
ConfigurationReport,
|
||||
ScalaArtifacts,
|
||||
SemanticSelector,
|
||||
UpdateReport,
|
||||
VersionNumber
|
||||
}
|
||||
import xsbti.ScalaProvider
|
||||
|
||||
private[sbt] object Compiler {
|
||||
def scalaInstanceTask: Def.Initialize[Task[ScalaInstance]] =
|
||||
|
||||
/**
|
||||
* Returns a ScalaInstance.
|
||||
* extraToolConf is used for Scala 3 since it started splitting up scaladoc and repl.
|
||||
*/
|
||||
def scalaInstanceTask(extraToolConf: Option[Configuration]): Def.Initialize[Task[ScalaInstance]] =
|
||||
Def.taskDyn {
|
||||
val sh = Keys.scalaHome.value
|
||||
val app = Keys.appConfiguration.value
|
||||
|
|
@ -35,7 +43,7 @@ private[sbt] object Compiler {
|
|||
val scalaProvider = app.provider.scalaProvider
|
||||
if (!managed) emptyScalaInstance
|
||||
else if (sv == scalaProvider.version) optimizedScalaInstance(sv, scalaProvider)
|
||||
else scalaInstanceFromUpdate
|
||||
else scalaInstanceFromUpdate(extraToolConf)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -95,30 +103,19 @@ private[sbt] object Compiler {
|
|||
)
|
||||
}
|
||||
|
||||
def scalaInstanceFromUpdate: Def.Initialize[Task[ScalaInstance]] = Def.task {
|
||||
/**
|
||||
* Returns a ScalaInstance.
|
||||
* extraToolConf is used for Scala 3 since it started splitting up scaladoc and repl.
|
||||
*/
|
||||
def scalaInstanceFromUpdate(
|
||||
extraToolConf: Option[Configuration]
|
||||
): Def.Initialize[Task[ScalaInstance]] =
|
||||
Def.task {
|
||||
val sv = Keys.scalaVersion.value
|
||||
val fullReport = Keys.update.value
|
||||
val s = Keys.streams.value
|
||||
|
||||
// For Scala 3, update scala-library.jar in `scala-tool` and `scala-doc-tool` in case a newer version
|
||||
// is present in the `compile` configuration. This is needed once forwards binary compatibility is dropped
|
||||
// to avoid NoSuchMethod exceptions when expanding macros.
|
||||
def updateLibraryToCompileConfiguration(report: ConfigurationReport) =
|
||||
if (!ScalaArtifacts.isScala3(sv)) report
|
||||
else
|
||||
(for {
|
||||
compileConf <- fullReport.configuration(Configurations.Compile)
|
||||
compileLibMod <- compileConf.modules.find(_.module.name == ScalaArtifacts.LibraryID)
|
||||
reportLibMod <- report.modules.find(_.module.name == ScalaArtifacts.LibraryID)
|
||||
if VersionNumber(reportLibMod.module.revision)
|
||||
.matchesSemVer(SemanticSelector(s"<${compileLibMod.module.revision}"))
|
||||
} yield {
|
||||
val newMods = report.modules
|
||||
.filterNot(_.module.name == ScalaArtifacts.LibraryID) :+ compileLibMod
|
||||
report.withModules(newMods)
|
||||
}).getOrElse(report)
|
||||
|
||||
val toolReport = updateLibraryToCompileConfiguration(
|
||||
val toolReport = updateLibraryToCompileConfiguration(sv, fullReport)(
|
||||
fullReport
|
||||
.configuration(Configurations.ScalaTool)
|
||||
.getOrElse(sys.error(noToolConfiguration(Keys.managedScalaInstance.value)))
|
||||
|
|
@ -170,46 +167,70 @@ private[sbt] object Compiler {
|
|||
}
|
||||
|
||||
val allCompilerJars = toolReport.modules.flatMap(_.artifacts.map(_._2))
|
||||
val allDocJars =
|
||||
val extraToolJars =
|
||||
extraToolConf match {
|
||||
case Some(extra) =>
|
||||
fullReport
|
||||
.configuration(Configurations.ScalaDocTool)
|
||||
.map(updateLibraryToCompileConfiguration)
|
||||
.configuration(extra)
|
||||
.map(updateLibraryToCompileConfiguration(sv, fullReport))
|
||||
.toSeq
|
||||
.flatMap(_.modules)
|
||||
.flatMap(_.artifacts.map(_._2))
|
||||
case None => Nil
|
||||
}
|
||||
val libraryJars = ScalaArtifacts.libraryIds(sv).map(file)
|
||||
|
||||
makeScalaInstance(
|
||||
sv,
|
||||
libraryJars,
|
||||
allCompilerJars,
|
||||
allDocJars,
|
||||
extraToolJars,
|
||||
Keys.state.value,
|
||||
Keys.scalaInstanceTopLoader.value,
|
||||
)
|
||||
}
|
||||
|
||||
// For Scala 3, update scala-library.jar in `scala-tool` and `scala-doc-tool` in case a newer version
|
||||
// is present in the `compile` configuration. This is needed once forwards binary compatibility is dropped
|
||||
// to avoid NoSuchMethod exceptions when expanding macros.
|
||||
private def updateLibraryToCompileConfiguration(sv: String, fullReport: UpdateReport)(
|
||||
report: ConfigurationReport
|
||||
) =
|
||||
if (!ScalaArtifacts.isScala3(sv)) report
|
||||
else
|
||||
(for {
|
||||
compileConf <- fullReport.configuration(Configurations.Compile)
|
||||
compileLibMod <- compileConf.modules.find(_.module.name == ScalaArtifacts.LibraryID)
|
||||
reportLibMod <- report.modules.find(_.module.name == ScalaArtifacts.LibraryID)
|
||||
if VersionNumber(reportLibMod.module.revision)
|
||||
.matchesSemVer(SemanticSelector(s"<${compileLibMod.module.revision}"))
|
||||
} yield {
|
||||
val newMods = report.modules
|
||||
.filterNot(_.module.name == ScalaArtifacts.LibraryID) :+ compileLibMod
|
||||
report.withModules(newMods)
|
||||
}).getOrElse(report)
|
||||
|
||||
def makeScalaInstance(
|
||||
version: String,
|
||||
libraryJars: Array[File],
|
||||
allCompilerJars: Seq[File],
|
||||
allDocJars: Seq[File],
|
||||
extraToolJars: Seq[File],
|
||||
state: State,
|
||||
topLoader: ClassLoader,
|
||||
): ScalaInstance = {
|
||||
val classLoaderCache = state.extendedClassLoaderCache
|
||||
val compilerJars = allCompilerJars.filterNot(libraryJars.contains).distinct.toArray
|
||||
val docJars = allDocJars
|
||||
val toolJars = extraToolJars
|
||||
.filterNot(jar => libraryJars.contains(jar) || compilerJars.contains(jar))
|
||||
.distinct
|
||||
.toArray
|
||||
val allJars = libraryJars ++ compilerJars ++ docJars
|
||||
val allJars = libraryJars ++ compilerJars ++ toolJars
|
||||
|
||||
val libraryLoader = classLoaderCache(libraryJars.toList, topLoader)
|
||||
val compilerLoader = classLoaderCache(compilerJars.toList, libraryLoader)
|
||||
val fullLoader =
|
||||
if (docJars.isEmpty) compilerLoader
|
||||
else classLoaderCache(docJars.distinct.toList, compilerLoader)
|
||||
if (toolJars.isEmpty) compilerLoader
|
||||
else classLoaderCache(toolJars.distinct.toList, compilerLoader)
|
||||
new ScalaInstance(
|
||||
version = version,
|
||||
loader = fullLoader,
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ object Dependencies {
|
|||
// sbt modules
|
||||
private val ioVersion = nightlyVersion.getOrElse("1.10.5")
|
||||
private val lmVersion =
|
||||
sys.props.get("sbt.build.lm.version").orElse(nightlyVersion).getOrElse("1.11.6")
|
||||
val zincVersion = nightlyVersion.getOrElse("1.11.0")
|
||||
sys.props.get("sbt.build.lm.version").orElse(nightlyVersion).getOrElse("1.12.0-M1")
|
||||
val zincVersion = nightlyVersion.getOrElse("1.12.0-M1")
|
||||
|
||||
private val sbtIO = "org.scala-sbt" %% "io" % ioVersion
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue