diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bfaaa56456..53cc7d3e4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,13 @@ jobs: - uses: actions/checkout@v2 - uses: olafurpg/setup-scala@v7 - run: sbt ${{ matrix.command }} + ci-explicit-result-types-test: + name: ci-explicit-result-types-rule tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: olafurpg/setup-scala@v7 + - run: sbt ci-explicit-result-types-rule jdk11_212: name: JDK11/scala_2.12 tests runs-on: ubuntu-latest diff --git a/build.sbt b/build.sbt index ba27446643..542ee91a04 100644 --- a/build.sbt +++ b/build.sbt @@ -217,8 +217,11 @@ lazy val unit = project "outputSourceDirectories", sourceDirectories.in(testsOutput, Compile).value ) - props.put("scalaVersion", scalaVersion.value) - props.put("scalacOptions", scalacOptions.value.mkString("|")) + props.put("scalaVersion", scalaVersion.in(testsInput, Compile).value) + props.put( + "scalacOptions", + scalacOptions.in(testsInput, Compile).value.mkString("|") + ) val out = managedResourceDirectories.in(Test).value.head / "scalafix-testkit.properties" diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 8640e6047f..45aac7e698 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -1,4 +1,6 @@ import sbt._ + +import scala.util.{Properties, Try} /* scalafmt: { maxColumn = 120 }*/ object Dependencies { @@ -11,6 +13,10 @@ object Dependencies { def coursierV = "2.0.0-RC5-6" def coursierInterfaceV = "0.0.22" val currentScalaVersion = scala213 + // we support 3 last binary versions of each scala Version, except for 2.11 because semanticdb-scalac_2.11.10 is missing. + val supportedScalaVersionforExplicitResultRule = + List(scala213, scala212).map(version => version -> supportedScalaVersions(version)).toMap ++ + Map(scala211 -> List(scala211)) val jgit = "org.eclipse.jgit" % "org.eclipse.jgit" % "5.7.0.202003110725-r" @@ -36,4 +42,13 @@ object Dependencies { "com.chuusai" %% "shapeless" % "2.3.3", scalacheck ) + + private def supportedScalaVersions(scalaVersion: String): List[String] = { + val split = scalaVersion.split('.') + val binaryVersion = split.take(2).mkString(".") + val compilerVersion = Try(split.last.toInt).toOption + val supportedVersions = + compilerVersion.map(version => List.range(version - 2, version + 1).filter(_ >= 0)).getOrElse(Nil) + supportedVersions.map(v => s"$binaryVersion.$v") + } } diff --git a/project/ScalafixBuild.scala b/project/ScalafixBuild.scala index 596b33beed..73ea0d8864 100644 --- a/project/ScalafixBuild.scala +++ b/project/ScalafixBuild.scala @@ -67,6 +67,7 @@ object ScalafixBuild extends AutoPlugin with GhpagesKeys { "scalameta" -> scalametaV, scalaVersion, "supportedScalaVersions" -> supportedScalaVersions, + "supportedScalaVersionsForExplicitResultTypeRule" -> supportedScalaVersionforExplicitResultRule, "scala211" -> scala211, "scala212" -> scala212, "scala213" -> scala213, @@ -212,6 +213,21 @@ object ScalafixBuild extends AutoPlugin with GhpagesKeys { s"unit/testOnly -- -l scalafix.internal.tests.utils.SkipWindows" :: s }, + commands += Command.command("ci-explicit-result-types-rule") { s => + supportedScalaVersionforExplicitResultRule + .flatMap { + case (k, versions) => + versions.flatMap { v => + List( + s"""set ThisBuild/scalaVersion := "$k"""", + s"""set testsInput/scalaVersion := "$v"""", + s"""set testsOutput/scalaVersion := "$v\"""", + s"unit/testOnly scalafix.tests.rule.RuleSuite -- -z explicitResult" + ) + } + } + .foldRight(s)(_ :: _) + }, commands += Command.command("mima") { s => // Disabled until v0.6.0 stable // "scalafix/mimaReportBinaryIssues" :: diff --git a/scalafix-rules/src/main/scala/scalafix/internal/rule/ExplicitResultTypes.scala b/scalafix-rules/src/main/scala/scalafix/internal/rule/ExplicitResultTypes.scala index 8d809af71d..d098091419 100644 --- a/scalafix-rules/src/main/scala/scalafix/internal/rule/ExplicitResultTypes.scala +++ b/scalafix-rules/src/main/scala/scalafix/internal/rule/ExplicitResultTypes.scala @@ -6,10 +6,12 @@ import scalafix.patch.Patch import scalafix.v1._ import scalafix.util.TokenOps import metaconfig.Configured + import scala.meta.internal.pc.ScalafixGlobal import scalafix.internal.v1.LazyValue + import scala.util.control.NonFatal -import scala.util.Properties +import scala.util.{Properties, Try} import scalafix.internal.compat.CompilerCompat._ final class ExplicitResultTypes( @@ -19,10 +21,20 @@ final class ExplicitResultTypes( def this() = this(ExplicitResultTypesConfig.default, LazyValue.now(None)) - private def supportedScalaVersion = Properties.versionNumberString + private def supportedScalaVersions: List[String] = { + val scalaVersion = Properties.versionNumberString + val split = scalaVersion.split('.') + val binaryVersion = split.take(2).mkString(".") + val compilerVersion = Try(split.last.toInt).toOption + val supportedVersions = compilerVersion + .map(version => List.range(version - 2, version + 1).filter(_ >= 0)) + .getOrElse(Nil) + supportedVersions.map(v => s"$binaryVersion.$v") + } + override def description: String = "Inserts type annotations for inferred public members. " + - s"Only compatible with Scala $supportedScalaVersion." + s"Only compatible with Scala $supportedScalaVersions." override def isRewrite: Boolean = true override def afterComplete(): Unit = { @@ -57,11 +69,21 @@ final class ExplicitResultTypes( ) } } - if (config.scalacClasspath.nonEmpty && config.scalaVersion != supportedScalaVersion) { + if (config.scalacClasspath.nonEmpty && !supportedScalaVersions.contains( + config.scalaVersion + )) { + val shortScalaVersion = + config.scalaVersion.split(".").take(2).mkString(".") + val shortRuleScalaVersion = + Properties.versionNumberString.split(".").take(2).mkString(".") Configured.error( - s"The ExplicitResultTypes rule only supports the Scala version '$supportedScalaVersion'. " + - s"To fix this problem, either remove `ExplicitResultTypes` from .scalafix.conf or change the Scala version " + - s"in your build to match exactly '$supportedScalaVersion'." + s"Your scalaVersion is ${config.scalaVersion} but the ExplicitResultTypes rule is compiled with ${shortRuleScalaVersion}" + + s"and only supports these Scala versions '$supportedScalaVersions'. " + + (if (shortScalaVersion == shortRuleScalaVersion) + s"To fix this problem, either remove `ExplicitResultTypes` from .scalafix.conf or change the Scala version to be within '$supportedScalaVersions'" + else + s"To fix this problem, either remove `ExplicitResultTypes` from .scalafix.conf or " + + s"specify a `scalafixScalaBinaryVersion` key in your build.sbt equal to $shortScalaVersion") ) } else { config.conf // Support deprecated explicitReturnTypes config