Skip to content

Commit e317435

Browse files
authored
Ensure vague Scala versions are capped at defaults (#3259)
1 parent eec8bde commit e317435

File tree

4 files changed

+133
-89
lines changed

4 files changed

+133
-89
lines changed

build.sc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,8 @@ trait Core extends ScalaCliCrossSbtModule
497497
| def defaultScalaVersion = "${Scala.defaultUser}"
498498
| def defaultScala212Version = "${Scala.scala212}"
499499
| def defaultScala213Version = "${Scala.scala213}"
500+
| def scala3NextRcVersion = "${Scala.scala3NextRc}"
501+
| def scala3NextPrefix = "${Scala.scala3NextPrefix}"
500502
| def scala3LtsPrefix = "${Scala.scala3LtsPrefix}"
501503
|
502504
| def workspaceDirName = "$workspaceDirName"

modules/build/src/test/scala/scala/build/tests/BuildOptionsTests.scala

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import scala.build.internal.Regexes.scala2NightlyRegex
1717
import scala.build.options.{
1818
BuildOptions,
1919
BuildRequirements,
20+
ClassPathOptions,
2021
InternalOptions,
2122
MaybeScalaVersion,
2223
ScalaOptions,
@@ -318,34 +319,61 @@ class BuildOptionsTests extends TestUtil.ScalaCliBuildSuite {
318319
expect(scalaParams == expectedScalaParams)
319320
}
320321

321-
for {
322-
(prefix, defaultMatchingVersion) <- Seq(
323-
"2.12" -> defaultScala212Version,
324-
"2.13" -> defaultScala213Version,
325-
"3" -> defaultScalaVersion
326-
)
327-
} {
328-
val options = BuildOptions(
329-
scalaOptions = ScalaOptions(
330-
scalaVersion = Some(prefix).map(MaybeScalaVersion(_))
331-
),
332-
internal = InternalOptions(
333-
cache = Some(FileCache().withTtl(0.seconds))
322+
{
323+
val cache = FileCache().withTtl(0.seconds)
324+
val repositories = BuildOptions(
325+
internal = InternalOptions(cache = Some(cache)),
326+
classPathOptions =
327+
ClassPathOptions(extraRepositories = Seq(coursier.Repositories.scalaIntegration.root))
328+
).finalRepositories.orThrow
329+
val allScalaVersions = ScalaVersionUtil.allMatchingVersions(None, cache, repositories)
330+
for {
331+
(prefix, defaultMatchingVersion, predefinedDefaultScalaVersion) <- {
332+
val scala2Nightlies = allScalaVersions.filter(ScalaVersionUtil.isScala2Nightly)
333+
val latest212Nightly = scala2Nightlies.filter(_.startsWith("2.12")).maxBy(Version(_))
334+
val latest213Nightly = scala2Nightlies.filter(_.startsWith("2.13")).maxBy(Version(_))
335+
val latestScala3NextNightly =
336+
allScalaVersions
337+
.filter(ScalaVersionUtil.isScala3Nightly)
338+
.filter(_.startsWith(scala3NextPrefix))
339+
.maxBy(Version(_))
340+
Seq(
341+
("2.12", defaultScala212Version, None),
342+
("2.12", defaultScala212Version, Some(latest212Nightly)),
343+
("2.13", defaultScala213Version, None),
344+
("2.13", defaultScala213Version, Some(latest213Nightly)),
345+
("3", defaultScalaVersion, None),
346+
(scala3NextPrefix, defaultScalaVersion, None),
347+
(scala3NextPrefix, defaultScalaVersion, Some(latestScala3NextNightly))
348+
)
349+
}
350+
options = BuildOptions(
351+
scalaOptions = ScalaOptions(
352+
scalaVersion = Some(prefix).map(MaybeScalaVersion(_)),
353+
defaultScalaVersion = predefinedDefaultScalaVersion
354+
),
355+
internal = InternalOptions(
356+
cache = Some(cache)
357+
),
358+
classPathOptions = ClassPathOptions(
359+
extraRepositories = Seq(coursier.Repositories.scalaIntegration.root)
360+
)
334361
)
335-
)
336-
337-
val latestMatchingVersion = ScalaVersionUtil
338-
.allMatchingVersions(None, options.finalCache, options.finalRepositories.orThrow)
339-
.filter(ScalaVersionUtil.isStable)
340-
.filter(_.startsWith(prefix))
341-
.maxBy(Version(_))
342-
343-
test(
344-
s"-S $prefix should chose the latest version ($latestMatchingVersion), not necessarily the default ($defaultMatchingVersion)"
345-
) {
362+
latestMatchingVersion = allScalaVersions
363+
.filter(ScalaVersionUtil.isStable)
364+
.filter(_.startsWith(prefix))
365+
.maxBy(Version(_))
366+
expectedVersion = predefinedDefaultScalaVersion.getOrElse(defaultMatchingVersion)
367+
expectedVersionDescription =
368+
if expectedVersion == defaultMatchingVersion then "default" else "overridden default"
369+
launcherDefaultVersionDescription = if expectedVersion == defaultMatchingVersion then ""
370+
else s"or the launcher default ($defaultMatchingVersion)"
371+
testDescription =
372+
s"-S $prefix should choose the $expectedVersionDescription version ($expectedVersion), not necessarily the latest stable ($latestMatchingVersion) $launcherDefaultVersionDescription"
373+
} test(testDescription) {
346374
val scalaParams = options.scalaParams.orThrow.getOrElse(???)
347375

348-
val expectedScalaParams = ScalaParameters(latestMatchingVersion)
376+
val expectedScalaParams = ScalaParameters(expectedVersion)
349377

350378
expect(scalaParams == expectedScalaParams, s"expected $expectedScalaParams, got $scalaParams")
351379
}

modules/options/src/main/scala/scala/build/options/BuildOptions.scala

Lines changed: 75 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -317,69 +317,82 @@ final case class BuildOptions(
317317
scalaOptions.defaultScalaVersion.getOrElse(Constants.defaultScalaVersion)
318318
)
319319

320-
val svOpt: Option[String] = scalaOptions.scalaVersion match {
321-
case Some(MaybeScalaVersion(None)) =>
322-
None
323-
// Do not validate Scala version in offline mode
324-
case Some(MaybeScalaVersion(Some(svInput))) if internal.offline.getOrElse(false) =>
325-
Some(svInput)
326-
// Do not validate Scala version if it is a default one
327-
case Some(MaybeScalaVersion(Some(svInput))) if defaultVersions.contains(svInput) =>
328-
Some(svInput)
329-
case Some(MaybeScalaVersion(Some(svInput))) =>
330-
val sv = value {
331-
svInput match {
332-
case sv if ScalaVersionUtil.scala3Lts.contains(sv) =>
333-
ScalaVersionUtil.validateStable(
334-
Constants.scala3LtsPrefix,
335-
cache,
336-
repositories
337-
)
338-
case sv if ScalaVersionUtil.scala2Lts.contains(sv) =>
339-
Left(new ScalaVersionError(
340-
s"Invalid Scala version: $sv. There is no official LTS version for Scala 2."
341-
))
342-
case sv if sv == ScalaVersionUtil.scala3Nightly =>
343-
ScalaVersionUtil.GetNightly.scala3(cache)
344-
case scala3NightlyNicknameRegex(threeSubBinaryNum) =>
345-
ScalaVersionUtil.GetNightly.scala3X(
346-
threeSubBinaryNum,
347-
cache
348-
)
349-
case vs if ScalaVersionUtil.scala213Nightly.contains(vs) =>
350-
ScalaVersionUtil.GetNightly.scala2("2.13", cache)
351-
case sv if sv == ScalaVersionUtil.scala212Nightly =>
352-
ScalaVersionUtil.GetNightly.scala2("2.12", cache)
353-
case versionString if ScalaVersionUtil.isScala3Nightly(versionString) =>
354-
ScalaVersionUtil.CheckNightly.scala3(
355-
versionString,
356-
cache
357-
)
358-
.map(_ => versionString)
359-
case versionString if ScalaVersionUtil.isScala2Nightly(versionString) =>
360-
ScalaVersionUtil.CheckNightly.scala2(
361-
versionString,
362-
cache
363-
)
364-
.map(_ => versionString)
365-
case versionString if versionString.exists(_.isLetter) =>
366-
ScalaVersionUtil.validateNonStable(
367-
versionString,
368-
cache,
369-
repositories
370-
)
371-
case versionString =>
372-
ScalaVersionUtil.validateStable(
373-
versionString,
374-
cache,
375-
repositories
376-
)
320+
val svOpt: Option[String] =
321+
scalaOptions.scalaVersion -> scalaOptions.defaultScalaVersion match {
322+
case (Some(MaybeScalaVersion(None)), _) =>
323+
None
324+
// Do not validate Scala version in offline mode
325+
case (Some(MaybeScalaVersion(Some(svInput))), _) if internal.offline.getOrElse(false) =>
326+
Some(svInput)
327+
// Do not validate Scala version if it is a default one
328+
case (Some(MaybeScalaVersion(Some(svInput))), _) if defaultVersions.contains(svInput) =>
329+
Some(svInput)
330+
case (Some(MaybeScalaVersion(Some(svInput))), Some(predefinedScalaVersion))
331+
if predefinedScalaVersion.startsWith(svInput) &&
332+
(svInput == "3" || svInput == Constants.scala3NextPrefix ||
333+
svInput == "2.13" || svInput == "2.12") =>
334+
Some(predefinedScalaVersion)
335+
case (Some(MaybeScalaVersion(Some(svInput))), None)
336+
if svInput == "3" || svInput == Constants.scala3NextPrefix =>
337+
Some(Constants.defaultScalaVersion)
338+
case (Some(MaybeScalaVersion(Some(svInput))), None) if svInput == "2.13" =>
339+
Some(Constants.defaultScala213Version)
340+
case (Some(MaybeScalaVersion(Some(svInput))), None) if svInput == "2.12" =>
341+
Some(Constants.defaultScala212Version)
342+
case (Some(MaybeScalaVersion(Some(svInput))), _) =>
343+
val sv = value {
344+
svInput match {
345+
case sv if ScalaVersionUtil.scala3Lts.contains(sv) =>
346+
ScalaVersionUtil.validateStable(
347+
Constants.scala3LtsPrefix,
348+
cache,
349+
repositories
350+
)
351+
case sv if ScalaVersionUtil.scala2Lts.contains(sv) =>
352+
Left(new ScalaVersionError(
353+
s"Invalid Scala version: $sv. There is no official LTS version for Scala 2."
354+
))
355+
case sv if sv == ScalaVersionUtil.scala3Nightly =>
356+
ScalaVersionUtil.GetNightly.scala3(cache)
357+
case scala3NightlyNicknameRegex(threeSubBinaryNum) =>
358+
ScalaVersionUtil.GetNightly.scala3X(
359+
threeSubBinaryNum,
360+
cache
361+
)
362+
case vs if ScalaVersionUtil.scala213Nightly.contains(vs) =>
363+
ScalaVersionUtil.GetNightly.scala2("2.13", cache)
364+
case sv if sv == ScalaVersionUtil.scala212Nightly =>
365+
ScalaVersionUtil.GetNightly.scala2("2.12", cache)
366+
case versionString if ScalaVersionUtil.isScala3Nightly(versionString) =>
367+
ScalaVersionUtil.CheckNightly.scala3(
368+
versionString,
369+
cache
370+
)
371+
.map(_ => versionString)
372+
case versionString if ScalaVersionUtil.isScala2Nightly(versionString) =>
373+
ScalaVersionUtil.CheckNightly.scala2(
374+
versionString,
375+
cache
376+
)
377+
.map(_ => versionString)
378+
case versionString if versionString.exists(_.isLetter) =>
379+
ScalaVersionUtil.validateNonStable(
380+
versionString,
381+
cache,
382+
repositories
383+
)
384+
case versionString =>
385+
ScalaVersionUtil.validateStable(
386+
versionString,
387+
cache,
388+
repositories
389+
)
390+
}
377391
}
378-
}
379-
Some(sv)
380-
381-
case None => Some(scalaOptions.defaultScalaVersion.getOrElse(Constants.defaultScalaVersion))
382-
}
392+
Some(sv)
393+
case (None, Some(predefinedScalaVersion)) => Some(predefinedScalaVersion)
394+
case _ => Some(Constants.defaultScalaVersion)
395+
}
383396

384397
svOpt match {
385398
case Some(scalaVersion) =>

project/deps.sc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ object Scala {
77
def scala213 = "2.13.15"
88
def runnerScala3 = "3.0.2" // the newest version that is compatible with all Scala 3.x versions
99
def scala3LtsPrefix = "3.3" // used for the LTS version tags
10-
def scala3Lts = s"$scala3LtsPrefix.4" // the LTS version currently used in the build
11-
def scala3Next = "3.5.2" // the newest/next version of Scala
10+
def scala3Lts = s"$scala3LtsPrefix.4" // the LTS version currently used in the build
11+
def scala3NextPrefix = "3.5"
12+
def scala3Next = s"$scala3NextPrefix.2" // the newest/next version of Scala
1213
def scala3NextAnnounced = scala3Next // the newest/next version of Scala that's been announced
1314
def scala3NextRc = "3.6.2-RC1" // the latest RC version of Scala Next
1415

0 commit comments

Comments
 (0)