Skip to content

Commit

Permalink
expose scalafixScalaVersion
Browse files Browse the repository at this point in the history
- Advanced users with local rules targeting 2.13 code will be able
  to simplify their build
- 2.12 remains the default until 1.0 to be backward compatible with
  external rules (loaded through scalafixDependencies or dependency:)
  • Loading branch information
github-brice-jaglin committed Jun 1, 2020
1 parent 3c62af2 commit 5bc7995
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 21 deletions.
29 changes: 17 additions & 12 deletions src/main/scala/scalafix/internal/sbt/ScalafixCoursier.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,30 @@ import scalafix.sbt.BuildInfo
import scala.collection.JavaConverters._

object ScalafixCoursier {
private def scalafixCliModule: Module =
private def scalafixCliModule(scalaVersion: String): Module =
Module.of(
"ch.epfl.scala",
s"scalafix-cli_${BuildInfo.scala212}"
s"scalafix-cli_$scalaVersion"
)
private def scalafixCli: Dependency =
private def scalafixCli(scalaVersion: String): Dependency =
Dependency.of(
scalafixCliModule,
scalafixCliModule(scalaVersion),
BuildInfo.scalafixVersion
)

def scalafixCliJars(
scalaVersion: String,
repositories: Seq[cs.Repository]
): List[Path] = {
runFetch(
newFetch()
.addDependencies(scalafixCli)
newFetch(scalaVersion)
.addDependencies(scalafixCli(scalaVersion))
.addRepositories(toCoursierRepositories(repositories): _*)
)
}

def scalafixToolClasspath(
scalaVersion: String,
deps: Seq[ModuleID],
customResolvers: Seq[cs.Repository]
): Seq[URL] = {
Expand All @@ -41,7 +43,7 @@ object ScalafixCoursier {
} else {
val jars = dependencyCache.computeIfAbsent(
deps,
fetchScalafixDependencies(customResolvers)
fetchScalafixDependencies(scalaVersion, customResolvers)
)
jars.map(_.toUri.toURL)
}
Expand All @@ -51,13 +53,16 @@ object ScalafixCoursier {
jutil.Collections.synchronizedMap(new jutil.HashMap())
}
private[scalafix] def fetchScalafixDependencies(
scalaVersion: String,
customResolvers: Seq[cs.Repository]
): function.Function[Seq[ModuleID], List[Path]] =
new function.Function[Seq[ModuleID], List[Path]] {
override def apply(t: Seq[ModuleID]): List[Path] = {
val binaryScalaVersion = CrossVersion.binaryScalaVersion(scalaVersion)
val dependencies = t.map { module =>
val binarySuffix =
if (module.crossVersion.isInstanceOf[CrossVersion.Binary]) "_2.12"
if (module.crossVersion.isInstanceOf[CrossVersion.Binary])
s"_$binaryScalaVersion"
else ""
Dependency.of(
module.organization,
Expand All @@ -66,9 +71,9 @@ object ScalafixCoursier {
)
}
runFetch(
newFetch()
newFetch(scalaVersion)
.addRepositories(toCoursierRepositories(customResolvers): _*)
.addDependencies(scalafixCli)
.addDependencies(scalafixCli(scalaVersion))
.addDependencies(dependencies.toArray: _*)
)
}
Expand All @@ -84,7 +89,7 @@ object ScalafixCoursier {
}.toArray
def runFetch(fetch: Fetch): List[Path] =
fetch.fetch().asScala.iterator.map(_.toPath()).toList
def newFetch(): Fetch =
def newFetch(scalaVersion: String): Fetch =
Fetch
.create()
.withRepositories()
Expand All @@ -93,7 +98,7 @@ object ScalafixCoursier {
.create()
.withForceVersions(
Map(
scalafixCliModule -> scalafixCli.getVersion()
scalafixCliModule(scalaVersion) -> BuildInfo.scalafixVersion
).asJava
)
)
Expand Down
12 changes: 9 additions & 3 deletions src/main/scala/scalafix/internal/sbt/ScalafixInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ object Arg {
}

class ScalafixInterface private (
scalaVersion: String,
scalafixArguments: ScalafixArguments, // hide it to force usage of withArgs so we can intercept arguments
val args: Seq[Arg]
) {
Expand All @@ -88,11 +89,13 @@ class ScalafixInterface private (
.classLoader

private def this(
scalaVersion: String,
api: ScalafixAPI,
toolClasspath: URLClassLoader,
mainCallback: ScalafixMainCallback
) =
this(
scalaVersion,
api
.newArguments()
.withMainCallback(mainCallback)
Expand Down Expand Up @@ -125,6 +128,7 @@ class ScalafixInterface private (
): ScalafixInterface = {
val extraURLs = ScalafixCoursier
.scalafixToolClasspath(
scalaVersion,
extraExternalDeps,
customResolvers
) ++ extraInternalDeps.map(_.toURI.toURL)
Expand All @@ -141,7 +145,7 @@ class ScalafixInterface private (
try arg(acc)
catch { case NonFatal(e) => throw new InvalidArgument(e.getMessage) }
}
new ScalafixInterface(newScalafixArguments, this.args ++ args)
new ScalafixInterface(scalaVersion, newScalafixArguments, this.args ++ args)
}

def run(): Seq[ScalafixError] =
Expand All @@ -165,19 +169,21 @@ object ScalafixInterface {
override def apply(): T = _value.get
}
def fromToolClasspath(
scalafixScalaVersion: String,
scalafixDependencies: Seq[ModuleID],
scalafixCustomResolvers: Seq[Repository],
logger: Logger = Compat.ConsoleLogger(System.out)
): () => ScalafixInterface =
new LazyValue({ () =>
val jars = ScalafixCoursier.scalafixCliJars(scalafixCustomResolvers)
val jars = ScalafixCoursier
.scalafixCliJars(scalafixScalaVersion, scalafixCustomResolvers)
val urls = jars.map(_.toUri.toURL).toArray
val interfacesParent =
new ScalafixInterfacesClassloader(this.getClass.getClassLoader)
val classloader = new URLClassLoader(urls, interfacesParent)
val api = ScalafixAPI.classloadInstance(classloader)
val callback = new ScalafixLogger(logger)
new ScalafixInterface(api, classloader, callback)
new ScalafixInterface(scalafixScalaVersion, api, classloader, callback)
.addToolClasspath(
scalafixDependencies,
scalafixCustomResolvers,
Expand Down
8 changes: 8 additions & 0 deletions src/main/scala/scalafix/sbt/ScalafixPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ object ScalafixPlugin extends AutoPlugin {
"Optional list of custom rules to install from Maven Central. " +
"This setting is read from the global scope so it only needs to be defined once in the build."
)
val scalafixScalaVersion: SettingKey[String] =
settingKey[String](
"The full scala version used for the scalafix classpath. Rules must be compiled against that binary version." +
s"Defaults to the latest supported 2.12 version (${BuildInfo.scala212}). " +
"This setting is read from the global scope so it only needs to be defined once in the build."
)
val scalafixConfig: SettingKey[Option[File]] =
settingKey[Option[File]](
"Optional location to .scalafix.conf file to specify which scalafix rules should run. " +
Expand Down Expand Up @@ -111,6 +117,7 @@ object ScalafixPlugin extends AutoPlugin {
// https://github.com/sbt/sbt/issues/3572#issuecomment-417582703
workingDirectory = baseDirectory.in(ThisBuild).value.toPath
scalafixInterface = ScalafixInterface.fromToolClasspath(
scalafixScalaVersion = scalafixScalaVersion.in(ThisBuild).value,
scalafixDependencies = scalafixDependencies.in(ThisBuild).value,
scalafixCustomResolvers = scalafixResolvers.in(ThisBuild).value
)
Expand All @@ -119,6 +126,7 @@ object ScalafixPlugin extends AutoPlugin {
scalafixCaching := false,
scalafixResolvers := ScalafixCoursier.defaultResolvers,
scalafixDependencies := Nil,
scalafixScalaVersion := BuildInfo.scala212, // will follow scalafixVersion once community rules are cross-built
commands += ScalafixEnable.command
)

Expand Down
8 changes: 3 additions & 5 deletions src/sbt-test/sbt-scalafix/local-rules/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,26 @@ inThisBuild(
scalafixDependencies := List(
// Custom rule published to Maven Central https://github.com/olafurpg/example-scalafix-rule
"com.geirsson" %% "example-scalafix-rule" % "1.3.0"
)
),
scalaVersion := Versions.scala213,
scalafixScalaVersion := scalaVersion.version
)
)

val rules = project
.disablePlugins(ScalafixPlugin)
.settings(
scalaVersion := Versions.scala212,
crossPaths := false,
libraryDependencies += "ch.epfl.scala" %% "scalafix-core" % Versions.scalafixVersion,
libraryDependencies += "joda-time" % "joda-time" % "2.10.6"
)

val service = project
.dependsOn(rules % ScalafixConfig)
.settings(
scalaVersion := Versions.scala213,
libraryDependencies += "com.nequissimus" % "sort-imports_2.12" % "0.5.0" % ScalafixConfig
)

val sameproject = project
.settings(
scalaVersion := Versions.scala212, // the project scala version MUST match the one used by Scalafix
libraryDependencies += "ch.epfl.scala" %% "scalafix-core" % Versions.scalafixVersion % ScalafixConfig
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.eclipse.jgit.lib.AbbreviatedObjectId
import org.scalatest.Tag
import sbt.complete.Parser
import org.scalatest.funsuite.AnyFunSuite
import scalafix.sbt.BuildInfo

class SbtCompletionsSuite extends AnyFunSuite {
val fs = new Fs()
Expand All @@ -29,6 +30,7 @@ class SbtCompletionsSuite extends AnyFunSuite {
val mainArgs =
ScalafixInterface
.fromToolClasspath(
BuildInfo.scala212,
Seq(exampleDependency),
ScalafixCoursier.defaultResolvers
)()
Expand Down
4 changes: 3 additions & 1 deletion src/test/scala/scalafix/internal/sbt/ScalafixAPISuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import org.scalactic.source.Position
import sbt._
import sbt.internal.sbtscalafix.Compat
import scalafix.interfaces.ScalafixError

import org.scalatest.funsuite.AnyFunSuite
import scalafix.sbt.BuildInfo

import scala.util.Properties

class ScalafixAPISuite extends AnyFunSuite {
Expand All @@ -28,6 +29,7 @@ class ScalafixAPISuite extends AnyFunSuite {
val logger = Compat.ConsoleLogger(new PrintStream(baos))
val interface = ScalafixInterface
.fromToolClasspath(
BuildInfo.scala212,
List("com.geirsson" %% "example-scalafix-rule" % "1.3.0"),
ScalafixCoursier.defaultResolvers,
logger
Expand Down

0 comments on commit 5bc7995

Please sign in to comment.