mirror of https://github.com/sbt/sbt.git
Merge branch '1.10.x' into wip/merge-1.10.x
This commit is contained in:
commit
cb63de6574
|
|
@ -32,10 +32,10 @@ jobs:
|
|||
java: 21
|
||||
distribution: temurin
|
||||
jobtype: 5
|
||||
- os: ubuntu-latest
|
||||
java: 8
|
||||
distribution: zulu
|
||||
jobtype: 6
|
||||
# - os: ubuntu-latest
|
||||
# java: 8
|
||||
# distribution: zulu
|
||||
# jobtype: 6
|
||||
- os: ubuntu-latest
|
||||
java: 8
|
||||
distribution: zulu
|
||||
|
|
|
|||
|
|
@ -4,21 +4,7 @@ jobs:
|
|||
check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check CLA
|
||||
env:
|
||||
AUTHOR: ${{ github.event.pull_request.user.login }}
|
||||
run: |
|
||||
echo "Pull request submitted by $AUTHOR";
|
||||
signed=$(curl -s "https://contribute.akka.io/contribute/cla/scala/check/$AUTHOR" | jq -r ".signed");
|
||||
if [ "$signed" = "true" ] ; then
|
||||
echo "CLA check for $AUTHOR successful";
|
||||
else
|
||||
echo "CLA check for $AUTHOR failed";
|
||||
echo "Please sign the Scala CLA to contribute to the Scala compiler.";
|
||||
echo "Go to https://contribute.akka.io/contribute/cla/scala and then";
|
||||
echo "comment on the pull request to ask for a new check.";
|
||||
echo "";
|
||||
echo "Check if CLA is signed: https://contribute.akka.io/contribute/cla/scala/check/$AUTHOR";
|
||||
exit 1;
|
||||
fi;
|
||||
- name: Check CLA
|
||||
uses: scala/cla-checker@v1
|
||||
with:
|
||||
author: ${{ github.event.pull_request.user.login }}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import java.nio.file.{ Path, Paths }
|
|||
import java.util.Locale
|
||||
|
||||
import scala.collection.concurrent.TrieMap
|
||||
import scala.reflect.Selectable.reflectiveSelectable
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
object Util:
|
||||
def makeList[T](size: Int, value: T): List[T] = List.fill(size)(value)
|
||||
|
|
@ -86,4 +88,46 @@ object Util:
|
|||
case None =>
|
||||
if sys.props("java.home").endsWith("jre") then Paths.get(sys.props("java.home")).getParent()
|
||||
else Paths.get(sys.props("java.home"))
|
||||
|
||||
/**
|
||||
* Given a list of event handlers expressed partial functions, combine them
|
||||
* together using orElse from the left.
|
||||
*/
|
||||
def reduceIntents[A1, A2](intents: PartialFunction[A1, A2]*): PartialFunction[A1, A2] =
|
||||
intents.toList.reduceLeft(_ orElse _)
|
||||
|
||||
lazy val majorJavaVersion: Int =
|
||||
try {
|
||||
val javaVersion = sys.props.get("java.version").getOrElse("1.0")
|
||||
if (javaVersion.startsWith("1.")) {
|
||||
javaVersion.split("\\.")(1).toInt
|
||||
} else {
|
||||
javaVersion.split("\\.")(0).toInt
|
||||
}
|
||||
} catch {
|
||||
case NonFatal(_) => 0
|
||||
}
|
||||
|
||||
private type GetId = {
|
||||
def getId: Long
|
||||
}
|
||||
private type ThreadId = {
|
||||
def threadId: Long
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current thread id.
|
||||
* Thread.threadId was added in JDK 19, and deprecated Thread#getId
|
||||
* https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Thread.html#threadId()
|
||||
*/
|
||||
def threadId: Long =
|
||||
if (majorJavaVersion < 19) {
|
||||
(Thread.currentThread(): AnyRef) match {
|
||||
case g: GetId @unchecked => g.getId
|
||||
}
|
||||
} else {
|
||||
(Thread.currentThread(): AnyRef) match {
|
||||
case g: ThreadId @unchecked => g.threadId
|
||||
}
|
||||
}
|
||||
end Util
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ abstract class SourcePositionImpl {
|
|||
}
|
||||
|
||||
final class SourcePositionMacro(val c: blackbox.Context) {
|
||||
import c.universe.{ NoPosition => _, _ }
|
||||
import c.universe.{ NoPosition as _, * }
|
||||
|
||||
def fromEnclosingImpl(): Expr[SourcePosition] = {
|
||||
val pos = c.enclosingPosition
|
||||
|
|
|
|||
|
|
@ -56,6 +56,10 @@ class FileCommands(baseDirectory: File) extends BasicStatementHandler {
|
|||
def fromStrings(paths: List[String]) = paths.map(fromString)
|
||||
def fromString(path: String) = new File(baseDirectory, path)
|
||||
def filterFromStrings(exprs: List[String]): List[PathFilter] =
|
||||
def globs(exprs: List[String]): List[PathFilter] =
|
||||
exprs.map: g =>
|
||||
if g.startsWith("/") then (Glob(g): PathFilter)
|
||||
else (Glob(baseDirectory, g): PathFilter)
|
||||
def orGlobs =
|
||||
val exprs1 = exprs
|
||||
.mkString("")
|
||||
|
|
@ -63,16 +67,16 @@ class FileCommands(baseDirectory: File) extends BasicStatementHandler {
|
|||
.filter(_ != OR)
|
||||
.toList
|
||||
.map(_.trim)
|
||||
val combined = exprs1.map(Glob(baseDirectory, _)) match
|
||||
val combined = globs(exprs1) match
|
||||
case Nil => sys.error("unexpected Nil")
|
||||
case g :: Nil => (g: PathFilter)
|
||||
case g :: Nil => g
|
||||
case g :: gs =>
|
||||
gs.foldLeft(g: PathFilter) { case (acc, g) =>
|
||||
acc || (g: PathFilter)
|
||||
gs.foldLeft(g) { case (acc, g) =>
|
||||
acc || g
|
||||
}
|
||||
List(combined)
|
||||
if exprs.contains("||") then orGlobs
|
||||
else exprs.map(Glob(baseDirectory, _): PathFilter)
|
||||
else globs(exprs)
|
||||
|
||||
def touch(paths: List[String]): Unit = IO.touch(fromStrings(paths))
|
||||
def delete(paths: List[String]): Unit =
|
||||
|
|
@ -130,10 +134,10 @@ class FileCommands(baseDirectory: File) extends BasicStatementHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private type NamedCommand = (String, List[String] => Unit)
|
||||
type NamedCommand = (String, List[String] => Unit)
|
||||
|
||||
// these are for readability of the command list
|
||||
extension (commandName: String) {
|
||||
extension (commandName: String)
|
||||
def nonEmpty(action: List[String] => Unit): NamedCommand =
|
||||
commandName -> { paths =>
|
||||
if (paths.isEmpty)
|
||||
|
|
@ -177,5 +181,4 @@ class FileCommands(baseDirectory: File) extends BasicStatementHandler {
|
|||
"Wrong number of arguments to " + commandName + " command. " +
|
||||
requiredArgs + " required, found: '" + spaced(args) + "'."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import minitest._
|
|||
import scala.sys.process._
|
||||
import java.io.File
|
||||
import java.util.Locale
|
||||
import sbt.io.IO
|
||||
|
||||
object SbtRunnerTest extends SimpleTestSuite with PowerAssertions {
|
||||
// 1.3.0, 1.3.0-M4
|
||||
|
|
@ -20,6 +21,10 @@ object SbtRunnerTest extends SimpleTestSuite with PowerAssertions {
|
|||
sbt.internal.Process(Seq(sbtScript.getAbsolutePath) ++ args, new File("citest"),
|
||||
"JAVA_OPTS" -> javaOpts,
|
||||
"SBT_OPTS" -> sbtOpts)
|
||||
def sbtProcessInDir(dir: File)(args: String*) =
|
||||
sbt.internal.Process(Seq(sbtScript.getAbsolutePath) ++ args, dir,
|
||||
"JAVA_OPTS" -> "",
|
||||
"SBT_OPTS" -> "")
|
||||
|
||||
test("sbt runs") {
|
||||
assert(sbtScript.exists)
|
||||
|
|
@ -68,6 +73,27 @@ object SbtRunnerTest extends SimpleTestSuite with PowerAssertions {
|
|||
}
|
||||
}
|
||||
|
||||
test("sbt in empty directory") {
|
||||
IO.withTemporaryDirectory { tmp =>
|
||||
val out = sbtProcessInDir(tmp)("about").!
|
||||
assert(out == 1)
|
||||
}
|
||||
IO.withTemporaryDirectory { tmp =>
|
||||
val out = sbtProcessInDir(tmp)("about", "--allow-empty").!
|
||||
assert(out == 0)
|
||||
}
|
||||
()
|
||||
}
|
||||
|
||||
test("sbt --script-version in empty directory") {
|
||||
IO.withTemporaryDirectory { tmp =>
|
||||
val out = sbtProcessInDir(tmp)("--script-version").!!.trim
|
||||
val expectedVersion = "^"+versionRegEx+"$"
|
||||
assert(out.matches(expectedVersion))
|
||||
}
|
||||
()
|
||||
}
|
||||
|
||||
/*
|
||||
test("sbt --client") {
|
||||
val out = sbtProcess("--client", "--no-colors", "compile").!!.linesIterator.toList
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ set sbt_args_timings=
|
|||
set sbt_args_traces=
|
||||
set sbt_args_sbt_boot=
|
||||
set sbt_args_sbt_cache=
|
||||
set sbt_args_sbt_create=
|
||||
set sbt_args_allow_empty=
|
||||
set sbt_args_sbt_dir=
|
||||
set sbt_args_sbt_version=
|
||||
set sbt_args_mem=
|
||||
|
|
@ -72,11 +72,13 @@ rem TODO: remove/deprecate sbtconfig.txt and parse the sbtopts files
|
|||
rem FIRST we load the config file of extra options.
|
||||
set SBT_CONFIG=!SBT_HOME!\conf\sbtconfig.txt
|
||||
set SBT_CFG_OPTS=
|
||||
for /F "tokens=* eol=# usebackq delims=" %%i in ("!SBT_CONFIG!") do (
|
||||
set DO_NOT_REUSE_ME=%%i
|
||||
rem ZOMG (Part #2) WE use !! here to delay the expansion of
|
||||
rem SBT_CFG_OPTS, otherwise it remains "" for this loop.
|
||||
set SBT_CFG_OPTS=!SBT_CFG_OPTS! !DO_NOT_REUSE_ME!
|
||||
if exist "!SBT_CONFIG!" (
|
||||
for /F "tokens=* eol=# usebackq delims=" %%i in ("!SBT_CONFIG!") do (
|
||||
set DO_NOT_REUSE_ME=%%i
|
||||
rem ZOMG (Part #2) WE use !! here to delay the expansion of
|
||||
rem SBT_CFG_OPTS, otherwise it remains "" for this loop.
|
||||
set SBT_CFG_OPTS=!SBT_CFG_OPTS! !DO_NOT_REUSE_ME!
|
||||
)
|
||||
)
|
||||
|
||||
rem poor man's jenv (which is not available on Windows)
|
||||
|
|
@ -235,12 +237,14 @@ if defined _traces_arg (
|
|||
goto args_loop
|
||||
)
|
||||
|
||||
if "%~0" == "-sbt-create" set _sbt_create_arg=true
|
||||
if "%~0" == "--sbt-create" set _sbt_create_arg=true
|
||||
if "%~0" == "-sbt-create" set _allow_empty_arg=true
|
||||
if "%~0" == "--sbt-create" set _allow_empty_arg=true
|
||||
if "%~0" == "-allow-empty" set _allow_empty_arg=true
|
||||
if "%~0" == "--allow-empty" set _allow_empty_arg=true
|
||||
|
||||
if defined _sbt_create_arg (
|
||||
set _sbt_create_arg=
|
||||
set sbt_args_sbt_create=1
|
||||
if defined _allow_empty_arg (
|
||||
set _allow_empty_arg=
|
||||
set sbt_args_allow_empty=1
|
||||
goto args_loop
|
||||
)
|
||||
|
||||
|
|
@ -526,25 +530,12 @@ goto args_loop
|
|||
rem Confirm a user's intent if the current directory does not look like an sbt
|
||||
rem top-level directory and the "new" command was not given.
|
||||
|
||||
if not defined sbt_args_sbt_create if not defined sbt_args_print_version if not defined sbt_args_print_sbt_version if not defined sbt_args_print_sbt_script_version if not defined shutdownall if not exist build.sbt (
|
||||
if not defined sbt_args_allow_empty if not defined sbt_args_print_version if not defined sbt_args_print_sbt_version if not defined sbt_args_print_sbt_script_version if not defined shutdownall if not exist build.sbt (
|
||||
if not exist project\ (
|
||||
if not defined sbt_new (
|
||||
echo [warn] Neither build.sbt nor a 'project' directory in the current directory: "%CD%"
|
||||
setlocal
|
||||
:confirm
|
||||
echo c^) continue
|
||||
echo q^) quit
|
||||
|
||||
set /P reply=^?
|
||||
if /I "!reply!" == "c" (
|
||||
goto confirm_end
|
||||
) else if /I "!reply!" == "q" (
|
||||
exit /B 1
|
||||
)
|
||||
|
||||
goto confirm
|
||||
:confirm_end
|
||||
endlocal
|
||||
echo [error] Neither build.sbt nor a 'project' directory in the current directory: "%CD%"
|
||||
echo [error] run 'sbt new', touch build.sbt, or run 'sbt --allow-empty'.
|
||||
goto error
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
# Starts sbt even if the current directory contains no sbt project.
|
||||
#
|
||||
-sbt-create
|
||||
#--allow-empty
|
||||
|
||||
# Path to global settings/plugins directory (default: ~/.sbt)
|
||||
#
|
||||
|
|
@ -31,11 +31,11 @@
|
|||
#
|
||||
#-no-share
|
||||
|
||||
# Put SBT in offline mode.
|
||||
# Put sbt in offline mode.
|
||||
#
|
||||
#-offline
|
||||
|
||||
# Sets the SBT version to use.
|
||||
# Sets the sbt version to use.
|
||||
#-sbt-version 0.11.3
|
||||
|
||||
# Scala version (default: latest release)
|
||||
|
|
|
|||
|
|
@ -530,60 +530,76 @@ class NetworkClient(
|
|||
.getOrElse(1)
|
||||
case _ => 1
|
||||
}
|
||||
private def completeExec(execId: String, exitCode: => Int): Unit =
|
||||
|
||||
private val onAttachResponse: PartialFunction[JsonRpcResponseMessage, Unit] = {
|
||||
case msg if attachUUID.get == msg.id =>
|
||||
attachUUID.set(null)
|
||||
attached.set(true)
|
||||
Option(inputThread.get).foreach(_.drain())
|
||||
()
|
||||
}
|
||||
def completeExec(execId: String, exitCode: Int) = {
|
||||
pendingResults.remove(execId) match {
|
||||
case null =>
|
||||
case null => ()
|
||||
case (q, startTime, name) =>
|
||||
val now = System.currentTimeMillis
|
||||
val message = NetworkClient.timing(startTime, now)
|
||||
val ec = exitCode
|
||||
if (batchMode.get || !attached.get) {
|
||||
if (ec == 0) console.success(message)
|
||||
if (exitCode == 0) console.success(message)
|
||||
else console.appendLog(Level.Error, message)
|
||||
}
|
||||
Util.ignoreResult(q.offer(ec))
|
||||
}
|
||||
def onResponse(msg: JsonRpcResponseMessage): Unit = {
|
||||
completeExec(msg.id, getExitCode(msg.result))
|
||||
pendingCancellations.remove(msg.id) match {
|
||||
case null =>
|
||||
case q => q.offer(msg.toString.contains("Task cancelled"))
|
||||
}
|
||||
msg.id match {
|
||||
case execId =>
|
||||
if (attachUUID.get == msg.id) {
|
||||
attachUUID.set(null)
|
||||
attached.set(true)
|
||||
Option(inputThread.get).foreach(_.drain())
|
||||
}
|
||||
pendingCompletions.remove(execId) match {
|
||||
case null =>
|
||||
case completions =>
|
||||
completions(msg.result match {
|
||||
case Some(o: JObject) =>
|
||||
o.value
|
||||
.foldLeft(CompletionResponse(Vector.empty[String])) { case (resp, i) =>
|
||||
if (i.field == "items")
|
||||
resp.withItems(
|
||||
Converter
|
||||
.fromJson[Vector[String]](i.value)
|
||||
.getOrElse(Vector.empty[String])
|
||||
)
|
||||
else if (i.field == "cachedTestNames")
|
||||
resp.withCachedTestNames(
|
||||
Converter.fromJson[Boolean](i.value).getOrElse(true)
|
||||
)
|
||||
else if (i.field == "cachedMainClassNames")
|
||||
resp.withCachedMainClassNames(
|
||||
Converter.fromJson[Boolean](i.value).getOrElse(true)
|
||||
)
|
||||
else resp
|
||||
}
|
||||
case _ => CompletionResponse(Vector.empty[String])
|
||||
})
|
||||
}
|
||||
Util.ignoreResult(q.offer(exitCode))
|
||||
}
|
||||
}
|
||||
private val onExecResponse: PartialFunction[JsonRpcResponseMessage, Unit] = {
|
||||
case msg if pendingResults.containsKey(msg.id) =>
|
||||
completeExec(msg.id, getExitCode(msg.result))
|
||||
}
|
||||
private val onCancellationResponse: PartialFunction[JsonRpcResponseMessage, Unit] = {
|
||||
case msg if pendingCancellations.containsKey(msg.id) =>
|
||||
pendingCancellations.remove(msg.id) match {
|
||||
case null => ()
|
||||
case q => Util.ignoreResult(q.offer(msg.toString.contains("Task cancelled")))
|
||||
}
|
||||
}
|
||||
private val onCompletionResponse: PartialFunction[JsonRpcResponseMessage, Unit] = {
|
||||
case msg if pendingCompletions.containsKey(msg.id) =>
|
||||
pendingCompletions.remove(msg.id) match {
|
||||
case null => ()
|
||||
case completions =>
|
||||
completions(msg.result match {
|
||||
case Some(o: JObject) =>
|
||||
o.value
|
||||
.foldLeft(CompletionResponse(Vector.empty[String])) { case (resp, i) =>
|
||||
if (i.field == "items")
|
||||
resp.withItems(
|
||||
Converter
|
||||
.fromJson[Vector[String]](i.value)
|
||||
.getOrElse(Vector.empty[String])
|
||||
)
|
||||
else if (i.field == "cachedTestNames")
|
||||
resp.withCachedTestNames(
|
||||
Converter.fromJson[Boolean](i.value).getOrElse(true)
|
||||
)
|
||||
else if (i.field == "cachedMainClassNames")
|
||||
resp.withCachedMainClassNames(
|
||||
Converter.fromJson[Boolean](i.value).getOrElse(true)
|
||||
)
|
||||
else resp
|
||||
}
|
||||
case _ => CompletionResponse(Vector.empty[String])
|
||||
})
|
||||
}
|
||||
}
|
||||
// cache the composed plan
|
||||
private val responsePlan = Util.reduceIntents[JsonRpcResponseMessage, Unit](
|
||||
onExecResponse,
|
||||
onCancellationResponse,
|
||||
onAttachResponse,
|
||||
onCompletionResponse,
|
||||
{ case _ => () },
|
||||
)
|
||||
def onResponse(msg: JsonRpcResponseMessage): Unit = responsePlan(msg)
|
||||
|
||||
def onNotification(msg: JsonRpcNotificationMessage): Unit = {
|
||||
def splitToMessage: Vector[(Level.Value, String)] =
|
||||
|
|
|
|||
|
|
@ -191,6 +191,7 @@ object Defaults extends BuildCommon {
|
|||
apiMappings := Map.empty,
|
||||
autoScalaLibrary :== true,
|
||||
managedScalaInstance :== true,
|
||||
allowUnsafeScalaLibUpgrade :== false,
|
||||
classpathEntryDefinesClass := { (file: File) =>
|
||||
sys.error("use classpathEntryDefinesClassVF instead")
|
||||
},
|
||||
|
|
@ -296,6 +297,7 @@ object Defaults extends BuildCommon {
|
|||
csrLogger := LMCoursier.coursierLoggerTask.value,
|
||||
csrMavenProfiles :== Set.empty,
|
||||
csrReconciliations :== LMCoursier.relaxedForAllModules,
|
||||
csrMavenDependencyOverride :== false,
|
||||
csrSameVersions := Seq(
|
||||
ScalaArtifacts.Artifacts.map(a => InclExclRule(scalaOrganization.value, a)).toSet
|
||||
),
|
||||
|
|
|
|||
|
|
@ -499,6 +499,7 @@ object Keys {
|
|||
val csrPublications = taskKey[Seq[(lmcoursier.definitions.Configuration, lmcoursier.definitions.Publication)]]("")
|
||||
val csrReconciliations = settingKey[Seq[(ModuleMatchers, Reconciliation)]]("Strategy to reconcile version conflicts.")
|
||||
val csrSameVersions = settingKey[Seq[Set[InclExclRule]]]("Modules to keep at the same version.")
|
||||
val csrMavenDependencyOverride = settingKey[Boolean]("Enables Maven dependency override (bill of materials) support")
|
||||
|
||||
val internalConfigurationMap = settingKey[Configuration => Configuration]("Maps configurations to the actual configuration used to define the classpath.").withRank(CSetting)
|
||||
val classpathConfiguration = taskKey[Configuration]("The configuration used to define the classpath.").withRank(CTask)
|
||||
|
|
@ -615,6 +616,7 @@ object Keys {
|
|||
val conflictManager = settingKey[ConflictManager]("Selects the conflict manager to use for dependency management.").withRank(CSetting)
|
||||
val autoScalaLibrary = settingKey[Boolean]("Adds a dependency on scala-library if true.").withRank(ASetting)
|
||||
val managedScalaInstance = settingKey[Boolean]("Automatically obtains Scala tools as managed dependencies if true.").withRank(BSetting)
|
||||
val allowUnsafeScalaLibUpgrade = settingKey[Boolean]("Allow the Scala library on the compilation classpath to be newer than the scalaVersion (see Scala SIP-51).").withRank(CSetting)
|
||||
val sbtResolver = settingKey[Resolver]("Provides a resolver for obtaining sbt as a dependency.").withRank(BMinusSetting)
|
||||
val sbtResolvers = settingKey[Seq[Resolver]]("The external resolvers for sbt and plugin dependencies.").withRank(BMinusSetting)
|
||||
val sbtDependency = settingKey[ModuleID]("Provides a definition for declaring the current version of sbt.").withRank(BMinusSetting)
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ object LMCoursier {
|
|||
depsOverrides: Seq[ModuleID],
|
||||
updateConfig: Option[UpdateConfiguration],
|
||||
sameVersions: Seq[Set[InclExclRule]],
|
||||
enableDependencyOverrides: Option[Boolean],
|
||||
log: Logger
|
||||
): CoursierConfiguration = {
|
||||
val coursierExcludeDeps = Inputs
|
||||
|
|
@ -146,6 +147,7 @@ object LMCoursier {
|
|||
.withForceVersions(userForceVersions.toVector)
|
||||
.withMissingOk(missingOk)
|
||||
.withSameVersions(sameVersions)
|
||||
// .withEnableDependencyOverrides(enableDependencyOverrides)
|
||||
}
|
||||
|
||||
def coursierConfigurationTask: Def.Initialize[Task[CoursierConfiguration]] = Def.task {
|
||||
|
|
@ -172,6 +174,7 @@ object LMCoursier {
|
|||
dependencyOverrides.value,
|
||||
Some(updateConfiguration.value),
|
||||
csrSameVersions.value,
|
||||
Some(csrMavenDependencyOverride.value),
|
||||
streams.value.log
|
||||
)
|
||||
}
|
||||
|
|
@ -207,6 +210,7 @@ object LMCoursier {
|
|||
dependencyOverrides.value,
|
||||
Some(updateConfiguration.value),
|
||||
csrSameVersions.value,
|
||||
Some(csrMavenDependencyOverride.value),
|
||||
streams.value.log
|
||||
)
|
||||
}
|
||||
|
|
@ -235,6 +239,7 @@ object LMCoursier {
|
|||
dependencyOverrides.value,
|
||||
Some(updateConfiguration.value),
|
||||
csrSameVersions.value,
|
||||
Some(csrMavenDependencyOverride.value),
|
||||
streams.value.log
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
package sbt
|
||||
package internal
|
||||
|
||||
import sbt.internal.util.Util
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
import scala.jdk.CollectionConverters.*
|
||||
|
|
@ -126,6 +127,7 @@ object AbstractTaskExecuteProgress {
|
|||
private[sbt] class Timer() {
|
||||
val startNanos: Long = System.nanoTime()
|
||||
val threadName: String = Thread.currentThread().getName
|
||||
val threadId: Long = Util.threadId
|
||||
var endNanos: Long = 0L
|
||||
def stop(): Unit = {
|
||||
endNanos = System.nanoTime()
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ object Compiler:
|
|||
def scalaInstanceFromUpdate: 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
|
||||
|
|
@ -95,28 +96,39 @@ object Compiler:
|
|||
.getOrElse(sys.error(noToolConfiguration(Keys.managedScalaInstance.value)))
|
||||
)
|
||||
|
||||
if (Classpaths.isScala213(sv)) {
|
||||
for {
|
||||
compileReport <- fullReport.configuration(Configurations.Compile)
|
||||
libName <- ScalaArtifacts.Artifacts
|
||||
} {
|
||||
for (lib <- compileReport.modules.find(_.module.name == libName)) {
|
||||
val libVer = lib.module.revision
|
||||
val n = Keys.name.value
|
||||
if (VersionNumber(sv).matchesSemVer(SemanticSelector(s"<$libVer")))
|
||||
sys.error(
|
||||
s"""expected `$n/scalaVersion` to be "$libVer" or later,
|
||||
|but found "$sv"; upgrade scalaVersion to fix the build.
|
||||
|
|
||||
|to support backwards-only binary compatibility (SIP-51),
|
||||
|the Scala 2.13 compiler cannot be older than $libName on the
|
||||
|dependency classpath.
|
||||
|see `$n/evicted` to know why $libName $libVer is getting pulled in.
|
||||
|""".stripMargin
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
if Classpaths.isScala213(sv) then
|
||||
val scalaDeps = for
|
||||
compileReport <- fullReport.configuration(Configurations.Compile).iterator
|
||||
libName <- ScalaArtifacts.Artifacts.iterator
|
||||
lib <- compileReport.modules.find(_.module.name == libName)
|
||||
yield lib
|
||||
for lib <- scalaDeps.take(1) do
|
||||
val libVer = lib.module.revision
|
||||
val libName = lib.module.name
|
||||
val n = Keys.name.value
|
||||
if VersionNumber(sv).matchesSemVer(SemanticSelector(s"<$libVer")) then
|
||||
val err = !Keys.allowUnsafeScalaLibUpgrade.value
|
||||
val fix =
|
||||
if err then
|
||||
"""Upgrade the `scalaVersion` to fix the build. If upgrading the Scala compiler version is
|
||||
|not possible (for example due to a regression in the compiler or a missing dependency),
|
||||
|this error can be demoted by setting `allowUnsafeScalaLibUpgrade := true`.""".stripMargin
|
||||
else s"""Note that the dependency classpath and the runtime classpath of your project
|
||||
|contain the newer $libName $libVer, even if the scalaVersion is $sv.
|
||||
|Compilation (macro expansion) or using the Scala REPL in sbt may fail with a LinkageError.""".stripMargin
|
||||
val msg =
|
||||
s"""Expected `$n/scalaVersion` to be $libVer or later, but found $sv.
|
||||
|To support backwards-only binary compatibility (SIP-51), the Scala 2.13 compiler
|
||||
|should not be older than $libName on the dependency classpath.
|
||||
|
|
||||
|$fix
|
||||
|
|
||||
|See `$n/evicted` to know why $libName $libVer is getting pulled in.
|
||||
|""".stripMargin
|
||||
if err then sys.error(msg)
|
||||
else s.log.warn(msg)
|
||||
else ()
|
||||
else ()
|
||||
def file(id: String): File = {
|
||||
val files = for {
|
||||
m <- toolReport.modules if m.module.name.startsWith(id)
|
||||
|
|
|
|||
|
|
@ -409,12 +409,18 @@ private[sbt] object CrossJava {
|
|||
|
||||
class MacOsDiscoverConfig extends JavaDiscoverConf {
|
||||
val base: File = file("/Library") / "Java" / "JavaVirtualMachines"
|
||||
// User-specific JDKs are installed, for example, by IntelliJ IDEA
|
||||
private val baseInUserHome: File = Path.userHome / "Library" / "Java" / "JavaVirtualMachines"
|
||||
|
||||
def javaHomes: Vector[(String, File)] =
|
||||
wrapNull(base.list())
|
||||
.collect { case dir @ JavaHomeDir(version) =>
|
||||
version -> (base / dir / "Contents" / "Home")
|
||||
}
|
||||
findAllHomes(base) ++
|
||||
findAllHomes(baseInUserHome)
|
||||
|
||||
private def findAllHomes(root: File): Vector[(String, File)] = {
|
||||
wrapNull(root.list()).collect { case dir @ JavaHomeDir(version) =>
|
||||
version -> (root / dir / "Contents" / "Home")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class JabbaDiscoverConfig extends JavaDiscoverConf {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ object LintUnused {
|
|||
configuration,
|
||||
crossScalaVersions,
|
||||
crossSbtVersions,
|
||||
allowUnsafeScalaLibUpgrade,
|
||||
evictionWarningOptions,
|
||||
initialize,
|
||||
lintUnusedKeysOnLoad,
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ private[sbt] final class TaskTraceEvent extends AbstractTaskExecuteProgress with
|
|||
def durationEvent(name: String, cat: String, t: Timer): String = {
|
||||
val sb = new java.lang.StringBuilder(name.length + 2)
|
||||
CompactPrinter.print(new JString(name), sb)
|
||||
s"""{"name": ${sb.toString}, "cat": "$cat", "ph": "X", "ts": ${(t.startMicros)}, "dur": ${(t.durationMicros)}, "pid": 0, "tname": "${t.threadName}"}"""
|
||||
s"""{"name": ${sb.toString}, "cat": "$cat", "ph": "X", "ts": ${(t.startMicros)}, "dur": ${(t.durationMicros)}, "pid": 0, "tid": "${t.threadId}"}"""
|
||||
}
|
||||
val entryIterator = currentTimings
|
||||
while (entryIterator.hasNext) {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter, Parser as
|
|||
import xsbti.CompileFailed
|
||||
|
||||
import java.io.File
|
||||
import java.nio.file.Paths
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import scala.collection.mutable
|
||||
|
||||
|
|
@ -628,12 +629,18 @@ object BuildServerProtocol {
|
|||
val thisProjectRef = Keys.thisProjectRef.value
|
||||
val thisConfig = Keys.configuration.value
|
||||
val scalaJars = Keys.scalaInstance.value.allJars.map(_.toURI.toString)
|
||||
val (javaHomeForTarget, isForkedJava) = Keys.javaHome.value match
|
||||
case Some(forkedJava) => (Some(forkedJava.toURI), true)
|
||||
case None => (sys.props.get("java.home").map(Paths.get(_)).map(_.toUri), false)
|
||||
val javaVersionForTarget = extractJavaVersion(javacOptions.value, isForkedJava)
|
||||
val jvmBuildTarget = JvmBuildTarget(javaHomeForTarget, javaVersionForTarget)
|
||||
val compileData = ScalaBuildTarget(
|
||||
scalaOrganization = scalaOrganization.value,
|
||||
scalaVersion = scalaVersion.value,
|
||||
scalaBinaryVersion = scalaBinaryVersion.value,
|
||||
platform = ScalaPlatform.JVM,
|
||||
jars = scalaJars.toVector
|
||||
jars = scalaJars.toVector,
|
||||
jvmBuildTarget = jvmBuildTarget,
|
||||
)
|
||||
val configuration = Keys.configuration.value
|
||||
val displayName = BuildTargetName.fromScope(thisProject.id, configuration.name)
|
||||
|
|
@ -699,7 +706,11 @@ object BuildServerProtocol {
|
|||
scalaVersion = scalaProvider.version(),
|
||||
scalaBinaryVersion = binaryScalaVersion(scalaProvider.version()),
|
||||
platform = ScalaPlatform.JVM,
|
||||
jars = scalaJars.toVector.map(_.toURI.toString)
|
||||
jars = scalaJars.toVector.map(_.toURI.toString),
|
||||
jvmBuildTarget = JvmBuildTarget(
|
||||
sys.props.get("java.home").map(Paths.get(_)).map(_.toUri),
|
||||
sys.props.get("java.version")
|
||||
),
|
||||
)
|
||||
val sbtVersionValue = sbtVersion.value
|
||||
val sbtData = SbtBuildTarget(
|
||||
|
|
@ -1057,6 +1068,26 @@ object BuildServerProtocol {
|
|||
)
|
||||
}
|
||||
|
||||
private def extractJavaVersion(
|
||||
javacOptions: Seq[String],
|
||||
isForkedJava: Boolean
|
||||
): Option[String] = {
|
||||
def getVersionAfterFlag(flag: String): Option[String] = {
|
||||
val index = javacOptions.indexOf(flag)
|
||||
if (index >= 0) javacOptions.lift(index + 1)
|
||||
else None
|
||||
}
|
||||
|
||||
val versionFromJavacOption = getVersionAfterFlag("--release")
|
||||
.orElse(getVersionAfterFlag("--target"))
|
||||
.orElse(getVersionAfterFlag("-target"))
|
||||
|
||||
versionFromJavacOption.orElse {
|
||||
// TODO: extract java version from forked javac
|
||||
if (isForkedJava) None else sys.props.get("java.version")
|
||||
}
|
||||
}
|
||||
|
||||
// naming convention still seems like the only reliable way to get IntelliJ to import this correctly
|
||||
// https://github.com/JetBrains/intellij-scala/blob/a54c2a7c157236f35957049cbfd8c10587c9e60c/scala/scala-impl/src/org/jetbrains/sbt/language/SbtFileImpl.scala#L82-L84
|
||||
private def toSbtTargetIdName(ref: LoadedBuildUnit): String = {
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ final class NetworkChannel(
|
|||
}
|
||||
}
|
||||
|
||||
val thread = new Thread(s"sbt-networkchannel-${connection.getPort}") {
|
||||
private val thread = new Thread(s"sbt-networkchannel-${connection.getPort}") {
|
||||
private val ct = "Content-Type: "
|
||||
private val x1 = "application/sbt-x1"
|
||||
override def run(): Unit = {
|
||||
|
|
@ -243,7 +243,6 @@ final class NetworkChannel(
|
|||
}
|
||||
}
|
||||
}
|
||||
thread.start()
|
||||
|
||||
private[sbt] def isLanguageServerProtocol: Boolean = true
|
||||
|
||||
|
|
@ -370,7 +369,6 @@ final class NetworkChannel(
|
|||
s"sbt-$name-write-thread"
|
||||
)
|
||||
writeThread.setDaemon(true)
|
||||
writeThread.start()
|
||||
|
||||
def publishBytes(event: Array[Byte], delimit: Boolean): Unit =
|
||||
try pendingWrites.put(event -> delimit)
|
||||
|
|
@ -959,6 +957,9 @@ final class NetworkChannel(
|
|||
}
|
||||
}
|
||||
private[sbt] def isAttached: Boolean = attached.get
|
||||
|
||||
thread.start()
|
||||
writeThread.start()
|
||||
}
|
||||
|
||||
object NetworkChannel {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ object Giter8TemplatePlugin extends AutoPlugin {
|
|||
ModuleID(
|
||||
"org.scala-sbt.sbt-giter8-resolver",
|
||||
"sbt-giter8-resolver",
|
||||
"0.16.2"
|
||||
"0.17.0"
|
||||
).cross(CrossVersion.binary),
|
||||
"sbtgiter8resolver.Giter8TemplateResolver"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import Keys.*
|
|||
|
||||
object Dependencies {
|
||||
// WARNING: Please Scala update versions in PluginCross.scala too
|
||||
val scala213 = "2.13.15"
|
||||
val scala213 = "2.13.16"
|
||||
val scala3 = "3.6.3"
|
||||
val checkPluginCross = settingKey[Unit]("Make sure scalaVersion match up")
|
||||
val baseScalaVersion = scala3
|
||||
|
|
@ -77,7 +77,7 @@ object Dependencies {
|
|||
// JLine 3 version must be coordinated together with JAnsi version
|
||||
// and the JLine 2 fork version, which uses the same JAnsi
|
||||
val jline =
|
||||
"org.scala-sbt.jline" % "jline" % "2.14.7-sbt-9c3b6aca11c57e339441442bbf58e550cdfecb79"
|
||||
"org.scala-sbt.jline" % "jline" % "2.14.7-sbt-9a88bc413e2b34a4580c001c654d1a7f4f65bf18"
|
||||
val jline3Version = "3.27.1"
|
||||
val jline3Terminal = "org.jline" % "jline-terminal" % jline3Version
|
||||
val jline3JNI = "org.jline" % "jline-terminal-jni" % jline3Version
|
||||
|
|
@ -119,7 +119,7 @@ object Dependencies {
|
|||
|
||||
// lm-coursier dependencies
|
||||
val dataclassScalafixVersion = "0.1.0"
|
||||
val coursierVersion = "2.1.19"
|
||||
val coursierVersion = "2.1.23"
|
||||
|
||||
val coursier = ("io.get-coursier" %% "coursier" % coursierVersion)
|
||||
.cross(CrossVersion.for3Use2_13)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
sbt.version=1.10.5
|
||||
sbt.version=1.10.7
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp
|
||||
/**
|
||||
* Contains jvm-specific metadata, specifically JDK reference
|
||||
* @param javaHome Uri representing absolute path to jdk
|
||||
* @param javaVersion The java version this target is supposed to use (can be set using javac `-target` flag)
|
||||
*/
|
||||
final class JvmBuildTarget private (
|
||||
val javaHome: Option[java.net.URI],
|
||||
val javaVersion: Option[String]) extends Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: JvmBuildTarget => (this.javaHome == x.javaHome) && (this.javaVersion == x.javaVersion)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (17 + "sbt.internal.bsp.JvmBuildTarget".##) + javaHome.##) + javaVersion.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"JvmBuildTarget(" + javaHome + ", " + javaVersion + ")"
|
||||
}
|
||||
private def copy(javaHome: Option[java.net.URI] = javaHome, javaVersion: Option[String] = javaVersion): JvmBuildTarget = {
|
||||
new JvmBuildTarget(javaHome, javaVersion)
|
||||
}
|
||||
def withJavaHome(javaHome: Option[java.net.URI]): JvmBuildTarget = {
|
||||
copy(javaHome = javaHome)
|
||||
}
|
||||
def withJavaHome(javaHome: java.net.URI): JvmBuildTarget = {
|
||||
copy(javaHome = Option(javaHome))
|
||||
}
|
||||
def withJavaVersion(javaVersion: Option[String]): JvmBuildTarget = {
|
||||
copy(javaVersion = javaVersion)
|
||||
}
|
||||
def withJavaVersion(javaVersion: String): JvmBuildTarget = {
|
||||
copy(javaVersion = Option(javaVersion))
|
||||
}
|
||||
}
|
||||
object JvmBuildTarget {
|
||||
|
||||
def apply(javaHome: Option[java.net.URI], javaVersion: Option[String]): JvmBuildTarget = new JvmBuildTarget(javaHome, javaVersion)
|
||||
def apply(javaHome: java.net.URI, javaVersion: String): JvmBuildTarget = new JvmBuildTarget(Option(javaHome), Option(javaVersion))
|
||||
}
|
||||
|
|
@ -14,28 +14,30 @@ package sbt.internal.bsp
|
|||
For example, 2.12 if scalaVersion is 2.12.4.
|
||||
* @param platform The target platform for this target
|
||||
* @param jars A sequence of Scala jars such as scala-library, scala-compiler and scala-reflect.
|
||||
* @param jvmBuildTarget The jvm build target describing jdk to be used
|
||||
*/
|
||||
final class ScalaBuildTarget private (
|
||||
val scalaOrganization: String,
|
||||
val scalaVersion: String,
|
||||
val scalaBinaryVersion: String,
|
||||
val platform: Int,
|
||||
val jars: Vector[String]) extends Serializable {
|
||||
val jars: Vector[String],
|
||||
val jvmBuildTarget: Option[sbt.internal.bsp.JvmBuildTarget]) extends Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: ScalaBuildTarget => (this.scalaOrganization == x.scalaOrganization) && (this.scalaVersion == x.scalaVersion) && (this.scalaBinaryVersion == x.scalaBinaryVersion) && (this.platform == x.platform) && (this.jars == x.jars)
|
||||
case x: ScalaBuildTarget => (this.scalaOrganization == x.scalaOrganization) && (this.scalaVersion == x.scalaVersion) && (this.scalaBinaryVersion == x.scalaBinaryVersion) && (this.platform == x.platform) && (this.jars == x.jars) && (this.jvmBuildTarget == x.jvmBuildTarget)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.ScalaBuildTarget".##) + scalaOrganization.##) + scalaVersion.##) + scalaBinaryVersion.##) + platform.##) + jars.##)
|
||||
37 * (37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.ScalaBuildTarget".##) + scalaOrganization.##) + scalaVersion.##) + scalaBinaryVersion.##) + platform.##) + jars.##) + jvmBuildTarget.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"ScalaBuildTarget(" + scalaOrganization + ", " + scalaVersion + ", " + scalaBinaryVersion + ", " + platform + ", " + jars + ")"
|
||||
"ScalaBuildTarget(" + scalaOrganization + ", " + scalaVersion + ", " + scalaBinaryVersion + ", " + platform + ", " + jars + ", " + jvmBuildTarget + ")"
|
||||
}
|
||||
private def copy(scalaOrganization: String = scalaOrganization, scalaVersion: String = scalaVersion, scalaBinaryVersion: String = scalaBinaryVersion, platform: Int = platform, jars: Vector[String] = jars): ScalaBuildTarget = {
|
||||
new ScalaBuildTarget(scalaOrganization, scalaVersion, scalaBinaryVersion, platform, jars)
|
||||
private def copy(scalaOrganization: String = scalaOrganization, scalaVersion: String = scalaVersion, scalaBinaryVersion: String = scalaBinaryVersion, platform: Int = platform, jars: Vector[String] = jars, jvmBuildTarget: Option[sbt.internal.bsp.JvmBuildTarget] = jvmBuildTarget): ScalaBuildTarget = {
|
||||
new ScalaBuildTarget(scalaOrganization, scalaVersion, scalaBinaryVersion, platform, jars, jvmBuildTarget)
|
||||
}
|
||||
def withScalaOrganization(scalaOrganization: String): ScalaBuildTarget = {
|
||||
copy(scalaOrganization = scalaOrganization)
|
||||
|
|
@ -52,8 +54,15 @@ final class ScalaBuildTarget private (
|
|||
def withJars(jars: Vector[String]): ScalaBuildTarget = {
|
||||
copy(jars = jars)
|
||||
}
|
||||
def withJvmBuildTarget(jvmBuildTarget: Option[sbt.internal.bsp.JvmBuildTarget]): ScalaBuildTarget = {
|
||||
copy(jvmBuildTarget = jvmBuildTarget)
|
||||
}
|
||||
def withJvmBuildTarget(jvmBuildTarget: sbt.internal.bsp.JvmBuildTarget): ScalaBuildTarget = {
|
||||
copy(jvmBuildTarget = Option(jvmBuildTarget))
|
||||
}
|
||||
}
|
||||
object ScalaBuildTarget {
|
||||
|
||||
def apply(scalaOrganization: String, scalaVersion: String, scalaBinaryVersion: String, platform: Int, jars: Vector[String]): ScalaBuildTarget = new ScalaBuildTarget(scalaOrganization, scalaVersion, scalaBinaryVersion, platform, jars)
|
||||
def apply(scalaOrganization: String, scalaVersion: String, scalaBinaryVersion: String, platform: Int, jars: Vector[String], jvmBuildTarget: Option[sbt.internal.bsp.JvmBuildTarget]): ScalaBuildTarget = new ScalaBuildTarget(scalaOrganization, scalaVersion, scalaBinaryVersion, platform, jars, jvmBuildTarget)
|
||||
def apply(scalaOrganization: String, scalaVersion: String, scalaBinaryVersion: String, platform: Int, jars: Vector[String], jvmBuildTarget: sbt.internal.bsp.JvmBuildTarget): ScalaBuildTarget = new ScalaBuildTarget(scalaOrganization, scalaVersion, scalaBinaryVersion, platform, jars, Option(jvmBuildTarget))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ trait JsonProtocol extends sjsonnew.BasicJsonProtocol
|
|||
with sbt.internal.bsp.codec.TestResultFormats
|
||||
with sbt.internal.bsp.codec.RunParamsFormats
|
||||
with sbt.internal.bsp.codec.RunResultFormats
|
||||
with sbt.internal.bsp.codec.JvmBuildTargetFormats
|
||||
with sbt.internal.bsp.codec.ScalaBuildTargetFormats
|
||||
with sbt.internal.bsp.codec.ScalacOptionsParamsFormats
|
||||
with sbt.internal.bsp.codec.ScalacOptionsItemFormats
|
||||
|
|
|
|||
29
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/JvmBuildTargetFormats.scala
generated
Normal file
29
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/JvmBuildTargetFormats.scala
generated
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait JvmBuildTargetFormats { self: sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val JvmBuildTargetFormat: JsonFormat[sbt.internal.bsp.JvmBuildTarget] = new JsonFormat[sbt.internal.bsp.JvmBuildTarget] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.JvmBuildTarget = {
|
||||
__jsOpt match {
|
||||
case Some(__js) =>
|
||||
unbuilder.beginObject(__js)
|
||||
val javaHome = unbuilder.readField[Option[java.net.URI]]("javaHome")
|
||||
val javaVersion = unbuilder.readField[Option[String]]("javaVersion")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.bsp.JvmBuildTarget(javaHome, javaVersion)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.bsp.JvmBuildTarget, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("javaHome", obj.javaHome)
|
||||
builder.addField("javaVersion", obj.javaVersion)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait SbtBuildTargetFormats { self: sbt.internal.bsp.codec.ScalaBuildTargetFormats & sjsonnew.BasicJsonProtocol & sbt.internal.bsp.codec.BuildTargetIdentifierFormats =>
|
||||
trait SbtBuildTargetFormats { self: sbt.internal.bsp.codec.ScalaBuildTargetFormats & sbt.internal.bsp.codec.JvmBuildTargetFormats & sjsonnew.BasicJsonProtocol & sbt.internal.bsp.codec.BuildTargetIdentifierFormats =>
|
||||
implicit lazy val SbtBuildTargetFormat: JsonFormat[sbt.internal.bsp.SbtBuildTarget] = new JsonFormat[sbt.internal.bsp.SbtBuildTarget] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.SbtBuildTarget = {
|
||||
__jsOpt match {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait ScalaBuildTargetFormats { self: sjsonnew.BasicJsonProtocol =>
|
||||
trait ScalaBuildTargetFormats { self: sbt.internal.bsp.codec.JvmBuildTargetFormats & sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val ScalaBuildTargetFormat: JsonFormat[sbt.internal.bsp.ScalaBuildTarget] = new JsonFormat[sbt.internal.bsp.ScalaBuildTarget] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.ScalaBuildTarget = {
|
||||
__jsOpt match {
|
||||
|
|
@ -16,8 +16,9 @@ implicit lazy val ScalaBuildTargetFormat: JsonFormat[sbt.internal.bsp.ScalaBuild
|
|||
val scalaBinaryVersion = unbuilder.readField[String]("scalaBinaryVersion")
|
||||
val platform = unbuilder.readField[Int]("platform")
|
||||
val jars = unbuilder.readField[Vector[String]]("jars")
|
||||
val jvmBuildTarget = unbuilder.readField[Option[sbt.internal.bsp.JvmBuildTarget]]("jvmBuildTarget")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.bsp.ScalaBuildTarget(scalaOrganization, scalaVersion, scalaBinaryVersion, platform, jars)
|
||||
sbt.internal.bsp.ScalaBuildTarget(scalaOrganization, scalaVersion, scalaBinaryVersion, platform, jars, jvmBuildTarget)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
|
|
@ -29,6 +30,7 @@ implicit lazy val ScalaBuildTargetFormat: JsonFormat[sbt.internal.bsp.ScalaBuild
|
|||
builder.addField("scalaBinaryVersion", obj.scalaBinaryVersion)
|
||||
builder.addField("platform", obj.platform)
|
||||
builder.addField("jars", obj.jars)
|
||||
builder.addField("jvmBuildTarget", obj.jvmBuildTarget)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -615,6 +615,17 @@ type RunResult {
|
|||
}
|
||||
|
||||
|
||||
# JVM extension
|
||||
|
||||
## Contains jvm-specific metadata, specifically JDK reference
|
||||
type JvmBuildTarget {
|
||||
## Uri representing absolute path to jdk
|
||||
javaHome: java.net.URI
|
||||
|
||||
## The java version this target is supposed to use (can be set using javac `-target` flag)
|
||||
javaVersion: String
|
||||
}
|
||||
|
||||
# Scala Extension
|
||||
|
||||
## Contains scala-specific metadata for compiling a target containing Scala sources.
|
||||
|
|
@ -636,6 +647,9 @@ type ScalaBuildTarget {
|
|||
|
||||
## A sequence of Scala jars such as scala-library, scala-compiler and scala-reflect.
|
||||
jars: [String]!
|
||||
|
||||
## The jvm build target describing jdk to be used
|
||||
jvmBuildTarget: sbt.internal.bsp.JvmBuildTarget
|
||||
}
|
||||
|
||||
## Scalac options
|
||||
|
|
|
|||
67
sbt
67
sbt
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set +e
|
||||
declare builtin_sbt_version="1.10.6"
|
||||
declare builtin_sbt_version="1.10.7"
|
||||
declare -a residual_args
|
||||
declare -a java_args
|
||||
declare -a scalac_args
|
||||
|
|
@ -25,6 +25,7 @@ declare use_sbtn=
|
|||
declare no_server=
|
||||
declare sbtn_command="$SBTN_CMD"
|
||||
declare sbtn_version="1.10.5"
|
||||
declare use_colors=1
|
||||
|
||||
### ------------------------------- ###
|
||||
### Helper methods for BASH scripts ###
|
||||
|
|
@ -104,6 +105,15 @@ declare -r sbt_home="$(dirname "$sbt_bin_dir")"
|
|||
echoerr () {
|
||||
echo 1>&2 "$@"
|
||||
}
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m' # No Color
|
||||
echoerr_error () {
|
||||
if [[ $use_colors == "1" ]]; then
|
||||
echoerr -e "[${RED}error${NC}] $@"
|
||||
else
|
||||
echoerr "[error] $@"
|
||||
fi
|
||||
}
|
||||
vlog () {
|
||||
[[ $sbt_verbose || $sbt_debug ]] && echoerr "$@"
|
||||
}
|
||||
|
|
@ -486,6 +496,21 @@ copyRt() {
|
|||
fi
|
||||
}
|
||||
|
||||
# Confirm a user's intent if the current directory does not look like an sbt
|
||||
# top-level directory and neither the --allow-empty option nor the "new" command was given.
|
||||
checkWorkingDirectory() {
|
||||
if [[ ! -n "$allow_empty" ]]; then
|
||||
[[ -f ./build.sbt || -d ./project || -n "$sbt_new" ]] || {
|
||||
echoerr_error "Neither build.sbt nor a 'project' directory in the current directory: $(pwd)"
|
||||
echoerr_error "run 'sbt new', touch build.sbt, or run 'sbt --allow-empty'."
|
||||
echoerr_error ""
|
||||
echoerr_error "To opt out of this check, create ${config_home}/sbtopts with:"
|
||||
echoerr_error "--allow-empty"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
}
|
||||
|
||||
run() {
|
||||
# Copy preloaded repo to user's preloaded directory
|
||||
syncPreloaded
|
||||
|
|
@ -522,6 +547,7 @@ run() {
|
|||
done
|
||||
echo "shutdown ${#sbt_processes[@]} sbt processes"
|
||||
else
|
||||
checkWorkingDirectory
|
||||
# run sbt
|
||||
execRunner "$java_cmd" \
|
||||
"${java_args[@]}" \
|
||||
|
|
@ -546,7 +572,10 @@ declare -r sbt_opts_file=".sbtopts"
|
|||
declare -r build_props_file="$(pwd)/project/build.properties"
|
||||
declare -r etc_sbt_opts_file="/etc/sbt/sbtopts"
|
||||
# this allows /etc/sbt/sbtopts location to be changed
|
||||
declare -r etc_file="${SBT_ETC_FILE:-$etc_sbt_opts_file}"
|
||||
declare machine_sbt_opts_file="${etc_sbt_opts_file}"
|
||||
declare config_home="${XDG_CONFIG_HOME:-$HOME/.config}/sbt"
|
||||
[[ -f "${config_home}/sbtopts" ]] && machine_sbt_opts_file="${config_home}/sbtopts"
|
||||
[[ -f "$SBT_ETC_FILE" ]] && machine_sbt_opts_file="$SBT_ETC_FILE"
|
||||
declare -r dist_sbt_opts_file="${sbt_home}/conf/sbtopts"
|
||||
declare -r win_sbt_opts_file="${sbt_home}/conf/sbtconfig.txt"
|
||||
declare sbt_jar="$(jar_file)"
|
||||
|
|
@ -571,7 +600,7 @@ Usage: `basename "$0"` [options]
|
|||
enable or disable supershell (sbt 1.3 and above)
|
||||
--traces generate Trace Event report on shutdown (sbt 1.3 and above)
|
||||
--timings display task timings report on shutdown
|
||||
--sbt-create start sbt even if current directory contains no sbt project
|
||||
--allow-empty start sbt even if current directory contains no sbt project
|
||||
--sbt-dir <path> path to global settings/plugins directory (default: ~/.sbt)
|
||||
--sbt-boot <path> path to shared boot directory (default: ~/.sbt/boot in 0.11 series)
|
||||
--sbt-cache <path> path to global cache directory (default: operating system specific)
|
||||
|
|
@ -610,7 +639,7 @@ process_my_args () {
|
|||
case "$1" in
|
||||
-batch|--batch) exec </dev/null && shift ;; #>
|
||||
|
||||
-sbt-create|--sbt-create) sbt_create=true && shift ;;
|
||||
-allow-empty|--allow-empty|-sbt-create|--sbt-create) allow_empty=true && shift ;;
|
||||
|
||||
new) sbt_new=true && addResidual "$1" && shift ;;
|
||||
|
||||
|
|
@ -620,23 +649,6 @@ process_my_args () {
|
|||
|
||||
# Now, ensure sbt version is used.
|
||||
[[ "${sbt_version}XXX" != "XXX" ]] && addJava "-Dsbt.version=$sbt_version"
|
||||
|
||||
# Confirm a user's intent if the current directory does not look like an sbt
|
||||
# top-level directory and neither the -sbt-create option nor the "new"
|
||||
# command was given.
|
||||
[[ -f ./build.sbt || -d ./project || -n "$sbt_create" || -n "$sbt_new" ]] || {
|
||||
echo "[warn] Neither build.sbt nor a 'project' directory in the current directory: $(pwd)"
|
||||
while true; do
|
||||
echo 'c) continue'
|
||||
echo 'q) quit'
|
||||
|
||||
read -p '? ' || exit 1
|
||||
case "$REPLY" in
|
||||
c|C) break ;;
|
||||
q|Q) exit 1 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
## map over argument array. this is used to process both command line arguments and SBT_OPTS
|
||||
|
|
@ -697,6 +709,7 @@ process_args () {
|
|||
export PATH="$2/bin:$PATH" &&
|
||||
shift 2 ;;
|
||||
|
||||
-Dsbt.color=never|-Dsbt.log.noformat=true) addJava "$1" && use_colors=0 && shift ;;
|
||||
"-D*"|-D*) addJava "$1" && shift ;;
|
||||
-J*) addJava "${1:2}" && shift ;;
|
||||
*) addResidual "$1" && shift ;;
|
||||
|
|
@ -788,11 +801,13 @@ runNativeClient() {
|
|||
|
||||
original_args=("$@")
|
||||
|
||||
# Here we pull in the default settings configuration.
|
||||
[[ -f "$dist_sbt_opts_file" ]] && set -- $(loadConfigFile "$dist_sbt_opts_file") "$@"
|
||||
|
||||
# Here we pull in the global settings configuration.
|
||||
[[ -f "$etc_file" ]] && set -- $(loadConfigFile "$etc_file") "$@"
|
||||
# Pull in the machine-wide settings configuration.
|
||||
if [[ -f "$machine_sbt_opts_file" ]]; then
|
||||
set -- $(loadConfigFile "$machine_sbt_opts_file") "$@"
|
||||
else
|
||||
# Otherwise pull in the default settings configuration.
|
||||
[[ -f "$dist_sbt_opts_file" ]] && set -- $(loadConfigFile "$dist_sbt_opts_file") "$@"
|
||||
fi
|
||||
|
||||
# Pull in the project-level config file, if it exists.
|
||||
[[ -f "$sbt_opts_file" ]] && set -- $(loadConfigFile "$sbt_opts_file") "$@"
|
||||
|
|
|
|||
|
|
@ -2,3 +2,5 @@
|
|||
-> demo-failure
|
||||
> +z
|
||||
> z
|
||||
|
||||
$ absent /tmp/non-existent
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ libraryDependencies ++= Seq(
|
|||
"org.slf4j" % "slf4j-api" % "1.7.2",
|
||||
"ch.qos.logback" % "logback-classic" % "1.0.7"
|
||||
)
|
||||
csrMavenDependencyOverride := false
|
||||
|
||||
TaskKey[Unit]("check") := {
|
||||
val report = updateFull.value
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
import scala.language.reflectiveCalls
|
||||
|
||||
|
||||
package scala.collection.immutable {
|
||||
object Exp {
|
||||
// Access RedBlackTree.validate added in Scala 2.13.13
|
||||
def v = RedBlackTree.validate(null)(null)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object A extends App {
|
||||
println(scala.util.Properties.versionString)
|
||||
}
|
||||
|
||||
object AMacro {
|
||||
import scala.language.experimental.macros
|
||||
import scala.reflect.macros.blackbox.Context
|
||||
|
||||
def m(x: Int): Int = macro impl
|
||||
|
||||
def impl(c: Context)(x: c.Expr[Int]): c.Expr[Int] = {
|
||||
import c.universe._
|
||||
println(scala.collection.immutable.Exp.v)
|
||||
c.Expr(q"2 + $x")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import java.nio.file.{Paths, Files}
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
object B extends App {
|
||||
println(AMacro.m(33)) // fails
|
||||
Files.write(Paths.get(s"s${scala.util.Properties.versionNumberString}.txt"), "nix".getBytes)
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import sbt.librarymanagement.InclExclRule
|
||||
|
||||
lazy val a = project.settings(
|
||||
scalaVersion := "2.13.13",
|
||||
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value,
|
||||
TaskKey[Unit]("checkLibs") := checkLibs("2.13.13", (Compile/dependencyClasspath).value, ".*scala-(library|reflect).*"),
|
||||
)
|
||||
|
||||
lazy val b = project.dependsOn(a).settings(
|
||||
allowUnsafeScalaLibUpgrade := true,
|
||||
scalaVersion := "2.13.12",
|
||||
|
||||
// dependencies are upgraded to 2.13.13
|
||||
TaskKey[Unit]("checkLibs") := checkLibs("2.13.13", (Compile/dependencyClasspath).value, ".*scala-(library|reflect).*"),
|
||||
|
||||
// check the compiler uses the 2.13.12 library on its runtime classpath
|
||||
TaskKey[Unit]("checkScala") := {
|
||||
val i = scalaInstance.value
|
||||
i.libraryJars.filter(_.toString.contains("scala-library")).toList match {
|
||||
case List(l) => assert(l.toString.contains("2.13.12"), i.toString)
|
||||
}
|
||||
assert(i.compilerJars.filter(_.toString.contains("scala-library")).isEmpty, i.toString)
|
||||
assert(i.otherJars.filter(_.toString.contains("scala-library")).isEmpty, i.toString)
|
||||
},
|
||||
)
|
||||
|
||||
lazy val c = project.dependsOn(a).settings(
|
||||
allowUnsafeScalaLibUpgrade := true,
|
||||
scalaVersion := "2.13.12",
|
||||
TaskKey[Unit]("checkLibs") := checkLibs("2.13.13", (Compile/dependencyClasspath).value, ".*scala-(library|reflect).*"),
|
||||
)
|
||||
|
||||
def checkLibs(v: String, cp: Classpath, filter: String): Unit = {
|
||||
for (p <- cp)
|
||||
if (p.toString.matches(filter)) {
|
||||
println(s"$p -- $v")
|
||||
assert(p.toString.contains(v), p)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import java.nio.file.{Paths, Files}
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
object C extends App {
|
||||
assert(scala.collection.immutable.Exp.v == null)
|
||||
Files.write(Paths.get(s"s${scala.util.Properties.versionNumberString}.txt"), "nix".getBytes)
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
> a/checkLibs
|
||||
> b/checkLibs
|
||||
> b/checkScala
|
||||
> c/checkLibs
|
||||
|
||||
# macro expansion fails
|
||||
-> b/compile
|
||||
|
||||
> c/runBlock
|
||||
$ exists s2.13.13.txt
|
||||
$ delete s2.13.13.txt
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# This tests that this sbt scripted plugin can launch the previous one
|
||||
|
||||
> ^^1.10.5
|
||||
> ^^1.10.7
|
||||
|
||||
$ copy-file changes/A.scala src/sbt-test/a/b/A.scala
|
||||
> scripted
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter }
|
|||
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.{ Files, Paths }
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import scala.concurrent.duration.*
|
||||
|
||||
|
|
@ -57,6 +57,16 @@ class BuildServerTest extends AbstractServerTest {
|
|||
case None => sys.error(s"buildserver-root-build not in ${result.targets}")
|
||||
assert(buildServerBuildTarget.id.uri.toString.endsWith("#buildserver-root-build"))
|
||||
assert(!result.targets.exists(_.displayName.contains("badBuildTarget")))
|
||||
// Check for JVM based Scala Project, built target should contain Java version information
|
||||
val scalaBuildTarget =
|
||||
Converter.fromJsonOptionUnsafe[ScalaBuildTarget](utilTarget.data)
|
||||
val javaTarget = scalaBuildTarget.jvmBuildTarget
|
||||
(javaTarget.flatMap(_.javaVersion), javaTarget.flatMap(_.javaHome)) match {
|
||||
case (Some(javaVersion), Some(javaHome)) =>
|
||||
assert(javaVersion.equals(sys.props("java.version")))
|
||||
assert(javaHome.equals(Paths.get(sys.props("java.home")).toUri))
|
||||
case _ => fail("JVM build target should contain javaVersion and javaHome")
|
||||
}
|
||||
}
|
||||
|
||||
test("buildTarget/sources") {
|
||||
|
|
|
|||
Loading…
Reference in New Issue