From 2c370fdc470236a39f543eba3a1cf94db7bf1742 Mon Sep 17 00:00:00 2001 From: Brice Jaglin Date: Sat, 9 Apr 2022 21:51:32 +0200 Subject: [PATCH] switch build to projectmatrix --- .github/workflows/ci.yml | 2 +- build.sbt | 114 +++++++++++++----- project/Dependencies.scala | 4 + project/ScalafixBuild.scala | 57 +++------ project/TargetAxis.scala | 49 ++++++++ project/plugins.sbt | 1 + .../{scala => scala-2}/test/PrettyTest.scala | 7 +- 7 files changed, 158 insertions(+), 76 deletions(-) create mode 100644 project/TargetAxis.scala rename scalafix-tests/shared/src/main/{scala => scala-2}/test/PrettyTest.scala (97%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a92b7bd703..d64a726606 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,4 +72,4 @@ jobs: - uses: actions/checkout@v3 - uses: olafurpg/setup-scala@v13 - run: git fetch --unshallow - - run: sbt +versionPolicyCheck + - run: sbt versionPolicyCheck diff --git a/build.sbt b/build.sbt index 56a0886e01..6447368583 100644 --- a/build.sbt +++ b/build.sbt @@ -4,8 +4,6 @@ import sbt.Keys.scalacOptions inThisBuild( List( onLoadMessage := s"Welcome to scalafix ${version.value}", - scalaVersion := scala213, - crossScalaVersions := List(scala213, scala212, scala211), fork := true, scalacOptions ++= List("-P:semanticdb:synthetics:on"), semanticdbEnabled := true, @@ -28,7 +26,7 @@ def inferJavaHome() = { Some(actualHome) } -lazy val interfaces = project +lazy val interfaces = projectMatrix .in(file("scalafix-interfaces")) .settings( Compile / resourceGenerators += Def.task { @@ -57,9 +55,11 @@ lazy val interfaces = project crossPaths := false, autoScalaLibrary := false ) + .defaultAxes(VirtualAxis.jvm) + .jvmPlatform(buildScalaVersions) .disablePlugins(ScalafixPlugin) -lazy val core = project +lazy val core = projectMatrix .in(file("scalafix-core")) .settings( moduleName := "scalafix-core", @@ -81,9 +81,11 @@ lazy val core = project ) } ) + .defaultAxes(VirtualAxis.jvm) + .jvmPlatform(buildScalaVersions) .enablePlugins(BuildInfoPlugin) -lazy val rules = project +lazy val rules = projectMatrix .in(file("scalafix-rules")) .settings( moduleName := "scalafix-rules", @@ -96,10 +98,12 @@ lazy val rules = project collectionCompat ) ) + .defaultAxes(VirtualAxis.jvm) + .jvmPlatform(buildScalaVersions) .dependsOn(core) .enablePlugins(BuildInfoPlugin) -lazy val reflect = project +lazy val reflect = projectMatrix .in(file("scalafix-reflect")) .settings( moduleName := "scalafix-reflect", @@ -109,9 +113,11 @@ lazy val reflect = project "org.scala-lang" % "scala-reflect" % scalaVersion.value ) ) + .defaultAxes(VirtualAxis.jvm) + .jvmPlatform(buildScalaVersions) .dependsOn(core) -lazy val cli = project +lazy val cli = projectMatrix .in(file("scalafix-cli")) .settings( moduleName := "scalafix-cli", @@ -123,21 +129,27 @@ lazy val cli = project commonText ) ) + .defaultAxes(VirtualAxis.jvm) + .jvmPlatform(buildScalaVersions) .dependsOn(reflect, interfaces, rules) -lazy val testsShared = project +lazy val testsShared = projectMatrix .in(file("scalafix-tests/shared")) .settings( noPublishAndNoMima, + scalacOptions --= (if (isScala3.value) + Seq("-P:semanticdb:synthetics:on") + else Nil), coverageEnabled := false ) + .defaultAxes(VirtualAxis.jvm) + .jvmPlatform(testTargetScalaVersions) .disablePlugins(ScalafixPlugin) -lazy val testsInput = project +lazy val testsInput = projectMatrix .in(file("scalafix-tests/input")) .settings( noPublishAndNoMima, - crossScalaVersions := List(scala3, scala213, scala212, scala211), scalacOptions --= (if (isScala3.value) Seq("-P:semanticdb:synthetics:on") else Nil), @@ -149,9 +161,11 @@ lazy val testsInput = project libraryDependencies ++= testsDependencies.value, coverageEnabled := false ) + .defaultAxes(VirtualAxis.jvm) + .jvmPlatform(testTargetScalaVersions) .disablePlugins(ScalafixPlugin) -lazy val testsOutput = project +lazy val testsOutput = projectMatrix .in(file("scalafix-tests/output")) .settings( noPublishAndNoMima, @@ -162,9 +176,11 @@ lazy val testsOutput = project libraryDependencies ++= testsDependencies.value, coverageEnabled := false ) + .defaultAxes(VirtualAxis.jvm) + .jvmPlatform(testTargetScalaVersions) .disablePlugins(ScalafixPlugin) -lazy val testkit = project +lazy val testkit = projectMatrix .in(file("scalafix-testkit")) .settings( moduleName := "scalafix-testkit", @@ -174,9 +190,11 @@ lazy val testkit = project scalatest ) ) + .defaultAxes(VirtualAxis.jvm) + .jvmPlatform(buildScalaVersions) .dependsOn(cli) -lazy val unit = project +lazy val unit = projectMatrix .in(file("scalafix-tests/unit")) .settings( noPublishAndNoMima, @@ -197,9 +215,9 @@ lazy val unit = project Compile / compile / compileInputs := { (Compile / compile / compileInputs) .dependsOn( - testsInput / Compile / compile, - testsOutput / Compile / compile, - testsShared / Compile / compile + TargetAxis.resolve(testsInput, Compile / compile), + TargetAxis.resolve(testsOutput, Compile / compile), + TargetAxis.resolve(testsShared, Compile / compile) ) .value }, @@ -214,20 +232,29 @@ lazy val unit = project } put( "inputClasspath", - (testsInput / Compile / fullClasspath).value.map(_.data) + TargetAxis + .resolve(testsInput, Compile / fullClasspath) + .value + .map(_.data) ) put( "inputSourceDirectories", - (testsInput / Compile / sourceDirectories).value + TargetAxis.resolve(testsInput, Compile / sourceDirectories).value ) put( "outputSourceDirectories", - (testsOutput / Compile / sourceDirectories).value + TargetAxis.resolve(testsOutput, Compile / sourceDirectories).value + ) + props.put( + "scalaVersion", + TargetAxis.resolve(testsInput, Compile / scalaVersion).value ) - props.put("scalaVersion", (testsInput / Compile / scalaVersion).value) props.put( "scalacOptions", - (testsInput / Compile / scalacOptions).value.mkString("|") + TargetAxis + .resolve(testsInput, Compile / scalacOptions) + .value + .mkString("|") ) val out = (Test / managedResourceDirectories).value.head / @@ -240,44 +267,69 @@ lazy val unit = project "baseDirectory" -> (ThisBuild / baseDirectory).value, "inputSourceroot" -> - (testsInput / Compile / sourceDirectory).value, + TargetAxis.resolve(testsInput, Compile / sourceDirectory).value, "outputSourceroot" -> - (testsOutput / Compile / sourceDirectory).value, + TargetAxis.resolve(testsOutput, Compile / sourceDirectory).value, "unitResourceDirectory" -> (Compile / resourceDirectory).value, "testsInputResources" -> - (testsInput / Compile / sourceDirectory).value / "resources", + TargetAxis + .resolve(testsInput, Compile / sourceDirectory) + .value / "resources", "semanticClasspath" -> Seq( - (testsInput / Compile / semanticdbTargetRoot).value, - (testsShared / Compile / semanticdbTargetRoot).value + TargetAxis.resolve(testsInput, Compile / semanticdbTargetRoot).value, + TargetAxis.resolve(testsShared, Compile / semanticdbTargetRoot).value ), "sharedSourceroot" -> (ThisBuild / baseDirectory).value / "scalafix-tests" / "shared" / "src" / "main", "sharedClasspath" -> - (testsShared / Compile / classDirectory).value + TargetAxis.resolve(testsShared, Compile / classDirectory).value ), Test / test := (Test / test) - .dependsOn(cli / crossPublishLocalBinTransitive) + .dependsOn(cli.finder().get.map(_ / publishLocalTransitive): _*) .value ) + .defaultAxes( + buildScalaVersions.map(VirtualAxis.scalaABIVersion) :+ VirtualAxis.jvm: _* + ) + .customRow( + scalaVersions = Seq(scala212), + axisValues = Seq(TargetAxis(scala3), VirtualAxis.jvm), + settings = Seq() + ) + .customRow( + scalaVersions = Seq(scala213), + axisValues = Seq(TargetAxis(scala213), VirtualAxis.jvm), + settings = Seq() + ) + .customRow( + scalaVersions = Seq(scala212), + axisValues = Seq(TargetAxis(scala212), VirtualAxis.jvm), + settings = Seq() + ) + .customRow( + scalaVersions = Seq(scala211), + axisValues = Seq(TargetAxis(scala211), VirtualAxis.jvm), + settings = Seq() + ) .enablePlugins(BuildInfoPlugin) .dependsOn(testkit) -lazy val docs = project +lazy val docs = projectMatrix .in(file("scalafix-docs")) .settings( noPublishAndNoMima, run / baseDirectory := (ThisBuild / baseDirectory).value, moduleName := "scalafix-docs", - scalaVersion := scala213, scalacOptions += "-Wconf:msg='match may not be exhaustive':s", // silence exhaustive pattern matching warning for documentation scalacOptions += "-Xfatal-warnings", mdoc := (Compile / run).evaluated, - crossScalaVersions := List(scala213), libraryDependencies += (if (isScala211.value) metaconfigDocFor211 else metaconfigDoc) ) + .defaultAxes(VirtualAxis.jvm) + .jvmPlatform(scalaVersions = Seq(scala213)) .dependsOn(testkit, core, cli) .enablePlugins(DocusaurusPlugin) .disablePlugins(ScalafixPlugin) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index cb43fe3374..974c586627 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -11,6 +11,10 @@ object Dependencies { val scala212 = "2.12.15" val scala213 = "2.13.8" val scala3 = "3.1.1" + + val buildScalaVersions = Seq(scala211, scala212, scala213) + val testTargetScalaVersions = Seq(scala211, scala212, scala213, scala3) + // we support 3 last binary versions of scala212 and scala213 val testedPreviousScalaVersions: Map[String, List[String]] = List(scala213, scala212).map(version => version -> previousVersions(version)).toMap diff --git a/project/ScalafixBuild.scala b/project/ScalafixBuild.scala index fa8e0535e4..06ded91001 100644 --- a/project/ScalafixBuild.scala +++ b/project/ScalafixBuild.scala @@ -25,9 +25,6 @@ object ScalafixBuild extends AutoPlugin with GhpagesKeys { lazy val supportedScalaVersions = List(scala213, scala211, scala212) lazy val publishLocalTransitive = taskKey[Unit]("Run publishLocal on this project and its dependencies") - lazy val crossPublishLocalBinTransitive = taskKey[Unit]( - "Run, for each crossVersion, publishLocal without packageDoc & packageSrc, on this project and its dependencies" - ) lazy val isFullCrossVersion = Seq( crossVersion := CrossVersion.full ) @@ -127,35 +124,29 @@ object ScalafixBuild extends AutoPlugin with GhpagesKeys { updateOptions := updateOptions.value.withCachedResolution(true), ThisBuild / watchTriggeredMessage := Watch.clearScreenOnTrigger, commands += Command.command("save-expect") { s => - "unit/test:runMain scalafix.tests.util.SaveExpect" :: + "unitTarget2_13/test:runMain scalafix.tests.util.SaveExpect" :: s }, commands += Command.command("ci-3") { s => - s"""set testsInput/scalaVersion := "$scala3"""" :: - s"""set testsOutput/scalaVersion := "$scala3"""" :: - "unit/testOnly scalafix.tests.rule.RuleSuite" :: s + "unitTarget3/test" :: s }, commands += Command.command("ci-213") { s => - s"""set ThisBuild/scalaVersion := "$scala213"""" :: - "unit/test" :: - "docs/run" :: - "interfaces/doc" :: + "unitTarget2_13/test" :: + "docs2_13/run" :: + "interfaces2_13/doc" :: testRulesAgainstPreviousScalaVersions(scala213, s) }, commands += Command.command("ci-212") { s => - s"""set ThisBuild/scalaVersion := "$scala212"""" :: - "unit/test" :: + "unitTarget2_12/test" :: testRulesAgainstPreviousScalaVersions(scala212, s) }, commands += Command.command("ci-211") { s => - s"""set ThisBuild/scalaVersion := "$scala211"""" :: - "unit/test" :: + "unitTarget2_11/test" :: testRulesAgainstPreviousScalaVersions(scala211, s) }, commands += Command.command("ci-213-windows") { s => - s"++$scala213" :: - "cli/crossPublishLocalBinTransitive" :: // scalafix.tests.interfaces.ScalafixSuite - s"unit/testOnly -- -l scalafix.internal.tests.utils.SkipWindows" :: + "cli2_13/crossPublishLocalBinTransitive" :: // scalafix.tests.interfaces.ScalafixSuite + s"unitTarget2_13/testOnly -- -l scalafix.internal.tests.utils.SkipWindows" :: s }, // There is flakyness in CliGitDiffTests and CliSemanticTests @@ -188,10 +179,13 @@ object ScalafixBuild extends AutoPlugin with GhpagesKeys { Compile / doc / scalacOptions ++= scaladocOptions, Compile / unmanagedSourceDirectories ++= { val sourceDir = (Compile / sourceDirectory).value - CrossVersion.partialVersion(scalaVersion.value) match { + (CrossVersion.partialVersion(scalaVersion.value) match { case Some((2, n)) if n >= 12 => Seq(sourceDir / "scala-2.12+") case _ => Seq() - } + }) ++ (CrossVersion.partialVersion(scalaVersion.value) match { + case Some((2, _)) => Seq(sourceDir / "scala-2") + case _ => Seq() + }) }, publishTo := Some { if (isSnapshot.value) Opts.resolver.sonatypeSnapshots @@ -227,28 +221,9 @@ object ScalafixBuild extends AutoPlugin with GhpagesKeys { publishLocalTransitive := Def.taskDyn { val ref = thisProjectRef.value publishLocal.all(ScopeFilter(inDependencies(ref))) - }.value, - crossPublishLocalBinTransitive := { - val currentState = state.value - val ref = thisProjectRef.value - val versions = crossScalaVersions.value - versions.map { version => - val withScalaVersion = Project - .extract(currentState) - .appendWithoutSession( - Seq( - ThisBuild / scalaVersion := version, - ThisBuild / packageDoc / publishArtifact := false, - ThisBuild / packageSrc / publishArtifact := false - ), - currentState - ) - Project - .extract(withScalaVersion) - .runTask(ref / publishLocalTransitive, withScalaVersion) - } - } + }.value ) + // TODO private def testRulesAgainstPreviousScalaVersions( scalaVersion: String, state: State diff --git a/project/TargetAxis.scala b/project/TargetAxis.scala new file mode 100644 index 0000000000..e5799cc1a4 --- /dev/null +++ b/project/TargetAxis.scala @@ -0,0 +1,49 @@ +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 { + + private val scalaBinaryVersion = CrossVersion.binaryScalaVersion(scalaVersion) + + override val idSuffix = s"Target${scalaBinaryVersion.replace('.', '_')}" + override val directorySuffix = s"target$scalaBinaryVersion" +} + +object TargetAxis { + + private def targetScalaVersion(virtualAxes: Seq[VirtualAxis]): String = + virtualAxes.collectFirst { case a: TargetAxis => a.scalaVersion }.get + + /** + * 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`. + */ + def resolve[T]( + matrix: ProjectMatrix, + key: TaskKey[T] + ): Def.Initialize[Task[T]] = + Def.taskDyn { + val sv = targetScalaVersion(virtualAxes.value) + val project = matrix.finder().apply(sv) + 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`. + */ + def resolve[T]( + matrix: ProjectMatrix, + key: SettingKey[T] + ): Def.Initialize[T] = + Def.settingDyn { + val sv = targetScalaVersion(virtualAxes.value) + val project = matrix.finder().apply(sv) + Def.setting((project / key).value) + } + +} diff --git a/project/plugins.sbt b/project/plugins.sbt index 94a932c793..d2ba68e869 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,3 +5,4 @@ addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "2.0.1") addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.3.2") addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.9.3") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.34") +addSbtPlugin("com.eed3si9n" % "sbt-projectmatrix" % "0.9.0") diff --git a/scalafix-tests/shared/src/main/scala/test/PrettyTest.scala b/scalafix-tests/shared/src/main/scala-2/test/PrettyTest.scala similarity index 97% rename from scalafix-tests/shared/src/main/scala/test/PrettyTest.scala rename to scalafix-tests/shared/src/main/scala-2/test/PrettyTest.scala index a0465b6fbf..44e477cacb 100644 --- a/scalafix-tests/shared/src/main/scala/test/PrettyTest.scala +++ b/scalafix-tests/shared/src/main/scala-2/test/PrettyTest.scala @@ -22,9 +22,10 @@ class PrettyTest { val b = new a.Inner Option(null.asInstanceOf[{ - def bar(a: Int): Int - def foo(a: Int): Int - }]) + def bar(a: Int): Int + def foo(a: Int): Int + } + ]) Option(b) Option(null.asInstanceOf[Int with String]) Option(null.asInstanceOf[this.type])