Skip to content

Commit

Permalink
add support for -Xsource:3 testkit input & output
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
bjaglin committed Sep 10, 2022
1 parent 36e89d2 commit bfe0624
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 55 deletions.
8 changes: 4 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
77 changes: 48 additions & 29 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down
20 changes: 14 additions & 6 deletions project/ScalafixBuild.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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 =>
Expand All @@ -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
Expand Down Expand Up @@ -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)(_ :: _)
Expand Down
75 changes: 59 additions & 16 deletions project/TargetAxis.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down

0 comments on commit bfe0624

Please sign in to comment.