diff --git a/src/main/scala/sbt/VirtualAxis.scala b/src/main/scala/sbt/VirtualAxis.scala index 2b2648909..7d831682b 100644 --- a/src/main/scala/sbt/VirtualAxis.scala +++ b/src/main/scala/sbt/VirtualAxis.scala @@ -23,16 +23,50 @@ object VirtualAxis { abstract class StrongAxis extends VirtualAxis - def isMatch(lhs: Seq[VirtualAxis], rhs: Seq[VirtualAxis]): Boolean = { - def isCompatible(v: VirtualAxis, stack: Seq[VirtualAxis]): Boolean = - v match { - case v: WeakAxis => - val clazz = v.getClass - stack.contains(v) || !stack.exists(_.getClass == clazz) - case v: StrongAxis => - stack.contains(v) + def isMatch(lhs: Seq[VirtualAxis], rhs: Seq[VirtualAxis]): Boolean = + lhs.forall(isStronglyCompatible(_, rhs)) && rhs.forall(isStronglyCompatible(_, lhs)) + + private[sbt] def isStronglyCompatible(v: VirtualAxis, stack: Seq[VirtualAxis]): Boolean = + v match { + case v: WeakAxis => + val clazz = v.getClass + stack.contains(v) || !stack.exists(_.getClass == clazz) + case v: StrongAxis => + stack.contains(v) + } + + def isSecondaryMatch(lhs: Seq[VirtualAxis], rhs: Seq[VirtualAxis]): Boolean = + lhs.forall(isSecondaryCompatible(_, rhs)) && rhs.forall(isSecondaryCompatible(_, lhs)) + + def isSecondaryCompatible(v: VirtualAxis, stack: Seq[VirtualAxis]): Boolean = + v match { + case v: ScalaVersionAxis => + val thatSVOpt = (stack collect { + case x: ScalaVersionAxis => x + }).headOption + thatSVOpt match { + case Some(ScalaVersionAxis(sv, _)) => + (v.scalaVersion == sv) || + isScala2Scala3Sandwich(partialVersion(v.scalaVersion), partialVersion(sv)) + case _ => true + } + case _ => + isStronglyCompatible(v, stack) + } + + private[sbt] def isScala2Scala3Sandwich(sbv1: Option[(Long, Long)], sbv2: Option[(Long, Long)]): Boolean = { + def str(x: Option[(Long, Long)]): String = + x match { + case Some((a, b)) => s"$a.$b" + case _ => "0.0" } - lhs.forall(isCompatible(_, rhs)) && rhs.forall(isCompatible(_, lhs)) + isScala2Scala3Sandwich(str(sbv1), str(sbv2)) + } + + private[sbt] def isScala2Scala3Sandwich(sbv1: String, sbv2: String): Boolean = { + def compare(a: String, b: String): Boolean = + a == "2.13" && (b.startsWith("0.") || b.startsWith("3.0")) + compare(sbv1, sbv2) || compare(sbv2, sbv1) } case class ScalaVersionAxis(scalaVersion: String, value: String) extends WeakAxis { diff --git a/src/main/scala/sbt/internal/ProjectMatrix.scala b/src/main/scala/sbt/internal/ProjectMatrix.scala index d4e43afc2..50304ddff 100644 --- a/src/main/scala/sbt/internal/ProjectMatrix.scala +++ b/src/main/scala/sbt/internal/ProjectMatrix.scala @@ -163,6 +163,9 @@ object ProjectMatrix { def isMatch(that: ProjectRow): Boolean = VirtualAxis.isMatch(this.axisValues, that.axisValues) + def isSecondaryMatch(that: ProjectRow): Boolean = + VirtualAxis.isSecondaryMatch(this.axisValues, that.axisValues) + override def toString: String = s"ProjectRow($autoScalaLibrary, $axisValues)" } @@ -275,7 +278,8 @@ object ProjectMatrix { // resolve to the closest match for the given row private[sbt] def resolveMatch(thatRow: ProjectRow): ProjectReference = - rows.find(r => r.isMatch(thatRow)) match { + (rows.find(r => r.isMatch(thatRow)) orElse + rows.find(r => r.isSecondaryMatch(thatRow))) match { case Some(r) => LocalProject(resolveProjectIds(r)) case _ => sys.error(s"no rows were found in $id matching $thatRow: $rows") } diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/build.sbt b/src/sbt-test/projectMatrix/jvm-sandwich/build.sbt new file mode 100644 index 000000000..eb3fb0f85 --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/build.sbt @@ -0,0 +1,17 @@ +val dottyVersion = "0.23.0" +ThisBuild / resolvers += "scala-integration" at "https://scala-ci.typesafe.com/artifactory/scala-integration/" +// TODO use 2.13.4 when it's out +lazy val scala213 = "2.13.4-bin-aeee8f0" + +lazy val fooApp = (projectMatrix in file("foo-app")) + .dependsOn(fooCore) + .settings( + name := "app", + ) + .jvmPlatform(scalaVersions = Seq(dottyVersion)) + +lazy val fooCore = (projectMatrix in file("foo-core")) + .settings( + name := "core", + ) + .jvmPlatform(scalaVersions = Seq("2.13.3", "2.12.12")) diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/project/build.properties b/src/sbt-test/projectMatrix/jvm-sandwich/project/build.properties new file mode 100644 index 000000000..0837f7a13 --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.3.13 diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/project/plugins.sbt b/src/sbt-test/projectMatrix/jvm-sandwich/project/plugins.sbt new file mode 100644 index 000000000..c129c032b --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/project/plugins.sbt @@ -0,0 +1,6 @@ +sys.props.get("plugin.version") match { + case Some(x) => addSbtPlugin("com.eed3si9n" % "sbt-projectmatrix" % x) + case _ => sys.error("""|The system property 'plugin.version' is not defined. + |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) +} +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.4.1") diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/test b/src/sbt-test/projectMatrix/jvm-sandwich/test new file mode 100644 index 000000000..33560c709 --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/test @@ -0,0 +1,2 @@ +> fooAppJVM0_23/compile +