From bfe0624b6e3e59c8eaca8670db9b7492e2a8f1ed Mon Sep 17 00:00:00 2001 From: Brice Jaglin Date: Sat, 10 Sep 2022 21:52:35 +0200 Subject: [PATCH] add support for -Xsource:3 testkit input & output Also rework the unit matrix to distinguish projects where we run all tests against the same version as the build version (now without suffix), from the extra ones where we are just interested in the testkit tests (since integration tests have been covered by the other projects). --- CONTRIBUTING.md | 8 ++-- build.sbt | 77 +++++++++++++++++++++++-------------- project/ScalafixBuild.scala | 20 +++++++--- project/TargetAxis.scala | 75 ++++++++++++++++++++++++++++-------- 4 files changed, 125 insertions(+), 55 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6a56731b9..4e673aa15 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,7 +19,7 @@ hesitate to ask in the [Discord channel](https://discord.gg/8AHaqGx3Qj). The project should import normally into IntelliJ and there should not be any false red squiggles. To use the debugger or run tests from within IntelliJ, run -at least once `sbt unit2_13Target2_13/test` to generate a `BuildInfo` file and +at least once `sbt unit2_13/test` to generate a `BuildInfo` file and property files for Scalafix testkit. ## Testing @@ -30,13 +30,13 @@ sbt shell. ```sh # Fast unit tests for rules, cli, core. Contains a lot # of different test suites, so it's recommended to use testOnly. -> unit2_13Target2_13/test +> unit2_13/test # Only run tests for rules, using scalafix-testkit. -> unit2_13Target2_13/testOnly *RuleSuite +> unit2_13/testOnly *RuleSuite # Only run only ProcedureSyntax unit test. -> unit2_13Target2_13/testOnly *RuleSuite -- -z ProcedureSyntax +> unit2_13/testOnly *RuleSuite -- -z ProcedureSyntax ``` [sbt-projectmatrix](https://github.com/sbt/sbt-projectmatrix) is used to diff --git a/build.sbt b/build.sbt index 58a2096d7..f54956bb7 100644 --- a/build.sbt +++ b/build.sbt @@ -177,6 +177,11 @@ lazy val testsInput = projectMatrix ) .defaultAxes(VirtualAxis.jvm) .jvmPlatform(testTargetScalaVersions) + .jvmPlatform( + scalaVersions = Seq(scala212, scala213), + axisValues = Seq(Xsource3Axis), + settings = xsource3 + ) .disablePlugins(ScalafixPlugin) lazy val testsOutput = projectMatrix @@ -189,6 +194,11 @@ lazy val testsOutput = projectMatrix ) .defaultAxes(VirtualAxis.jvm) .jvmPlatform(testTargetScalaVersions) + .jvmPlatform( + scalaVersions = Seq(scala212, scala213), + axisValues = Seq(Xsource3Axis), + settings = xsource3 + ) .disablePlugins(ScalafixPlugin) lazy val testkit = projectMatrix @@ -292,46 +302,55 @@ lazy val unit = projectMatrix "scalafix-tests" / "shared" / "src" / "main", "sharedClasspath" -> TargetAxis.resolve(testsShared, Compile / classDirectory).value - ), - Test / test := (Test / test) - .dependsOn(cli.projectRefs.map(_ / publishLocalTransitive): _*) - .value, - Test / unmanagedSourceDirectories ++= { - val sourceDir = (Test / sourceDirectory).value - val maybeTargetScalaVersion = - TargetAxis - .targetScalaVersion(virtualAxes.value) - .flatMap(CrossVersion.partialVersion(_)) - maybeTargetScalaVersion match { - case Some((n, m)) => - Seq( - sourceDir / s"scala-target$n", - sourceDir / s"scala-target$n.$m" - ) - case _ => Seq() - } - } + ) ) .defaultAxes(VirtualAxis.jvm) + // testkit & integration tests + .jvmPlatform( + scalaVersions = buildScalaVersions, + settings = Seq( + Test / test := (Test / test) + .dependsOn(cli.projectRefs.map(_ / publishLocalTransitive): _*) + .value, + Test / unmanagedSourceDirectories ++= { + val sourceDir = (Test / sourceDirectory).value + val targetScalaVersion = + TargetAxis.targetAxis(virtualAxes.value).scalaVersion + val (n, m) = CrossVersion.partialVersion(targetScalaVersion).get + Seq( + sourceDir / s"scala-target$n", + sourceDir / s"scala-target$n.$m" + ) + } + ) + ) + // testkit only .jvmPlatform( scalaVersions = Seq(scala212), axisValues = Seq(TargetAxis(scala3)), - settings = Seq() + settings = Seq( + Test / test := (Test / testOnly) + .toTask(" scalafix.tests.rule.RuleSuite") + .value + ) ) .jvmPlatform( scalaVersions = Seq(scala213), - axisValues = Seq(TargetAxis(scala213)), - settings = Seq() + axisValues = Seq(TargetAxis(scala213, xsource3 = true)), + settings = Seq( + Test / test := (Test / testOnly) + .toTask(" scalafix.tests.rule.RuleSuite") + .value + ) ) .jvmPlatform( scalaVersions = Seq(scala212), - axisValues = Seq(TargetAxis(scala212)), - settings = Seq() - ) - .jvmPlatform( - scalaVersions = Seq(scala211), - axisValues = Seq(TargetAxis(scala211)), - settings = Seq() + axisValues = Seq(TargetAxis(scala212, xsource3 = true)), + settings = Seq( + Test / test := (Test / testOnly) + .toTask(" scalafix.tests.rule.RuleSuite") + .value + ) ) .enablePlugins(BuildInfoPlugin) .dependsOn(testkit) diff --git a/project/ScalafixBuild.scala b/project/ScalafixBuild.scala index 07c372022..742994030 100644 --- a/project/ScalafixBuild.scala +++ b/project/ScalafixBuild.scala @@ -68,6 +68,12 @@ object ScalafixBuild extends AutoPlugin with GhpagesKeys { "-groups", "-implicits" ) + lazy val xsource3 = Seq( + scalacOptions += "-Xsource:3", + Compile / unmanagedSourceDirectories := + ((Compile / sourceDirectory).value * "*xsource3").get + ) + lazy val testsDependencies = Def.setting { val xmlLib = if (isScala211.value) scalaXml211 else scalaXml val otherLibs = @@ -140,7 +146,7 @@ object ScalafixBuild extends AutoPlugin with GhpagesKeys { updateOptions := updateOptions.value.withCachedResolution(true), ThisBuild / watchTriggeredMessage := Watch.clearScreenOnTrigger, commands += Command.command("save-expect") { s => - "unit2_13Target2_13/test:runMain scalafix.tests.util.SaveExpect" :: + "unit2_13/test:runMain scalafix.tests.util.SaveExpect" :: s }, commands += Command.command("ci-3") { s => @@ -150,22 +156,24 @@ object ScalafixBuild extends AutoPlugin with GhpagesKeys { s }, commands += Command.command("ci-213") { s => - "unit2_13Target2_13/test" :: + "unit2_13/test" :: + "unit2_13Target2_13xsource3/test" :: "docs2_13/run" :: "interfaces/doc" :: testRulesAgainstPreviousScalaVersions(scala213, s) }, commands += Command.command("ci-212") { s => - "unit2_12Target2_12/test" :: + "unit2_12/test" :: + "unit2_12Target2_12xsource3/test" :: testRulesAgainstPreviousScalaVersions(scala212, s) }, commands += Command.command("ci-211") { s => - "unit2_11Target2_11/test" :: + "unit2_11/test" :: testRulesAgainstPreviousScalaVersions(scala211, s) }, commands += Command.command("ci-213-windows") { s => "publishLocalTransitive" :: // scalafix.tests.interfaces.ScalafixSuite - s"unit2_13Target2_13/testOnly -- -l scalafix.internal.tests.utils.SkipWindows" :: + s"unit2_13/testOnly -- -l scalafix.internal.tests.utils.SkipWindows" :: s }, // There is flakyness in CliGitDiffTests and CliSemanticTests @@ -274,7 +282,7 @@ object ScalafixBuild extends AutoPlugin with GhpagesKeys { List( s"""set Project("testsInput${projectSuffix}", file(".")) / scalaVersion := "$v"""", s"show testsInput${projectSuffix} / scalaVersion", - s"unit${projectSuffix}Target${projectSuffix} / testOnly scalafix.tests.rule.RuleSuite" + s"unit${projectSuffix} / testOnly scalafix.tests.rule.RuleSuite" ) } .foldRight(state)(_ :: _) diff --git a/project/TargetAxis.scala b/project/TargetAxis.scala index 753c6160f..9b6480506 100644 --- a/project/TargetAxis.scala +++ b/project/TargetAxis.scala @@ -2,48 +2,91 @@ import sbt._ import sbt.internal.ProjectMatrix import sbtprojectmatrix.ProjectMatrixPlugin.autoImport._ -/** Use on ProjectMatrix rows to tag an affinity to a custom scalaVersion */ -case class TargetAxis(scalaVersion: String) extends VirtualAxis.WeakAxis { +/** + * Use on ProjectMatrix rows to tag an affinity to a custom scalaVersion with or + * without "-Xsource:3" + */ +case class TargetAxis(scalaVersion: String, xsource3: Boolean = false) + extends VirtualAxis.WeakAxis { private val scalaBinaryVersion = CrossVersion.binaryScalaVersion(scalaVersion) + private val maybeSource3 = if (xsource3) "xsource3" else "" - override val idSuffix = s"Target${scalaBinaryVersion.replace('.', '_')}" - override val directorySuffix = s"target$scalaBinaryVersion" + override val idSuffix = + s"Target${scalaBinaryVersion.replace('.', '_')}$maybeSource3" + override val directorySuffix = s"target$scalaBinaryVersion$maybeSource3" + override val suffixOrder = VirtualAxis.scalaABIVersion("any").suffixOrder + 1 +} + +/** Use on ProjectMatrix rows to mark usage of "-Xsource:3" */ +case object Xsource3Axis extends VirtualAxis.WeakAxis { + override val idSuffix = "Xsource3" + override val directorySuffix = "xsource3" override val suffixOrder = VirtualAxis.scalaABIVersion("any").suffixOrder + 1 } object TargetAxis { - def targetScalaVersion(virtualAxes: Seq[VirtualAxis]): Option[String] = - virtualAxes.collectFirst { case a: TargetAxis => a.scalaVersion } + def targetAxis(virtualAxes: Seq[VirtualAxis]): TargetAxis = { + val explicitTargetAxis = + virtualAxes.collectFirst { case a: TargetAxis => a } + val scalaVersion = + virtualAxes.collectFirst { case a: VirtualAxis.ScalaVersionAxis => + a.scalaVersion + } + + explicitTargetAxis.getOrElse(TargetAxis(scalaVersion.get)) + } + + /** + * Find a project in the provided matrix, matching the scalaVersion in the + * target axis (or the version of the project if no target axis was set). If + * the target axis requests xsource3 and a project tagged with Xsource3Axis + * exists, favor this one. + */ + private def lookup( + matrix: ProjectMatrix, + virtualAxes: Seq[VirtualAxis] + ): Project = { + val TargetAxis(sv, xsource3) = targetAxis(virtualAxes) + + def maybeXsource3Project = + matrix + .finder(VirtualAxis.scalaABIVersion(sv), Xsource3Axis) + .get + .headOption + def nonXsource3Project = + matrix.finder(VirtualAxis.scalaABIVersion(sv)).get.head + + if (xsource3) maybeXsource3Project.getOrElse(nonXsource3Project) + else nonXsource3Project + } /** - * When invoked on a ProjectMatrix with a TargetAxis, lookup the project - * generated by `matrix` with a scalaVersion matching the one declared in that - * TargetAxis, and resolve `key`. + * Lookup the project generated by `matrix` with a scalaVersion matching the + * one declared in the TargetAxis (or the scalaVersion of the current project + * if no TargetAxis is defined on it), and resolve `key`. */ def resolve[T]( matrix: ProjectMatrix, key: TaskKey[T] ): Def.Initialize[Task[T]] = Def.taskDyn { - val sv = targetScalaVersion(virtualAxes.value).get - val project = matrix.finder().apply(sv) + val project = lookup(matrix, virtualAxes.value) Def.task((project / key).value) } /** - * When invoked on a ProjectMatrix with a TargetAxis, lookup the project - * generated by `matrix` with a scalaVersion matching the one declared in that - * TargetAxis, and resolve `key`. + * Lookup the project generated by `matrix` with a scalaVersion matching the + * one declared in the TargetAxis (or the scalaVersion of the current project + * if no TargetAxis is defined on it), and resolve `key`. */ def resolve[T]( matrix: ProjectMatrix, key: SettingKey[T] ): Def.Initialize[T] = Def.settingDyn { - val sv = targetScalaVersion(virtualAxes.value).get - val project = matrix.finder().apply(sv) + val project = lookup(matrix, virtualAxes.value) Def.setting((project / key).value) }