Adapt ScalaOverride to Scala 3

This commit is contained in:
Adrien Piquerez 2020-12-18 16:55:36 +01:00
parent 0672da475d
commit 24f85fd18c
3 changed files with 198 additions and 52 deletions

View File

@ -1,16 +1,30 @@
package sbt.librarymanagement package sbt.librarymanagement
object ScalaArtifacts { object ScalaArtifacts {
val Organization = "org.scala-lang" final val Organization = "org.scala-lang"
val LibraryID = "scala-library" final val LibraryID = "scala-library"
val CompilerID = "scala-compiler" final val CompilerID = "scala-compiler"
val ReflectID = "scala-reflect" final val ReflectID = "scala-reflect"
val ActorsID = "scala-actors" final val ActorsID = "scala-actors"
val ScalapID = "scalap" final val ScalapID = "scalap"
val Artifacts = Vector(LibraryID, CompilerID, ReflectID, ActorsID, ScalapID) final val Artifacts = Vector(LibraryID, CompilerID, ReflectID, ActorsID, ScalapID)
val Scala3LibraryID = "scala3-library" final val Scala3LibraryID = "scala3-library"
val Scala3CompilerID = "scala3-compiler" final val Scala3CompilerID = "scala3-compiler"
final val Scala3InterfacesID = "scala3-interfaces"
final val TastyCoreID = "tasty-core"
private[sbt] final val Scala3LibraryPrefix = Scala3LibraryID + "_"
private[sbt] final val Scala3CompilerPrefix = Scala3CompilerID + "_"
private[sbt] final val TastyCorePrefix = TastyCoreID + "_"
def isScala2Artifact(name: String): Boolean = {
name == LibraryID || name == CompilerID || name == ReflectID || name == ActorsID || name == ScalapID
}
def isScala3Artifact(name: String): Boolean = {
name.startsWith(Scala3LibraryPrefix) || name.startsWith(Scala3CompilerPrefix) ||
name.startsWith(TastyCorePrefix) || name == Scala3InterfacesID
}
def isScala3(scalaVersion: String): Boolean = scalaVersion.startsWith("3.") def isScala3(scalaVersion: String): Boolean = scalaVersion.startsWith("3.")

View File

@ -12,7 +12,7 @@ import org.apache.ivy.plugins.matcher.ExactPatternMatcher
import org.apache.ivy.plugins.namespace.NamespaceTransformer import org.apache.ivy.plugins.namespace.NamespaceTransformer
import sbt.util.Logger import sbt.util.Logger
import sbt.librarymanagement.ScalaArtifacts._ import sbt.librarymanagement.ScalaArtifacts._
import sbt.librarymanagement.{ ScalaModuleInfo, CrossVersion, Configuration } import sbt.librarymanagement.{ Configuration, CrossVersion, ScalaModuleInfo }
object IvyScalaUtil { object IvyScalaUtil {
@ -48,38 +48,43 @@ object IvyScalaUtil {
scalaVersionConfigs0: Vector[String] scalaVersionConfigs0: Vector[String]
) extends DependencyDescriptorMediator { ) extends DependencyDescriptorMediator {
private[this] val scalaVersionConfigs = scalaVersionConfigs0.toSet private[this] val scalaVersionConfigs = scalaVersionConfigs0.toSet
private val binaryVersion = CrossVersion.binaryScalaVersion(scalaVersion)
def mediate(dd: DependencyDescriptor): DependencyDescriptor = { def mediate(dd: DependencyDescriptor): DependencyDescriptor = {
// Mediate only for the dependencies in scalaVersion configurations. https://github.com/sbt/sbt/issues/2786 // Mediate only for the dependencies in scalaVersion configurations. https://github.com/sbt/sbt/issues/2786
def configQualifies: Boolean = def configQualifies: Boolean =
(dd.getModuleConfigurations exists { scalaVersionConfigs }) dd.getModuleConfigurations exists { scalaVersionConfigs }
// Do not rewrite the dependencies of Scala dependencies themselves, this prevents bootstrapping // Do not rewrite the dependencies of Scala dependencies themselves, this prevents bootstrapping
// a Scala compiler using another Scala compiler. // a Scala compiler using another Scala compiler.
def dependeeQualifies: Boolean = def dependeeQualifies: Boolean =
dd.getParentRevisionId == null || ( dd.getParentRevisionId == null ||
dd.getParentRevisionId.getName match { !isScala2Artifact(dd.getParentRevisionId.getName) ||
case _ @(CompilerID | LibraryID | ReflectID | ActorsID | ScalapID) => !isScala3Artifact(dd.getParentRevisionId.getName)
false
case _ => def matchBinaryVersion(version: String): Boolean =
true CrossVersion.binaryScalaVersion(version) == binaryVersion
}
)
val transformer = val transformer =
new NamespaceTransformer { new NamespaceTransformer {
def transform(mrid: ModuleRevisionId): ModuleRevisionId = { def transform(mrid: ModuleRevisionId): ModuleRevisionId = {
if (mrid == null) mrid if (mrid == null) mrid
else else if ((isScala2Artifact(mrid.getName) || isScala3Artifact(mrid.getName)) &&
mrid.getName match { configQualifies &&
case name @ (CompilerID | LibraryID | ReflectID | ActorsID | ScalapID) dependeeQualifies) {
if configQualifies && dependeeQualifies => // do not override the binary incompatible Scala version because:
ModuleRevisionId.newInstance( // - the artifacts compiled with Scala 3 depends on the Scala 2.13 scala-library
scalaOrganization, // - the Scala 2 TASTy reader can consume the Scala 3 artifacts
name, val newScalaVersion =
mrid.getBranch, if (matchBinaryVersion(mrid.getRevision)) scalaVersion
scalaVersion, else mrid.getRevision
mrid.getQualifiedExtraAttributes
) ModuleRevisionId.newInstance(
case _ => mrid scalaOrganization,
} mrid.getName,
mrid.getBranch,
newScalaVersion,
mrid.getQualifiedExtraAttributes
)
} else mrid
} }
def isIdentity: Boolean = false def isIdentity: Boolean = false

View File

@ -11,10 +11,13 @@ import verify.BasicTestSuite
object ScalaOverrideTest extends BasicTestSuite { object ScalaOverrideTest extends BasicTestSuite {
val OtherOrgID = "other.org" val OtherOrgID = "other.org"
def check(org0: String, version0: String)(org1: String, name1: String, version1: String) = { private val scalaConfigs =
val scalaConfigs = Configurations.default.toVector filter { Configurations.underScalaVersion } map { Configurations.default.filter(Configurations.underScalaVersion).map(_.name)
_.name
} def checkOrgAndVersion(
org0: String,
version0: String
)(org1: String, name1: String, version1: String): Unit = {
val osm = new OverrideScalaMediator(org0, version0, scalaConfigs) val osm = new OverrideScalaMediator(org0, version0, scalaConfigs)
val mrid = ModuleRevisionId.newInstance(org1, name1, version1) val mrid = ModuleRevisionId.newInstance(org1, name1, version1)
@ -25,8 +28,36 @@ object ScalaOverrideTest extends BasicTestSuite {
assert(res.getDependencyRevisionId == ModuleRevisionId.newInstance(org0, name1, version0)) assert(res.getDependencyRevisionId == ModuleRevisionId.newInstance(org0, name1, version0))
} }
test("""OverrideScalaMediator should override compiler version""") { def checkOnlyOrg(
check(Organization, "2.11.8")( org0: String,
version0: String
)(org1: String, name1: String, version1: String): Unit = {
val osm = new OverrideScalaMediator(org0, version0, scalaConfigs)
val mrid = ModuleRevisionId.newInstance(org1, name1, version1)
val dd = new DefaultDependencyDescriptor(mrid, false)
dd.addDependencyConfiguration("compile", "compile")
val res = osm.mediate(dd)
assert(res.getDependencyRevisionId == ModuleRevisionId.newInstance(org0, name1, version1))
}
def checkNoOverride(
org0: String,
version0: String
)(org1: String, name1: String, version1: String): Unit = {
val osm = new OverrideScalaMediator(org0, version0, scalaConfigs)
val mrid = ModuleRevisionId.newInstance(org1, name1, version1)
val dd = new DefaultDependencyDescriptor(mrid, false)
dd.addDependencyConfiguration("compile", "compile")
val res = osm.mediate(dd)
assert(res.getDependencyRevisionId == mrid)
}
test("OverrideScalaMediator should override compiler version") {
checkOrgAndVersion(Organization, "2.11.8")(
Organization, Organization,
CompilerID, CompilerID,
"2.11.9" "2.11.9"
@ -34,7 +65,7 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override library version") { test("it should override library version") {
check(Organization, "2.11.8")( checkOrgAndVersion(Organization, "2.11.8")(
Organization, Organization,
LibraryID, LibraryID,
"2.11.8" "2.11.8"
@ -42,7 +73,7 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override reflect version") { test("it should override reflect version") {
check(Organization, "2.11.8")( checkOrgAndVersion(Organization, "2.11.8")(
Organization, Organization,
ReflectID, ReflectID,
"2.11.7" "2.11.7"
@ -50,7 +81,7 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override actors version") { test("it should override actors version") {
check(Organization, "2.11.8")( checkOrgAndVersion(Organization, "2.11.8")(
Organization, Organization,
ActorsID, ActorsID,
"2.11.6" "2.11.6"
@ -58,7 +89,7 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override scalap version") { test("it should override scalap version") {
check(Organization, "2.11.8")( checkOrgAndVersion(Organization, "2.11.8")(
Organization, Organization,
ScalapID, ScalapID,
"2.11.5" "2.11.5"
@ -66,7 +97,7 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override default compiler organization") { test("it should override default compiler organization") {
check(OtherOrgID, "2.11.8")( checkOrgAndVersion(OtherOrgID, "2.11.8")(
Organization, Organization,
CompilerID, CompilerID,
"2.11.9" "2.11.9"
@ -74,7 +105,7 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override default library organization") { test("it should override default library organization") {
check(OtherOrgID, "2.11.8")( checkOrgAndVersion(OtherOrgID, "2.11.8")(
Organization, Organization,
LibraryID, LibraryID,
"2.11.8" "2.11.8"
@ -82,7 +113,7 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override default reflect organization") { test("it should override default reflect organization") {
check(OtherOrgID, "2.11.8")( checkOrgAndVersion(OtherOrgID, "2.11.8")(
Organization, Organization,
ReflectID, ReflectID,
"2.11.7" "2.11.7"
@ -90,7 +121,7 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override default actors organization") { test("it should override default actors organization") {
check(OtherOrgID, "2.11.8")( checkOrgAndVersion(OtherOrgID, "2.11.8")(
Organization, Organization,
ActorsID, ActorsID,
"2.11.6" "2.11.6"
@ -98,7 +129,7 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override default scalap organization") { test("it should override default scalap organization") {
check(OtherOrgID, "2.11.8")( checkOrgAndVersion(OtherOrgID, "2.11.8")(
Organization, Organization,
ScalapID, ScalapID,
"2.11.5" "2.11.5"
@ -106,7 +137,7 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override custom compiler organization") { test("it should override custom compiler organization") {
check(Organization, "2.11.8")( checkOrgAndVersion(Organization, "2.11.8")(
OtherOrgID, OtherOrgID,
CompilerID, CompilerID,
"2.11.9" "2.11.9"
@ -114,7 +145,7 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override custom library organization") { test("it should override custom library organization") {
check(Organization, "2.11.8")( checkOrgAndVersion(Organization, "2.11.8")(
OtherOrgID, OtherOrgID,
LibraryID, LibraryID,
"2.11.8" "2.11.8"
@ -122,7 +153,7 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override custom reflect organization") { test("it should override custom reflect organization") {
check(Organization, "2.11.8")( checkOrgAndVersion(Organization, "2.11.8")(
OtherOrgID, OtherOrgID,
ReflectID, ReflectID,
"2.11.7" "2.11.7"
@ -130,7 +161,7 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override custom actors organization") { test("it should override custom actors organization") {
check(Organization, "2.11.8")( checkOrgAndVersion(Organization, "2.11.8")(
OtherOrgID, OtherOrgID,
ActorsID, ActorsID,
"2.11.6" "2.11.6"
@ -138,10 +169,106 @@ object ScalaOverrideTest extends BasicTestSuite {
} }
test("it should override custom scalap organization") { test("it should override custom scalap organization") {
check(Organization, "2.11.8")( checkOrgAndVersion(Organization, "2.11.8")(
OtherOrgID, OtherOrgID,
ScalapID, ScalapID,
"2.11.5" "2.11.5"
) )
} }
test("it should override Scala 3 compiler version") {
checkOrgAndVersion(Organization, "3.1.0")(
Organization,
Scala3CompilerPrefix + "3",
"3.0.0"
)
}
test("it should override Scala 3 library version") {
checkOrgAndVersion(Organization, "3.1.0")(
Organization,
Scala3LibraryPrefix + "3",
"3.0.0"
)
}
test("it should override Scala 3 interfaces version") {
checkOrgAndVersion(Organization, "3.1.0")(
Organization,
Scala3InterfacesID,
"3.0.0"
)
}
test("it should override TASTy core version") {
checkOrgAndVersion(Organization, "3.1.0")(
Organization,
TastyCorePrefix + "3",
"3.0.0"
)
}
test("it should not override Scala 2 library version when using Scala 3") {
checkNoOverride(Organization, "3.1.0")(
Organization,
LibraryID,
"2.13.4"
)
}
test("it should not override TASTy core version when using Scala 2") {
checkNoOverride(Organization, "2.13.4")(
Organization,
TastyCorePrefix + "3",
"3.0.0"
)
}
test("it should override default Scala 3 compiler organization") {
checkOrgAndVersion(OtherOrgID, "3.1.0")(
Organization,
Scala3CompilerPrefix + "3",
"3.0.0"
)
}
test("it should override default Scala 3 library organization") {
checkOrgAndVersion(OtherOrgID, "3.1.0")(
Organization,
Scala3LibraryPrefix + "3",
"3.0.0"
)
}
test("it should override default Scala 3 interfaces organization") {
checkOrgAndVersion(OtherOrgID, "3.1.0")(
Organization,
Scala3InterfacesID,
"3.0.0"
)
}
test("it should override default Scala 3 TASTy core organization") {
checkOrgAndVersion(OtherOrgID, "3.1.0")(
Organization,
TastyCorePrefix + "3",
"3.0.0"
)
}
test("it should override default Scala 2 library organization when in Scala 3") {
checkOnlyOrg(OtherOrgID, "3.1.0")(
Organization,
LibraryID,
"2.13.4"
)
}
test("it should override default TASTy core organization when in Scala 2") {
checkOnlyOrg(OtherOrgID, "2.13.4")(
Organization,
TastyCorePrefix + "3",
"3.0.0"
)
}
} }