diff --git a/.scala-steward.conf b/.scala-steward.conf index 11d021e2..daf01b70 100644 --- a/.scala-steward.conf +++ b/.scala-steward.conf @@ -6,3 +6,10 @@ updates.pin = [ # JGit 6.x requires Java 11, see https://www.eclipse.org/lists/cross-project-issues-dev/msg18654.html { groupId = "org.eclipse.jgit", artifactId = "org.eclipse.jgit", version = "5." }, ] + +dependencyOverrides = [ + { + dependency = { groupId = "ch.epfl.scala", artifactId = "scalafix-interfaces" }, + pullRequests = { frequency = "@asap" }, + }, +] \ No newline at end of file diff --git a/build.sbt b/build.sbt index dd58d66a..328a51ec 100644 --- a/build.sbt +++ b/build.sbt @@ -101,5 +101,6 @@ scriptedParallelInstances := 2 scriptedLaunchOpts ++= Seq( "-Xmx2048M", s"-Dplugin.version=${version.value}", + s"-Dscalafix-interfaces.version=${Dependencies.scalafixInterfacesVersion}", "-Dsbt-scalafix.uselastmodified=true" // the caching scripted relies on sbt-scalafix only checking file attributes, not content ) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 76b5fb81..cd15eb28 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -2,11 +2,16 @@ import sbt._ object Dependencies { val x = List(1) // scalafix:ok - def scalafixVersion: String = "0.14.2" + + // keep this as low as possible, to allow bumping sbt-scalafix without scalafix-interfaces + def scalafixInterfacesVersion: String = + "0.14.2+48-9b6e03ac-SNAPSHOT" // scala-steward:off val all = List( + "ch.epfl.scala" % "scalafix-interfaces" % scalafixInterfacesVersion + exclude ("ch.epfl.scala", "scalafix-properties"), + "ch.epfl.scala" % "scalafix-interfaces" % scalafixInterfacesVersion % Test, "org.eclipse.jgit" % "org.eclipse.jgit" % "5.13.3.202401111512-r", - "ch.epfl.scala" % "scalafix-interfaces" % scalafixVersion, "io.get-coursier" % "interface" % "1.0.28", "org.scala-lang.modules" %% "scala-collection-compat" % "2.13.0" ) diff --git a/project/plugins.sbt b/project/plugins.sbt index 81f88620..48b6ea92 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -10,3 +10,6 @@ Compile / unmanagedSourceDirectories ++= { ) } libraryDependencies ++= Dependencies.all + +// latest version of interfaces to test compatibility & get most recent behavior for scalafix invocations +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % "0.14.2" diff --git a/readme.md b/readme.md index 5751e134..10c47574 100644 --- a/readme.md +++ b/readme.md @@ -12,14 +12,18 @@ https://github.com/scalacenter/scalafix/issues ## Nightlies -Our CI publishes a [snapshot release to Sonatype](https://oss.sonatype.org/content/repositories/snapshots/ch/epfl/scala/sbt-scalafix_2.12_1.0/) -on every merge into main. The latest snapshot at the time of the writing can be used via: +Our CI publishes a snapshot release to Sonatype on every merge into main. The latest snapshot(s) of +[the plugin](https://oss.sonatype.org/content/repositories/snapshots/ch/epfl/scala/sbt-scalafix_2.12_1.0/) +and/or [scalafix-interfaces](https://oss.sonatype.org/content/repositories/snapshots/ch/epfl/scala/scalafix-interfaces/) +can be used via: ```diff // project/plugins.sbt --addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.34") -+addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.34+5-5dfe5fb6-SNAPSHOT") -+resolvers += Resolver.sonatypeRepo("snapshots") ++resolvers ++= Resolver.sonatypeOssRepos("snapshots") +-addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.14.2") ++addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.14.2+17-4ba873d2-SNAPSHOT") +-libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % "0.14.2" ++libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % "0.14.2+48-9b6e03ac-SNAPSHOT" ``` ## Team diff --git a/src/main/scala/scalafix/sbt/BuildInfo.scala b/src/main/scala/scalafix/sbt/BuildInfo.scala index 1ebf6b3b..8c294869 100644 --- a/src/main/scala/scalafix/sbt/BuildInfo.scala +++ b/src/main/scala/scalafix/sbt/BuildInfo.scala @@ -29,7 +29,9 @@ object BuildInfo { props.load(stream) case None => sys.error( - s"failed to load the resource file '$propertiesPath'. To fix this problem, make sure to enable the sbt-scalafix in 'project/plugins.sbt' and validate that the scalafix-interfaces jar is available on the classpath of the sbt build." + s"failed to load the resource file '$propertiesPath'; " + + "to fix this problem, add \"ch.epfl.scala\" % \"scalafix-interfaces\" " + + "to libraryDependencies in 'project/plugins.sbt'" ) } props @@ -39,7 +41,8 @@ object BuildInfo { Option(props.getProperty(key)).getOrElse { sys.error( s"sbt-scalafix property '$key' missing in $propertiesPath; " + - "to fix this problem, upgrade to the latest version of Scalafix." + "to fix this problem, upgrade to a more recent version of " + + "\"ch.epfl.scala\" % \"scalafix-interfaces\"" ) } } diff --git a/src/main/scala/scalafix/sbt/ScalafixEnable.scala b/src/main/scala/scalafix/sbt/ScalafixEnable.scala index 2a154af2..fb4d9f76 100644 --- a/src/main/scala/scalafix/sbt/ScalafixEnable.scala +++ b/src/main/scala/scalafix/sbt/ScalafixEnable.scala @@ -1,188 +1,91 @@ package scalafix.sbt -import scala.jdk.CollectionConverters.* -import scala.util.* - import sbt.* import sbt.Keys.* -import sbt.VersionNumber.SemVer import coursierapi.Repository -import ScalafixPlugin.autoImport.scalafixResolvers +import ScalafixPlugin.autoImport.* -/** Command to automatically enable semanticdb compiler output for shell session - */ +/** Command to automatically prepare the build for scalafix invocations */ object ScalafixEnable { - /** If the provided Scala binary version is supported, return the latest scala - * full version for which the recommended semanticdb-scalac is available - */ - private lazy val recommendedSemanticdbScalacScalaVersion - : PartialFunction[(Long, Long), VersionNumber] = (for { - v <- BuildInfo.supportedScalaVersions - p <- CrossVersion.partialVersion(v).toList - } yield p -> VersionNumber(v)).toMap - - /** If the provided Scala binary version is supported, return the latest scala - * full version for which the recommended semanticdb-scalac is available, or - * None if semanticdb support is built-in in the compiler - */ - private lazy val maybeRecommendedSemanticdbScalacScalaVersion - : PartialFunction[(Long, Long), Option[VersionNumber]] = - recommendedSemanticdbScalacScalaVersion.andThen(Some.apply).orElse { - // semanticdb is built-in in the Scala 3 compiler - case (major, _) if major == 3 => None - } + private def latestSemanticdbScalac( + scalaVersion: String, + repositories: Seq[Repository] + ): Option[String] = { + val semanticdbScalacModule = coursierapi.Module.parse( + "org.scalameta:::semanticdb-scalac", + coursierapi.ScalaVersion.of(scalaVersion) + ) + Option( + coursierapi.Versions.create + .withModule(semanticdbScalacModule) + .withRepositories(repositories*) + .versions() + .getMergedListings + .getRelease + ).filter(_.nonEmpty) + } - /** Collect compatible projects across the entire build */ - private def collectProjects(extracted: Extracted): Seq[CompatibleProject] = + private def collectProjects(extracted: Extracted): Seq[CompatibleProject] = { + val repositories = (ThisBuild / scalafixResolvers) + .get(extracted.structure.data) + .getOrElse(Seq.empty) for { - p <- extracted.structure.allProjectRefs - scalaV <- (p / scalaVersion).get(extracted.structure.data).toList - partialVersion <- CrossVersion.partialVersion(scalaV).toList - maybeRecommendedSemanticdbScalacV <- - maybeRecommendedSemanticdbScalacScalaVersion.lift(partialVersion).toList - scalafixResolvers0 <- (p / scalafixResolvers) - .get(extracted.structure.data) - .toList - semanticdbCompilerPlugin0 <- (p / semanticdbCompilerPlugin) - .get(extracted.structure.data) - .toList - } yield CompatibleProject( - p, - VersionNumber(scalaV), - semanticdbCompilerPlugin0, - scalafixResolvers0, - maybeRecommendedSemanticdbScalacV - ) + (scalaVersion, projectRefs) <- + extracted.structure.allProjectRefs + .flatMap { projectRef => + (projectRef / scalaVersion) + .get(extracted.structure.data) + .map(sv => (sv, projectRef)) + } + .foldLeft(Map.empty[String, Seq[ProjectRef]]) { + case (acc, (sv, projectRef)) => + acc.updated(sv, acc.getOrElse(sv, Seq.empty) :+ projectRef) + } + .toSeq + maybeSemanticdbVersion <- + if (scalaVersion.startsWith("2.")) + latestSemanticdbScalac(scalaVersion, repositories) match { + case None => + Seq.empty // don't activate semanticdb + case Some(version) => + Seq(Some(version)) // activate semanticdb with plugin + } + else Seq(None) // activate semanticdb without plugin + projectRef <- projectRefs + } yield CompatibleProject(projectRef, maybeSemanticdbVersion) + } private case class CompatibleProject( ref: ProjectRef, - scalaVersion0: VersionNumber, - semanticdbCompilerPlugin0: ModuleID, - scalafixResolvers0: Seq[Repository], - maybeRecommendedSemanticdbScalacScalaV: Option[VersionNumber] + semanticdbVersion: Option[String] ) lazy val command: Command = Command.command( "scalafixEnable", briefHelp = "Configure SemanticdbPlugin for scalafix on supported projects.", - detail = """1. set semanticdbEnabled := true - |2. for scala 2.x, - | - set semanticdbCompilerPlugin to the scalameta version tracked by scalafix if available for scalaVersion, - | - otherwise set semanticdbCompilerPlugin to a compatible version available for scalaVersion, - | - otherwise force scalaVersion to the latest version supported by the scalameta version tracked by scalafix.""".stripMargin + detail = """1. set scalafixAllowDynamicFallback := true + |2. set semanticdbEnabled := true + |3. for scala 2.x, set semanticdbVersion to the latest scalameta version""".stripMargin ) { s => val extracted = Project.extract(s) val scalacOptionsSettings = Seq(Compile, Test).flatMap( inConfig(_)(ScalafixPlugin.relaxScalacOptionsConfigSettings) ) + val dynamicFallbackSetting = + scalafixAllowDynamicFallback := true val settings = for { project <- collectProjects(extracted) - enableSemanticdbPlugin <- - project.maybeRecommendedSemanticdbScalacScalaV.toList - .flatMap { recommendedSemanticdbScalacScalaV => - - import scalafix.internal.sbt.Implicits._ - val semanticdbScalacModule = - coursierapi.Dependency - .parse( - project.semanticdbCompilerPlugin0.asCoursierCoordinates, - coursierapi.ScalaVersion.of(project.scalaVersion0.toString) - ) - .getModule - val recommendedSemanticdbV = - VersionNumber(BuildInfo.scalametaVersion) - val compatibleSemanticdbVs = Try( - coursierapi.Versions.create - .withRepositories(project.scalafixResolvers0*) - .withModule(semanticdbScalacModule) - .versions() - .getMergedListings - .getAvailable - .asScala - .map(VersionNumber.apply) - // don't use snapshots - .filter(_.extras == Nil) - // https://github.com/scalameta/scalameta/blob/main/COMPATIBILITY.md - .filter(SemVer.isCompatible(_, recommendedSemanticdbV)) - .toList - ) - - compatibleSemanticdbVs match { - case Success(Nil) | Failure(_) => - Seq( - scalaVersion := { - val v = recommendedSemanticdbScalacScalaV.toString - sLog.value.warn( - s"Forcing scalaVersion to $v in project " + - s"${project.ref.project} since no semanticdb-scalac " + - s"version binary-compatible with $recommendedSemanticdbV " + - s"and cross-published for scala " + - s"${project.scalaVersion0.toString} was found - " + - s"consider bumping scala" - ) - v - }, - semanticdbVersion := recommendedSemanticdbV.toString - ) - case Success(available) - if available.contains(recommendedSemanticdbV) => - Seq( - semanticdbVersion := recommendedSemanticdbV.toString - ) - case Success(earliestAvailable :: tail) => - val safeRecommendedSemanticdbV = - if (recommendedSemanticdbV.toString == "4.13.1.1") - VersionNumber("4.13.1") - else recommendedSemanticdbV - - val futureVersion = - SemanticSelector.apply(s">${safeRecommendedSemanticdbV}") - - if (earliestAvailable.matchesSemVer(futureVersion)) { - Seq( - semanticdbVersion := { - val v = earliestAvailable.toString - sLog.value.info( - s"Setting semanticdbVersion to $v in project " + - s"${project.ref.project} since the version " + - s"${recommendedSemanticdbV} tracked by scalafix " + - s"${BuildInfo.scalafixVersion} will not be " + - s"published for scala " + - s"${project.scalaVersion0.toString} - " + - s"consider upgrading sbt-scalafix" - ) - v - } - ) - } else { - val latestAvailable = - tail.lastOption.getOrElse(earliestAvailable) - Seq( - semanticdbVersion := { - val v = latestAvailable.toString - sLog.value.info( - s"Setting semanticdbVersion to $v in project " + - s"${project.ref.project} since the version " + - s"${recommendedSemanticdbV} tracked by scalafix " + - s"${BuildInfo.scalafixVersion} is no longer " + - s"published for scala " + - s"${project.scalaVersion0.toString} - " + - s"consider bumping scala" - ) - v - } - ) - } - } - } :+ (semanticdbEnabled := true) - settings <- - inScope(ThisScope.copy(project = Select(project.ref)))( - scalacOptionsSettings ++ enableSemanticdbPlugin - ) + semanticdbPluginSettings <- (semanticdbEnabled := true) +: + project.semanticdbVersion.map { version => + semanticdbVersion := version + }.toSeq + settings <- inScope(ThisScope.copy(project = Select(project.ref)))( + scalacOptionsSettings ++ semanticdbPluginSettings :+ dynamicFallbackSetting + ) } yield settings extracted.appendWithSession(settings, s) } diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index d67bf994..c168c6e4 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -89,7 +89,13 @@ object ScalafixPlugin extends AutoPlugin { "Defaults to a wrapper around `sbt.Logger`." ) - val scalafixSemanticdb: ModuleID = + val scalafixAllowDynamicFallback: SettingKey[Boolean] = + settingKey[Boolean]( + "Control whether the latest version of scalafix may be downloaded instead of failing when " + + "scalafix-interfaces is not explicitly provided. Off by default because non-deterministic." + ) + + lazy val scalafixSemanticdb: ModuleID = scalafixSemanticdb(BuildInfo.scalametaVersion) def scalafixSemanticdb(scalametaVersion: String): ModuleID = ("org.scalameta" % "semanticdb-scalac" % scalametaVersion) @@ -263,7 +269,8 @@ object ScalafixPlugin extends AutoPlugin { "via `semanticdbVersion` does follow the version recommended " + "for Scalafix, but is not supported for the given Scala " + s"version ${scalaV}. Please consider upgrading to a more recent version " + - "of sbt-scalafix and/or Scala, or uninstalling sbt-scalafix plugin." + "of \"ch.epfl.scala\" % \"scalafix-interfaces\" and/or Scala, or " + + "uninstalling sbt-scalafix." throw inc.copy(message = Some(msg)) case _ => } @@ -287,6 +294,7 @@ object ScalafixPlugin extends AutoPlugin { scalafixCaching := true, scalafixResolvers := defaultScalafixResolvers, scalafixDependencies := Nil, + scalafixAllowDynamicFallback := false, commands += ScalafixEnable.command, scalafixInterfaceCache := new BlockingCache, concurrentRestrictions += Tags.exclusiveGroup(Scalafix), @@ -443,6 +451,12 @@ object ScalafixPlugin extends AutoPlugin { config: ConfigKey ): Def.Initialize[Task[Unit]] = { val task = Def.taskDyn { + if (!scalafixAllowDynamicFallback.value) { + // force scalafix properties to be loaded, to trigger an actionnable error instead + // of letting the built-in scalafix-interfaces fallback to the latest scalafix version + BuildInfo.scalafixVersion + } + implicit val conv: FileConverter = fileConverter.value val errorLogger = diff --git a/src/sbt-test/sbt-scalafix/basic/project/plugins.sbt b/src/sbt-test/sbt-scalafix/basic/project/plugins.sbt index 7f5dd58a..22fad61f 100644 --- a/src/sbt-test/sbt-scalafix/basic/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/basic/project/plugins.sbt @@ -1,3 +1,5 @@ resolvers += Resolver.sonatypeRepo("public") libraryDependencies += "com.googlecode.java-diff-utils" % "diffutils" % "1.3.0" addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/build-lint/project/plugins.sbt b/src/sbt-test/sbt-scalafix/build-lint/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/sbt-scalafix/build-lint/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/build-lint/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/concurrency/project/plugins.sbt b/src/sbt-test/sbt-scalafix/concurrency/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/sbt-scalafix/concurrency/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/concurrency/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/cross-build/project/plugins.sbt b/src/sbt-test/sbt-scalafix/cross-build/project/plugins.sbt index 7f5dd58a..22fad61f 100644 --- a/src/sbt-test/sbt-scalafix/cross-build/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/cross-build/project/plugins.sbt @@ -1,3 +1,5 @@ resolvers += Resolver.sonatypeRepo("public") libraryDependencies += "com.googlecode.java-diff-utils" % "diffutils" % "1.3.0" addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/custom-config/project/plugins.sbt b/src/sbt-test/sbt-scalafix/custom-config/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/sbt-scalafix/custom-config/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/custom-config/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/custom-src-directory/project/plugins.sbt b/src/sbt-test/sbt-scalafix/custom-src-directory/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/sbt-scalafix/custom-src-directory/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/custom-src-directory/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/dependency/project/plugins.sbt b/src/sbt-test/sbt-scalafix/dependency/project/plugins.sbt index 7f5dd58a..22fad61f 100644 --- a/src/sbt-test/sbt-scalafix/dependency/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/dependency/project/plugins.sbt @@ -1,3 +1,5 @@ resolvers += Resolver.sonatypeRepo("public") libraryDependencies += "com.googlecode.java-diff-utils" % "diffutils" % "1.3.0" addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/explicit-files/project/plugins.sbt b/src/sbt-test/sbt-scalafix/explicit-files/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/sbt-scalafix/explicit-files/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/explicit-files/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/inconfig/project/plugins.sbt b/src/sbt-test/sbt-scalafix/inconfig/project/plugins.sbt index 7f5dd58a..22fad61f 100644 --- a/src/sbt-test/sbt-scalafix/inconfig/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/inconfig/project/plugins.sbt @@ -1,3 +1,5 @@ resolvers += Resolver.sonatypeRepo("public") libraryDependencies += "com.googlecode.java-diff-utils" % "diffutils" % "1.3.0" addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/interfaces-missing/build.sbt b/src/sbt-test/sbt-scalafix/interfaces-missing/build.sbt new file mode 100644 index 00000000..67fa5e3c --- /dev/null +++ b/src/sbt-test/sbt-scalafix/interfaces-missing/build.sbt @@ -0,0 +1,13 @@ +lazy val checkLogs = + taskKey[Unit]("Check presence of call to action in last logs") + +checkLogs := { + val lastLog: File = BuiltinCommands.lastLogFile(state.value).get + val last: String = IO.read(lastLog) + assert( + last.contains( + "add \"ch.epfl.scala\" % \"scalafix-interfaces\" to libraryDependencies in 'project/plugins.sbt'" + ), + "actionable error should be logged" + ) +} diff --git a/src/sbt-test/sbt-scalafix/interfaces-missing/project/plugins.sbt b/src/sbt-test/sbt-scalafix/interfaces-missing/project/plugins.sbt new file mode 100644 index 00000000..2d3b4d3b --- /dev/null +++ b/src/sbt-test/sbt-scalafix/interfaces-missing/project/plugins.sbt @@ -0,0 +1,2 @@ +resolvers += Resolver.sonatypeRepo("public") +addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) diff --git a/src/sbt-test/sbt-scalafix/interfaces-missing/src/main/scala/A.scala b/src/sbt-test/sbt-scalafix/interfaces-missing/src/main/scala/A.scala new file mode 100644 index 00000000..69c493db --- /dev/null +++ b/src/sbt-test/sbt-scalafix/interfaces-missing/src/main/scala/A.scala @@ -0,0 +1 @@ +object A diff --git a/src/sbt-test/sbt-scalafix/interfaces-missing/test b/src/sbt-test/sbt-scalafix/interfaces-missing/test new file mode 100644 index 00000000..36336e4f --- /dev/null +++ b/src/sbt-test/sbt-scalafix/interfaces-missing/test @@ -0,0 +1,6 @@ +# the project loads, but scalafix fails +-> scalafix DisableSyntax +> checkLogs + +# a build reference to the member relying on scalafix properties prevents loading the project +-> set ThisBuild / semanticdbVersion := scalafixSemanticdb.revision diff --git a/src/sbt-test/sbt-scalafix/resolvers/project/plugins.sbt b/src/sbt-test/sbt-scalafix/resolvers/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/sbt-scalafix/resolvers/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/resolvers/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/root-validation/project/plugins.sbt b/src/sbt-test/sbt-scalafix/root-validation/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/sbt-scalafix/root-validation/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/root-validation/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/scalafixEnable/build.sbt b/src/sbt-test/sbt-scalafix/scalafixEnable/build.sbt index 8dbf659e..40a15786 100644 --- a/src/sbt-test/sbt-scalafix/scalafixEnable/build.sbt +++ b/src/sbt-test/sbt-scalafix/scalafixEnable/build.sbt @@ -1,36 +1,15 @@ val V = _root_.scalafix.sbt.BuildInfo lazy val config = project.settings( - scalafixScalaBinaryVersion := scalaBinaryVersion.value, // to support old scalafix-interface scalaVersion := "2.13.16" ) lazy val unsupported = project.settings( - scalafixScalaBinaryVersion := scalaBinaryVersion.value, // to support old scalafix-interface - // 2.11.x is not supported - scalaVersion := "2.11.12" -) - -lazy val bumpScala = project.settings( - scalafixScalaBinaryVersion := scalaBinaryVersion.value, // to support old scalafix-interface - // semanticdb-scalac_2.12.0 was never available - scalaVersion := "2.12.0" -) - -lazy val downgradeScalameta = project.settings( - scalafixScalaBinaryVersion := scalaBinaryVersion.value, // to support old scalafix-interface - // semanticdb-scalac_2.12.4 no longer available after 4.1.9 - scalaVersion := "2.12.4" -) - -lazy val upgradeScalameta = project.settings( - scalafixScalaBinaryVersion := scalaBinaryVersion.value, // to support old scalafix-interface - // semanticdb-scalac_2.12.15 not yet available in 4.4.10, became available as of 4.4.28 - scalaVersion := "2.12.15" + // 2.10.x is not supported + scalaVersion := "2.10.7" ) lazy val available = project.settings( - scalafixScalaBinaryVersion := scalaBinaryVersion.value, // to support old scalafix-interface // semanticdb-scalac_2.13.4 available in 4.4.10 scalaVersion := "2.13.4", crossScalaVersions := Seq("2.12.15") @@ -38,42 +17,9 @@ lazy val available = project.settings( TaskKey[Unit]("check") := { assert((unsupported / semanticdbEnabled).value == false) - assert((unsupported / scalaVersion).value == "2.11.12") assert((unsupported / Compile / compile / scalacOptions).value.isEmpty) - assert((bumpScala / semanticdbEnabled).value == true) - assert((bumpScala / scalaVersion).value == V.scala212) - assert( - (bumpScala / semanticdbCompilerPlugin).value.revision == V.scalametaVersion - ) - assert( - (bumpScala / Compile / compile / scalacOptions).value - .count(_ == "-Yrangepos") == 1 - ) - - assert((downgradeScalameta / semanticdbEnabled).value == true) - assert((downgradeScalameta / scalaVersion).value == "2.12.4") - assert( - (downgradeScalameta / semanticdbCompilerPlugin).value.revision == "4.1.9" - ) - assert( - (downgradeScalameta / Compile / compile / scalacOptions).value - .count(_ == "-Yrangepos") == 1 - ) - - assert((upgradeScalameta / semanticdbEnabled).value == true) - assert((upgradeScalameta / scalaVersion).value == "2.12.15") - assert( - (upgradeScalameta / semanticdbCompilerPlugin).value.revision == "4.4.28" - ) - assert( - (upgradeScalameta / Compile / compile / scalacOptions).value - .count(_ == "-Yrangepos") == 1 - ) - assert((available / semanticdbEnabled).value == true) - assert((available / scalaVersion).value == "2.13.4") - assert((available / semanticdbCompilerPlugin).value.revision == "4.4.10") assert( (available / Test / compile / scalacOptions).value .count(_ == "-Yrangepos") == 1 diff --git a/src/sbt-test/sbt-scalafix/scalafixEnable/project/plugins.sbt b/src/sbt-test/sbt-scalafix/scalafixEnable/project/plugins.sbt index 324c1724..2d3b4d3b 100644 --- a/src/sbt-test/sbt-scalafix/scalafixEnable/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/scalafixEnable/project/plugins.sbt @@ -1,5 +1,2 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) - -// https://github.com/scalameta/scalameta/blob/v4.4.10/project/Versions.scala -dependencyOverrides += "ch.epfl.scala" % "scalafix-interfaces" % "0.9.27" // scala-steward:off diff --git a/src/sbt-test/sbt-scalafix/scalafixOnCompile/project/plugins.sbt b/src/sbt-test/sbt-scalafix/scalafixOnCompile/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/sbt-scalafix/scalafixOnCompile/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/scalafixOnCompile/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/semanticdb-enabled/project/plugins.sbt b/src/sbt-test/sbt-scalafix/semanticdb-enabled/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/sbt-scalafix/semanticdb-enabled/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/semanticdb-enabled/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/skip/project/plugins.sbt b/src/sbt-test/sbt-scalafix/skip/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/sbt-scalafix/skip/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/skip/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/suppress/project/plugins.sbt b/src/sbt-test/sbt-scalafix/suppress/project/plugins.sbt index bb79ccd0..007d9d77 100644 --- a/src/sbt-test/sbt-scalafix/suppress/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/suppress/project/plugins.sbt @@ -1,3 +1,5 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") libraryDependencies += "com.googlecode.java-diff-utils" % "diffutils" % "1.3.0" diff --git a/src/sbt-test/sbt-scalafix/unavailable-semanticdb-scalac/build.sbt b/src/sbt-test/sbt-scalafix/unavailable-semanticdb-scalac/build.sbt index 175d9164..8585dfb2 100644 --- a/src/sbt-test/sbt-scalafix/unavailable-semanticdb-scalac/build.sbt +++ b/src/sbt-test/sbt-scalafix/unavailable-semanticdb-scalac/build.sbt @@ -19,7 +19,7 @@ checkLogs := { assert( logLines.exists( _.contains( - "Please consider upgrading to a more recent version of sbt-scalafix and/or Scala, or uninstalling sbt-scalafix plugin" + "Please consider upgrading to a more recent version of \"ch.epfl.scala\" % \"scalafix-interfaces\" and/or Scala, or uninstalling sbt-scalafix" ) ) ) diff --git a/src/sbt-test/sbt-scalafix/unavailable-semanticdb-scalac/project/plugins.sbt b/src/sbt-test/sbt-scalafix/unavailable-semanticdb-scalac/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/sbt-scalafix/unavailable-semanticdb-scalac/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/unavailable-semanticdb-scalac/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/sbt-scalafix/wrapper/project/plugins.sbt b/src/sbt-test/sbt-scalafix/wrapper/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/sbt-scalafix/wrapper/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/wrapper/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/skip-java17+/scalafixResolvers/project/plugins.sbt b/src/sbt-test/skip-java17+/scalafixResolvers/project/plugins.sbt index a8c87140..b0d8a82a 100644 --- a/src/sbt-test/skip-java17+/scalafixResolvers/project/plugins.sbt +++ b/src/sbt-test/skip-java17+/scalafixResolvers/project/plugins.sbt @@ -1,3 +1,5 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") addSbtPlugin("nl.gn0s1s" %% "sbt-dotenv" % "3.1.1") diff --git a/src/sbt-test/skip-sbt1.4/cross-build-scala3/project/plugins.sbt b/src/sbt-test/skip-sbt1.4/cross-build-scala3/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/skip-sbt1.4/cross-build-scala3/project/plugins.sbt +++ b/src/sbt-test/skip-sbt1.4/cross-build-scala3/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/skip-sbt1.4/local-rules/project/plugins.sbt b/src/sbt-test/skip-sbt1.4/local-rules/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/skip-sbt1.4/local-rules/project/plugins.sbt +++ b/src/sbt-test/skip-sbt1.4/local-rules/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/skip-sbt1.4/scala-3/project/plugins.sbt b/src/sbt-test/skip-sbt1.4/scala-3/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/skip-sbt1.4/scala-3/project/plugins.sbt +++ b/src/sbt-test/skip-sbt1.4/scala-3/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/skip-sbt1.4/scalafixEnable/build.sbt b/src/sbt-test/skip-sbt1.4/scalafixEnable/build.sbt index 9efcb881..a04b769a 100644 --- a/src/sbt-test/skip-sbt1.4/scalafixEnable/build.sbt +++ b/src/sbt-test/skip-sbt1.4/scalafixEnable/build.sbt @@ -3,23 +3,23 @@ ThisBuild / scalafixDependencies += "ch.epfl.scala" %% "example-scalafix-rule" % lazy val scala210 = project .in(file("scala210")) .settings( - scalaVersion := "2.10.7" // unsupported by semanticdb-scalac + scalaVersion := "2.10.7" // unsupported by semanticdb-scalac, unsupported by scalafix-interfaces ) lazy val scala211 = project .in(file("scala211")) .settings( - scalaVersion := "2.11.12" // supported by semanticdb-scalac, but not by sbt-scalafix + scalaVersion := "2.11.12" // supported by old semanticdb-scalac, no longer supported by scalafix-interfaces ) lazy val scala212 = project .in(file("scala212")) .settings( - scalaVersion := "2.12.20" // supported by semanticdb-scalac + scalaVersion := "2.12.20" // supported by semanticdb-scalac, supported by scalafix-interfaces ) lazy val scala3 = project .in(file("scala3")) .settings( - scalaVersion := "3.6.3" // built-in support for semanticdb + scalaVersion := "3.3.5" // built-in support for semanticdb, supported by scalafix-interfaces ) diff --git a/src/sbt-test/skip-sbt1.4/testkit/project/plugins.sbt b/src/sbt-test/skip-sbt1.4/testkit/project/plugins.sbt index e30c72f9..f978f56b 100644 --- a/src/sbt-test/skip-sbt1.4/testkit/project/plugins.sbt +++ b/src/sbt-test/skip-sbt1.4/testkit/project/plugins.sbt @@ -1,5 +1,7 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") libraryDependencies ++= { val sbtV = sbtBinaryVersion.value diff --git a/src/sbt-test/skip-windows/caching/project/plugins.sbt b/src/sbt-test/skip-windows/caching/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/skip-windows/caching/project/plugins.sbt +++ b/src/sbt-test/skip-windows/caching/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version") diff --git a/src/sbt-test/skip-windows/relax-scalacOptions/project/plugins.sbt b/src/sbt-test/skip-windows/relax-scalacOptions/project/plugins.sbt index 2d3b4d3b..3e9aa955 100644 --- a/src/sbt-test/skip-windows/relax-scalacOptions/project/plugins.sbt +++ b/src/sbt-test/skip-windows/relax-scalacOptions/project/plugins.sbt @@ -1,2 +1,4 @@ resolvers += Resolver.sonatypeRepo("public") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) +libraryDependencies += "ch.epfl.scala" % "scalafix-interfaces" % + sys.props("scalafix-interfaces.version")