From a0e479d9be8f5b9662561a6ba915889826869d32 Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Sun, 10 Mar 2024 19:51:20 +0800 Subject: [PATCH 01/24] feat: adapt sbt resolvers as scalafix custom resolve if possible --- .jvmopts | 1 + .../internal/sbt/CoursierRepoResolvers.scala | 178 ++++++++++++++++++ .../scala/scalafix/sbt/ScalafixPlugin.scala | 91 ++++++--- 3 files changed, 246 insertions(+), 24 deletions(-) create mode 100644 src/main/scala/scalafix/internal/sbt/CoursierRepoResolvers.scala diff --git a/.jvmopts b/.jvmopts index f9efc610..b45d2db8 100644 --- a/.jvmopts +++ b/.jvmopts @@ -4,3 +4,4 @@ -XX:ReservedCodeCacheSize=1024m -XX:+TieredCompilation -Dfile.encoding=UTF-8 +-Dadd-opens=java.base/java.util=ALL-UNNAMED diff --git a/src/main/scala/scalafix/internal/sbt/CoursierRepoResolvers.scala b/src/main/scala/scalafix/internal/sbt/CoursierRepoResolvers.scala new file mode 100644 index 00000000..314e0060 --- /dev/null +++ b/src/main/scala/scalafix/internal/sbt/CoursierRepoResolvers.scala @@ -0,0 +1,178 @@ +package scalafix.internal.sbt + +import coursierapi.{Credentials, IvyRepository, MavenRepository, Repository} +import org.apache.ivy.plugins.resolver.IBiblioResolver +import sbt.librarymanagement.{Configuration as _, MavenRepository as _, *} +import sbt.util.Logger + +import java.net.MalformedURLException +import java.nio.file.Paths +import scala.collection.JavaConverters.* + +// vendor from sbt-coursier/lmcoursier.internal.Resolvers +object CoursierRepoResolvers { + + private def mavenCompatibleBaseOpt(patterns: Patterns): Option[String] = + if (patterns.isMavenCompatible) { + // input : /Users/user/custom/repo/[organisation]/[module](_[scalaVersion])(_[sbtVersion])/[revision]/[artifact]-[revision](-[classifier]).[ext] + // output : /Users/user/custom/repo/ + def basePattern(pattern: String): String = + pattern.takeWhile(c => c != '[' && c != '(') + + val baseIvyPattern = basePattern(patterns.ivyPatterns.head) + val baseArtifactPattern = basePattern(patterns.artifactPatterns.head) + + if (baseIvyPattern == baseArtifactPattern) + Some(baseIvyPattern) + else + None + } else + None + + private def mavenRepositoryOpt( + root: String, + log: Logger, + credentialsByHost: Map[String, Credentials] + ): Option[MavenRepository] = + try { + val rootURI = java.net.URI.create( + root + ) // ensure root is a URL whose protocol can be handled here + val root0 = if (root.endsWith("/")) root else root + "/" + val mavenRepository = MavenRepository.of(root0) + + Some( + credentialsByHost + .get(rootURI.getHost) + .fold(mavenRepository)(mavenRepository.withCredentials) + ) + } catch { + case e: MalformedURLException => + log.warn( + "Error parsing Maven repository base " + + root + + Option(e.getMessage).fold("")(" (" + _ + ")") + + ", ignoring it" + ) + + None + } + + // this handles whitespace in path + private def pathToUriString(path: String): String = { + val stopAtIdx = path.indexWhere(c => c == '[' || c == '$' || c == '(') + if (stopAtIdx > 0) { + val (pathPart, patternPart) = path.splitAt(stopAtIdx) + Paths.get(pathPart).toUri.toASCIIString + patternPart + } else if (stopAtIdx == 0) + "file://" + path + else + Paths.get(path).toUri.toASCIIString + } + + def repository( + resolver: Resolver, + log: Logger, + credentialsByHost: Map[String, Credentials] + ): Option[Repository] = + resolver match { + case r: sbt.librarymanagement.MavenRepository => + mavenRepositoryOpt(r.root, log, credentialsByHost) + + case r: FileRepository + if r.patterns.ivyPatterns.lengthCompare(1) == 0 && + r.patterns.artifactPatterns.lengthCompare(1) == 0 => + val mavenCompatibleBaseOpt0 = mavenCompatibleBaseOpt(r.patterns) + + mavenCompatibleBaseOpt0 match { + case None => + val repo = IvyRepository + .of(pathToUriString(r.patterns.artifactPatterns.head)) + .withMetadataPattern(pathToUriString(r.patterns.ivyPatterns.head)) + .withDropInfoAttributes(true) + + Some(repo) + + case Some(mavenCompatibleBase) => + mavenRepositoryOpt( + pathToUriString(mavenCompatibleBase), + log, + credentialsByHost + ) + } + + case r: URLRepository if patternMatchGuard(r.patterns) => + parseMavenCompatResolver(log, r.patterns, credentialsByHost) + + case raw: RawRepository + if raw.name == "inter-project" => // sbt.RawRepository.equals just compares names anyway + None + + // Pattern Match resolver-type-specific RawRepositories + case IBiblioRepository(p) => + parseMavenCompatResolver( + log, + p, + credentialsByHost + ) + + case other => + log.warn(s"Unrecognized repository ${other.name}, ignoring it") + None + } + + private object IBiblioRepository { + + private def stringVector(v: java.util.List[_]): Vector[String] = + Option(v).map(_.asScala.toVector).getOrElse(Vector.empty).collect { + case s: String => s + } + + private def patterns(resolver: IBiblioResolver): Patterns = Patterns( + ivyPatterns = stringVector(resolver.getIvyPatterns), + artifactPatterns = stringVector(resolver.getArtifactPatterns), + isMavenCompatible = resolver.isM2compatible, + descriptorOptional = !resolver.isUseMavenMetadata, + skipConsistencyCheck = !resolver.isCheckconsistency + ) + + def unapply(r: Resolver): Option[Patterns] = + r match { + case raw: RawRepository => + raw.resolver match { + case b: IBiblioResolver => + Some(patterns(b)) + .filter(patternMatchGuard) + case _ => + None + } + case _ => + None + } + } + + private def patternMatchGuard(patterns: Patterns): Boolean = + patterns.ivyPatterns.lengthCompare(1) == 0 && + patterns.artifactPatterns.lengthCompare(1) == 0 + + private def parseMavenCompatResolver( + log: Logger, + patterns: Patterns, + credentialsByHost: Map[String, Credentials] + ): Option[Repository] = { + val mavenCompatibleBaseOpt0 = mavenCompatibleBaseOpt(patterns) + + mavenCompatibleBaseOpt0 match { + case None => + val repo = IvyRepository + .of(pathToUriString(patterns.artifactPatterns.head)) + .withMetadataPattern(pathToUriString(patterns.ivyPatterns.head)) + .withDropInfoAttributes(true) + + Some(repo) + + case Some(mavenCompatibleBase) => + mavenRepositoryOpt(mavenCompatibleBase, log, credentialsByHost) + } + } +} diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index 6a43993d..dad84866 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -132,7 +132,8 @@ object ScalafixPlugin extends AutoPlugin { Invisible ) - private val scalafixInterfaceProvider: SettingKey[() => ScalafixInterface] = + private val scalafixInterfaceProvider + : SettingKey[Seq[Repository] => ScalafixInterface] = SettingKey( "scalafixInterfaceProvider", "Implementation detail - do not use", @@ -149,6 +150,32 @@ object ScalafixPlugin extends AutoPlugin { Invisible ) + private val adaptSbtResolvers = Def.task { + val credentialsByHost = Credentials + .allDirect(credentials.value) + .map(dc => + dc.host -> coursierapi.Credentials.of( + dc.userName, + dc.passwd + ) + ) + .toMap + + resolvers.value.flatMap(resolver => { + val adaptedRepo = CoursierRepoResolvers.repository( + resolver, + stdoutLogger, + credentialsByHost + ) + if (adaptedRepo.isEmpty) { + stdoutLogger.warn( + s"Defined resolver $resolver cannot be converted to coursier repository, thus will be ignored by scalafix." + ) + } + adaptedRepo + }) + } + private lazy val cachingStyle = { val useLastModifiedCachingStyle = sys.props.get("sbt-scalafix.uselastmodified") == Some("true") @@ -156,6 +183,19 @@ object ScalafixPlugin extends AutoPlugin { else FileInfo.hash } + private lazy val defaultScalafixResolvers = + // Repository.defaults() defaults to Repository.ivy2Local() and Repository.central(). These can be overridden per + // env variable, e.g., export COURSIER_REPOSITORIES="ivy2Local|central|sonatype:releases|jitpack|https://corporate.com/repo". + // See https://github.com/coursier/coursier/blob/master/modules/coursier/jvm/src/main/scala/coursier/PlatformResolve.scala#L19-L68 + // and https://get-coursier.io/docs/other-repositories for more details. + // Also see src/sbt-test/sbt-scalafix/scalafixResolvers/test for a scripted test preserving this behavior. + Repository.defaults().asScala.toSeq ++ + Seq( + coursierapi.MavenRepository.of( + "https://oss.sonatype.org/content/repositories/public" + ) + ) + override lazy val projectConfigurations: Seq[Configuration] = Seq(ScalafixConfig) @@ -170,13 +210,17 @@ object ScalafixPlugin extends AutoPlugin { SettingKey[Boolean]("bspEnabled") := false ) ), - scalafixInterfaceProvider := ScalafixInterface.fromToolClasspath( - scalafixScalaBinaryVersion.value, - scalafixDependencies = scalafixDependencies.value, - scalafixCustomResolvers = scalafixResolvers.value, - logger = ScalafixInterface.defaultLogger, - callback = (ThisBuild / scalafixCallback).value - ), + scalafixInterfaceProvider := { (customResolvers: Seq[Repository]) => + ScalafixInterface + .fromToolClasspath( + scalafixScalaBinaryVersion.value, + scalafixDependencies = scalafixDependencies.value, + scalafixCustomResolvers = customResolvers, + logger = ScalafixInterface.defaultLogger, + callback = (ThisBuild / scalafixCallback).value + ) + .apply() + }, update := { object SemanticdbScalac { def unapply(id: ModuleID): Option[String] = @@ -217,18 +261,7 @@ object ScalafixPlugin extends AutoPlugin { scalafixConfig := None, // let scalafix-cli try to infer $CWD/.scalafix.conf scalafixOnCompile := false, scalafixCaching := true, - scalafixResolvers := - // Repository.defaults() defaults to Repository.ivy2Local() and Repository.central(). These can be overridden per - // env variable, e.g., export COURSIER_REPOSITORIES="ivy2Local|central|sonatype:releases|jitpack|https://corporate.com/repo". - // See https://github.com/coursier/coursier/blob/master/modules/coursier/jvm/src/main/scala/coursier/PlatformResolve.scala#L19-L68 - // and https://get-coursier.io/docs/other-repositories for more details. - // Also see src/sbt-test/sbt-scalafix/scalafixResolvers/test for a scripted test preserving this behavior. - Repository.defaults().asScala.toSeq ++ - Seq( - coursierapi.MavenRepository.of( - "https://oss.sonatype.org/content/repositories/public" - ) - ), + scalafixResolvers := defaultScalafixResolvers, scalafixDependencies := Nil, commands += ScalafixEnable.command, scalafixInterfaceCache := new BlockingCache[ @@ -305,7 +338,11 @@ object ScalafixPlugin extends AutoPlugin { val parser = Def.setting( new ScalafixCompletions( workingDirectory = (ThisBuild / baseDirectory).value.toPath, - loadedRules = () => scalafixInterfaceProvider.value().availableRules(), + loadedRules = () => + scalafixInterfaceProvider + // sbt Credentials is task, so unfortunately it cannot be showed up here + .value(scalafixResolvers.value) + .availableRules(), terminalWidth = Some(JLineAccess.terminalWidth), allowedTargetFilesPrefixes = Nil, jgitCompletion = scalafixJGitCompletion.value @@ -358,7 +395,11 @@ object ScalafixPlugin extends AutoPlugin { val parser = Def.setting( new ScalafixCompletions( workingDirectory = (ThisBuild / baseDirectory).value.toPath, - loadedRules = () => scalafixInterfaceProvider.value().availableRules(), + loadedRules = () => + // sbt Credentials is task, so unfortunately it cannot be showed up here + scalafixInterfaceProvider + .value(scalafixResolvers.value) + .availableRules(), terminalWidth = Some(JLineAccess.terminalWidth), allowedTargetFilesPrefixes = (scalafix / unmanagedSourceDirectories).value.map(_.toPath), @@ -395,9 +436,11 @@ object ScalafixPlugin extends AutoPlugin { scalafixHelp } else { val scalafixConf = (config / scalafixConfig).value.map(_.toPath) + val resolvers = + (adaptSbtResolvers.value ++ scalafixResolvers.value).distinct val (shell, mainInterface0) = scalafixArgsFromShell( shellArgs, - scalafixInterfaceProvider.value, + () => scalafixInterfaceProvider.value(resolvers), scalafixInterfaceCache.value, projectDepsExternal, (ThisBuild / scalafixDependencies).value, @@ -432,7 +475,7 @@ object ScalafixPlugin extends AutoPlugin { private def scalafixHelp: Def.Initialize[Task[Unit]] = Def.task { scalafixInterfaceProvider - .value() + .value((adaptSbtResolvers.value ++ scalafixResolvers.value).distinct) .withArgs(Arg.ParsedArgs(List("--help"))) .run() () From 655eaac611e14176644f0b9dbdb07bfcd98f00f6 Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Tue, 12 Mar 2024 08:23:07 +0800 Subject: [PATCH 02/24] chore: remove accidental change --- .jvmopts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.jvmopts b/.jvmopts index b45d2db8..d188d8a5 100644 --- a/.jvmopts +++ b/.jvmopts @@ -3,5 +3,4 @@ -Xmx4G -XX:ReservedCodeCacheSize=1024m -XX:+TieredCompilation --Dfile.encoding=UTF-8 --Dadd-opens=java.base/java.util=ALL-UNNAMED +-Dfile.encoding=UTF-8 \ No newline at end of file From 39faeb63b36b72cc2e88ef7785c4947feae4d58f Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Tue, 12 Mar 2024 08:31:01 +0800 Subject: [PATCH 03/24] refactor: comments --- src/main/scala/scalafix/sbt/ScalafixPlugin.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index dad84866..e60d8391 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -169,7 +169,7 @@ object ScalafixPlugin extends AutoPlugin { ) if (adaptedRepo.isEmpty) { stdoutLogger.warn( - s"Defined resolver $resolver cannot be converted to coursier repository, thus will be ignored by scalafix." + s"Defined resolver $resolver cannot be converted to coursier repository, it will be ignored by scalafix." ) } adaptedRepo @@ -340,7 +340,7 @@ object ScalafixPlugin extends AutoPlugin { workingDirectory = (ThisBuild / baseDirectory).value.toPath, loadedRules = () => scalafixInterfaceProvider - // sbt Credentials is task, so unfortunately it cannot be showed up here + // sbt Credentials is a task, so unfortunately it cannot be showed up here .value(scalafixResolvers.value) .availableRules(), terminalWidth = Some(JLineAccess.terminalWidth), @@ -396,7 +396,7 @@ object ScalafixPlugin extends AutoPlugin { new ScalafixCompletions( workingDirectory = (ThisBuild / baseDirectory).value.toPath, loadedRules = () => - // sbt Credentials is task, so unfortunately it cannot be showed up here + // sbt Credentials is a task, so unfortunately it cannot be showed up here scalafixInterfaceProvider .value(scalafixResolvers.value) .availableRules(), From 981734b990bc56f34048a8cd462e6d2fe60ed3fc Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Tue, 12 Mar 2024 08:46:10 +0800 Subject: [PATCH 04/24] refactor: scoped all scalafixResolvers setting --- src/main/scala/scalafix/sbt/ScalafixPlugin.scala | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index e60d8391..a807d16d 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -341,7 +341,7 @@ object ScalafixPlugin extends AutoPlugin { loadedRules = () => scalafixInterfaceProvider // sbt Credentials is a task, so unfortunately it cannot be showed up here - .value(scalafixResolvers.value) + .value((ThisBuild / scalafixResolvers).value) .availableRules(), terminalWidth = Some(JLineAccess.terminalWidth), allowedTargetFilesPrefixes = Nil, @@ -398,7 +398,7 @@ object ScalafixPlugin extends AutoPlugin { loadedRules = () => // sbt Credentials is a task, so unfortunately it cannot be showed up here scalafixInterfaceProvider - .value(scalafixResolvers.value) + .value((ThisBuild / scalafixResolvers).value) .availableRules(), terminalWidth = Some(JLineAccess.terminalWidth), allowedTargetFilesPrefixes = @@ -437,14 +437,14 @@ object ScalafixPlugin extends AutoPlugin { } else { val scalafixConf = (config / scalafixConfig).value.map(_.toPath) val resolvers = - (adaptSbtResolvers.value ++ scalafixResolvers.value).distinct + (adaptSbtResolvers.value ++ (ThisBuild / scalafixResolvers).value).distinct val (shell, mainInterface0) = scalafixArgsFromShell( shellArgs, () => scalafixInterfaceProvider.value(resolvers), scalafixInterfaceCache.value, projectDepsExternal, (ThisBuild / scalafixDependencies).value, - (ThisBuild / scalafixResolvers).value, + resolvers, projectDepsInternal ) val maybeNoCache = @@ -474,8 +474,10 @@ object ScalafixPlugin extends AutoPlugin { private def scalafixHelp: Def.Initialize[Task[Unit]] = Def.task { + val resolvers = + (adaptSbtResolvers.value ++ (ThisBuild / scalafixResolvers).value).distinct scalafixInterfaceProvider - .value((adaptSbtResolvers.value ++ scalafixResolvers.value).distinct) + .value(resolvers) .withArgs(Arg.ParsedArgs(List("--help"))) .run() () From 6b9c692b4b50b90ef91b74f25b79b8932775addb Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Tue, 16 Apr 2024 09:46:16 +0800 Subject: [PATCH 05/24] explicit type --- .../scala/scalafix/sbt/ScalafixPlugin.scala | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index a807d16d..3e604afb 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -2,16 +2,15 @@ package scalafix.sbt import java.io.PrintStream import java.nio.file.{Path, Paths} - import coursierapi.Repository import sbt.KeyRanks.Invisible -import sbt.Keys._ -import sbt._ +import sbt.Keys.* +import sbt.{Def, *} import sbt.internal.sbtscalafix.JLineAccess import sbt.plugins.JvmPlugin import scalafix.interfaces.{ScalafixError, ScalafixMainCallback} import scalafix.internal.sbt.Arg.ToolClasspath -import scalafix.internal.sbt._ +import scalafix.internal.sbt.* import scala.collection.JavaConverters.collectionAsScalaIterableConverter import scala.util.control.NoStackTrace @@ -150,31 +149,32 @@ object ScalafixPlugin extends AutoPlugin { Invisible ) - private val adaptSbtResolvers = Def.task { - val credentialsByHost = Credentials - .allDirect(credentials.value) - .map(dc => - dc.host -> coursierapi.Credentials.of( - dc.userName, - dc.passwd + private val adaptSbtResolvers: Def.Initialize[Task[Seq[Repository]]] = + Def.task { + val credentialsByHost = Credentials + .allDirect(credentials.value) + .map(dc => + dc.host -> coursierapi.Credentials.of( + dc.userName, + dc.passwd + ) ) - ) - .toMap + .toMap - resolvers.value.flatMap(resolver => { - val adaptedRepo = CoursierRepoResolvers.repository( - resolver, - stdoutLogger, - credentialsByHost - ) - if (adaptedRepo.isEmpty) { - stdoutLogger.warn( - s"Defined resolver $resolver cannot be converted to coursier repository, it will be ignored by scalafix." + resolvers.value.flatMap(resolver => { + val adaptedRepo = CoursierRepoResolvers.repository( + resolver, + stdoutLogger, + credentialsByHost ) - } - adaptedRepo - }) - } + if (adaptedRepo.isEmpty) { + stdoutLogger.warn( + s"Defined resolver $resolver cannot be converted to coursier repository, it will be ignored by scalafix." + ) + } + adaptedRepo + }) + } private lazy val cachingStyle = { val useLastModifiedCachingStyle = From 50d5d529db3b99143ccd766b31a11755c8653a8c Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Tue, 16 Apr 2024 09:47:50 +0800 Subject: [PATCH 06/24] remove redundant log --- src/main/scala/scalafix/sbt/ScalafixPlugin.scala | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index 3e604afb..27fa4baf 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -162,17 +162,11 @@ object ScalafixPlugin extends AutoPlugin { .toMap resolvers.value.flatMap(resolver => { - val adaptedRepo = CoursierRepoResolvers.repository( + CoursierRepoResolvers.repository( resolver, stdoutLogger, credentialsByHost ) - if (adaptedRepo.isEmpty) { - stdoutLogger.warn( - s"Defined resolver $resolver cannot be converted to coursier repository, it will be ignored by scalafix." - ) - } - adaptedRepo }) } From 9363f7ada80e77a77ee867d740bf3f51d398a24a Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Tue, 16 Apr 2024 09:49:37 +0800 Subject: [PATCH 07/24] use task dedicated logger --- src/main/scala/scalafix/sbt/ScalafixPlugin.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index 27fa4baf..0fee5ba0 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -151,6 +151,8 @@ object ScalafixPlugin extends AutoPlugin { private val adaptSbtResolvers: Def.Initialize[Task[Seq[Repository]]] = Def.task { + val logger = streams.value.log + val credentialsByHost = Credentials .allDirect(credentials.value) .map(dc => @@ -164,7 +166,7 @@ object ScalafixPlugin extends AutoPlugin { resolvers.value.flatMap(resolver => { CoursierRepoResolvers.repository( resolver, - stdoutLogger, + logger, credentialsByHost ) }) From 4cd03cd5aeb75e0004aad207e922f04323313c3e Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Tue, 16 Apr 2024 23:14:28 +0800 Subject: [PATCH 08/24] scoped adaptedSbtResolvers --- .../scala/scalafix/sbt/ScalafixPlugin.scala | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index 0fee5ba0..3878a4f1 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -149,28 +149,11 @@ object ScalafixPlugin extends AutoPlugin { Invisible ) - private val adaptSbtResolvers: Def.Initialize[Task[Seq[Repository]]] = - Def.task { - val logger = streams.value.log - - val credentialsByHost = Credentials - .allDirect(credentials.value) - .map(dc => - dc.host -> coursierapi.Credentials.of( - dc.userName, - dc.passwd - ) - ) - .toMap - - resolvers.value.flatMap(resolver => { - CoursierRepoResolvers.repository( - resolver, - logger, - credentialsByHost - ) - }) - } + private val scalafixAdaptedSbtResolvers: TaskKey[Seq[Repository]] = TaskKey( + "scalafixAdaptedSbtResolvers", + "Implementation detail - do not use", + Invisible + ) private lazy val cachingStyle = { val useLastModifiedCachingStyle = @@ -264,6 +247,27 @@ object ScalafixPlugin extends AutoPlugin { ToolClasspath, ScalafixInterface ], + scalafixAdaptedSbtResolvers := { + val logger = streams.value.log + + val credentialsByHost = Credentials + .allDirect(credentials.value) + .map(dc => + dc.host -> coursierapi.Credentials.of( + dc.userName, + dc.passwd + ) + ) + .toMap + + resolvers.value.flatMap(resolver => { + CoursierRepoResolvers.repository( + resolver, + logger, + credentialsByHost + ) + }) + }, concurrentRestrictions += Tags.exclusiveGroup(Scalafix) ) @@ -433,7 +437,7 @@ object ScalafixPlugin extends AutoPlugin { } else { val scalafixConf = (config / scalafixConfig).value.map(_.toPath) val resolvers = - (adaptSbtResolvers.value ++ (ThisBuild / scalafixResolvers).value).distinct + ((ThisBuild / scalafixAdaptedSbtResolvers).value ++ (ThisBuild / scalafixResolvers).value).distinct val (shell, mainInterface0) = scalafixArgsFromShell( shellArgs, () => scalafixInterfaceProvider.value(resolvers), @@ -471,7 +475,7 @@ object ScalafixPlugin extends AutoPlugin { private def scalafixHelp: Def.Initialize[Task[Unit]] = Def.task { val resolvers = - (adaptSbtResolvers.value ++ (ThisBuild / scalafixResolvers).value).distinct + ((ThisBuild / scalafixAdaptedSbtResolvers).value ++ (ThisBuild / scalafixResolvers).value).distinct scalafixInterfaceProvider .value(resolvers) .withArgs(Arg.ParsedArgs(List("--help"))) From 927004576699f601e0ebecbd1d8a82f8825f2594 Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 00:12:26 +0800 Subject: [PATCH 09/24] move scalafixAdaptSbtResolvers to buildSettings --- .../scala/scalafix/sbt/ScalafixPlugin.scala | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index 3878a4f1..fa4ec1a6 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -149,8 +149,8 @@ object ScalafixPlugin extends AutoPlugin { Invisible ) - private val scalafixAdaptedSbtResolvers: TaskKey[Seq[Repository]] = TaskKey( - "scalafixAdaptedSbtResolvers", + private val scalafixAdaptSbtResolvers: TaskKey[Seq[Repository]] = TaskKey( + "scalafixAdaptSbtResolvers", "Implementation detail - do not use", Invisible ) @@ -247,32 +247,32 @@ object ScalafixPlugin extends AutoPlugin { ToolClasspath, ScalafixInterface ], - scalafixAdaptedSbtResolvers := { - val logger = streams.value.log - - val credentialsByHost = Credentials - .allDirect(credentials.value) - .map(dc => - dc.host -> coursierapi.Credentials.of( - dc.userName, - dc.passwd - ) - ) - .toMap - - resolvers.value.flatMap(resolver => { - CoursierRepoResolvers.repository( - resolver, - logger, - credentialsByHost - ) - }) - }, concurrentRestrictions += Tags.exclusiveGroup(Scalafix) ) override def buildSettings: Seq[Def.Setting[_]] = Seq( + scalafixAdaptedSbtResolvers := { + val logger = streams.value.log + + val credentialsByHost = Credentials + .allDirect(credentials.value) + .map(dc => + dc.host -> coursierapi.Credentials.of( + dc.userName, + dc.passwd + ) + ) + .toMap + + resolvers.value.flatMap(resolver => { + CoursierRepoResolvers.repository( + resolver, + logger, + credentialsByHost + ) + }) + }, scalafixScalaBinaryVersion := "2.12", scalafixJGitCompletion := new JGitCompletion(baseDirectory.value.toPath) ) @@ -437,7 +437,7 @@ object ScalafixPlugin extends AutoPlugin { } else { val scalafixConf = (config / scalafixConfig).value.map(_.toPath) val resolvers = - ((ThisBuild / scalafixAdaptedSbtResolvers).value ++ (ThisBuild / scalafixResolvers).value).distinct + ((ThisBuild / scalafixAdaptSbtResolvers).value ++ (ThisBuild / scalafixResolvers).value).distinct val (shell, mainInterface0) = scalafixArgsFromShell( shellArgs, () => scalafixInterfaceProvider.value(resolvers), @@ -475,7 +475,7 @@ object ScalafixPlugin extends AutoPlugin { private def scalafixHelp: Def.Initialize[Task[Unit]] = Def.task { val resolvers = - ((ThisBuild / scalafixAdaptedSbtResolvers).value ++ (ThisBuild / scalafixResolvers).value).distinct + ((ThisBuild / scalafixAdaptSbtResolvers).value ++ (ThisBuild / scalafixResolvers).value).distinct scalafixInterfaceProvider .value(resolvers) .withArgs(Arg.ParsedArgs(List("--help"))) From 05de29561cab94e0aa915afb800467d925ea84e0 Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 00:12:41 +0800 Subject: [PATCH 10/24] +sbt scripted test for adapt sbt resolvers --- src/sbt-test/sbt-scalafix/scalafixResolvers/build.sbt | 6 ++++++ .../sbt-scalafix/scalafixResolvers/project/plugins.sbt | 2 ++ .../sbt-scalafix/scalafixResolvers/src/main/scala/A.scala | 1 + src/sbt-test/sbt-scalafix/scalafixResolvers/test | 3 +++ 4 files changed, 12 insertions(+) create mode 100644 src/sbt-test/sbt-scalafix/scalafixResolvers/build.sbt create mode 100644 src/sbt-test/sbt-scalafix/scalafixResolvers/project/plugins.sbt create mode 100644 src/sbt-test/sbt-scalafix/scalafixResolvers/src/main/scala/A.scala create mode 100644 src/sbt-test/sbt-scalafix/scalafixResolvers/test diff --git a/src/sbt-test/sbt-scalafix/scalafixResolvers/build.sbt b/src/sbt-test/sbt-scalafix/scalafixResolvers/build.sbt new file mode 100644 index 00000000..edfe5617 --- /dev/null +++ b/src/sbt-test/sbt-scalafix/scalafixResolvers/build.sbt @@ -0,0 +1,6 @@ +ThisBuild / scalafixDependencies := List( + // Custom rule cross-published to Maven Central https://github.com/scalacenter/example-scalafix-rule + "ch.epfl.scala" %% "example-scalafix-rule" % "4.0.0+3-e9850db5-SNAPSHOT" +) + +ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots") diff --git a/src/sbt-test/sbt-scalafix/scalafixResolvers/project/plugins.sbt b/src/sbt-test/sbt-scalafix/scalafixResolvers/project/plugins.sbt new file mode 100644 index 00000000..d100b2a5 --- /dev/null +++ b/src/sbt-test/sbt-scalafix/scalafixResolvers/project/plugins.sbt @@ -0,0 +1,2 @@ +addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) + diff --git a/src/sbt-test/sbt-scalafix/scalafixResolvers/src/main/scala/A.scala b/src/sbt-test/sbt-scalafix/scalafixResolvers/src/main/scala/A.scala new file mode 100644 index 00000000..528ffce7 --- /dev/null +++ b/src/sbt-test/sbt-scalafix/scalafixResolvers/src/main/scala/A.scala @@ -0,0 +1 @@ +object A \ No newline at end of file diff --git a/src/sbt-test/sbt-scalafix/scalafixResolvers/test b/src/sbt-test/sbt-scalafix/scalafixResolvers/test new file mode 100644 index 00000000..13ac60d4 --- /dev/null +++ b/src/sbt-test/sbt-scalafix/scalafixResolvers/test @@ -0,0 +1,3 @@ +# even resolver was only set for sbt resolvers, dependency fetching works fine and scalafix can be used normally +> scalafix SyntacticRule +> scalafix --check SyntacticRule \ No newline at end of file From 62d9157313e4fcaad36dce2ac772cbe37a552d33 Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 09:24:40 +0800 Subject: [PATCH 11/24] fix typo --- src/main/scala/scalafix/sbt/ScalafixPlugin.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index fa4ec1a6..0d9227ee 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -252,7 +252,7 @@ object ScalafixPlugin extends AutoPlugin { override def buildSettings: Seq[Def.Setting[_]] = Seq( - scalafixAdaptedSbtResolvers := { + scalafixAdaptSbtResolvers := { val logger = streams.value.log val credentialsByHost = Credentials From 7e764a9763b22b7c3bec0437c4d352cc8b2b6c8f Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 09:32:52 +0800 Subject: [PATCH 12/24] refactor scripted test --- src/sbt-test/sbt-scalafix/resolvers/build.sbt | 7 +++++++ .../{scalafixResolvers => resolvers}/project/plugins.sbt | 0 .../src/main/scala/A.scala | 0 src/sbt-test/sbt-scalafix/resolvers/test | 7 +++++++ src/sbt-test/sbt-scalafix/scalafixResolvers/build.sbt | 6 ------ src/sbt-test/sbt-scalafix/scalafixResolvers/test | 3 --- 6 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 src/sbt-test/sbt-scalafix/resolvers/build.sbt rename src/sbt-test/sbt-scalafix/{scalafixResolvers => resolvers}/project/plugins.sbt (100%) rename src/sbt-test/sbt-scalafix/{scalafixResolvers => resolvers}/src/main/scala/A.scala (100%) create mode 100644 src/sbt-test/sbt-scalafix/resolvers/test delete mode 100644 src/sbt-test/sbt-scalafix/scalafixResolvers/build.sbt delete mode 100644 src/sbt-test/sbt-scalafix/scalafixResolvers/test diff --git a/src/sbt-test/sbt-scalafix/resolvers/build.sbt b/src/sbt-test/sbt-scalafix/resolvers/build.sbt new file mode 100644 index 00000000..4cadc389 --- /dev/null +++ b/src/sbt-test/sbt-scalafix/resolvers/build.sbt @@ -0,0 +1,7 @@ +ThisBuild / scalafixDependencies := List( + "ch.epfl.scala" %% "example-scalafix-rule" % "4.0.0+3-e9850db5-SNAPSHOT" +) + +import scala.collection.JavaConverters.collectionAsScalaIterableConverter + +ThisBuild / scalafixResolvers := coursierapi.Repository.defaults().asScala.toSeq diff --git a/src/sbt-test/sbt-scalafix/scalafixResolvers/project/plugins.sbt b/src/sbt-test/sbt-scalafix/resolvers/project/plugins.sbt similarity index 100% rename from src/sbt-test/sbt-scalafix/scalafixResolvers/project/plugins.sbt rename to src/sbt-test/sbt-scalafix/resolvers/project/plugins.sbt diff --git a/src/sbt-test/sbt-scalafix/scalafixResolvers/src/main/scala/A.scala b/src/sbt-test/sbt-scalafix/resolvers/src/main/scala/A.scala similarity index 100% rename from src/sbt-test/sbt-scalafix/scalafixResolvers/src/main/scala/A.scala rename to src/sbt-test/sbt-scalafix/resolvers/src/main/scala/A.scala diff --git a/src/sbt-test/sbt-scalafix/resolvers/test b/src/sbt-test/sbt-scalafix/resolvers/test new file mode 100644 index 00000000..44419892 --- /dev/null +++ b/src/sbt-test/sbt-scalafix/resolvers/test @@ -0,0 +1,7 @@ +# without the proper resolver/repository, invocation of the community rule fails +-> scalafix SyntacticRule + +# once the proper resolver is setup via sbt, dependency fetching works fine and scalafix can be used normally +> set ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots") +> scalafix SyntacticRule +> scalafix --check SyntacticRule \ No newline at end of file diff --git a/src/sbt-test/sbt-scalafix/scalafixResolvers/build.sbt b/src/sbt-test/sbt-scalafix/scalafixResolvers/build.sbt deleted file mode 100644 index edfe5617..00000000 --- a/src/sbt-test/sbt-scalafix/scalafixResolvers/build.sbt +++ /dev/null @@ -1,6 +0,0 @@ -ThisBuild / scalafixDependencies := List( - // Custom rule cross-published to Maven Central https://github.com/scalacenter/example-scalafix-rule - "ch.epfl.scala" %% "example-scalafix-rule" % "4.0.0+3-e9850db5-SNAPSHOT" -) - -ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots") diff --git a/src/sbt-test/sbt-scalafix/scalafixResolvers/test b/src/sbt-test/sbt-scalafix/scalafixResolvers/test deleted file mode 100644 index 13ac60d4..00000000 --- a/src/sbt-test/sbt-scalafix/scalafixResolvers/test +++ /dev/null @@ -1,3 +0,0 @@ -# even resolver was only set for sbt resolvers, dependency fetching works fine and scalafix can be used normally -> scalafix SyntacticRule -> scalafix --check SyntacticRule \ No newline at end of file From 528399b008d30de4c2144275a419862e3aa03db0 Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 15:53:02 +0800 Subject: [PATCH 13/24] scalafmt --- src/sbt-test/sbt-scalafix/resolvers/project/plugins.sbt | 1 - src/sbt-test/sbt-scalafix/resolvers/src/main/scala/A.scala | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sbt-test/sbt-scalafix/resolvers/project/plugins.sbt b/src/sbt-test/sbt-scalafix/resolvers/project/plugins.sbt index d100b2a5..843726fa 100644 --- a/src/sbt-test/sbt-scalafix/resolvers/project/plugins.sbt +++ b/src/sbt-test/sbt-scalafix/resolvers/project/plugins.sbt @@ -1,2 +1 @@ addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % sys.props("plugin.version")) - diff --git a/src/sbt-test/sbt-scalafix/resolvers/src/main/scala/A.scala b/src/sbt-test/sbt-scalafix/resolvers/src/main/scala/A.scala index 528ffce7..69c493db 100644 --- a/src/sbt-test/sbt-scalafix/resolvers/src/main/scala/A.scala +++ b/src/sbt-test/sbt-scalafix/resolvers/src/main/scala/A.scala @@ -1 +1 @@ -object A \ No newline at end of file +object A From 08398507559ee26ecdfd35a4e39fe54dd79fe55f Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 16:19:12 +0800 Subject: [PATCH 14/24] style --- src/main/scala/scalafix/sbt/ScalafixPlugin.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index 0d9227ee..8b4806ba 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -257,12 +257,12 @@ object ScalafixPlugin extends AutoPlugin { val credentialsByHost = Credentials .allDirect(credentials.value) - .map(dc => + .map { dc => dc.host -> coursierapi.Credentials.of( dc.userName, dc.passwd ) - ) + } .toMap resolvers.value.flatMap(resolver => { From 6d3daadefaa9a6c3db5726c16b20aa8d9ff3ecbb Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 16:21:24 +0800 Subject: [PATCH 15/24] style --- src/main/scala/scalafix/sbt/ScalafixPlugin.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index 8b4806ba..30587ed9 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -265,13 +265,13 @@ object ScalafixPlugin extends AutoPlugin { } .toMap - resolvers.value.flatMap(resolver => { + resolvers.value.flatMap { resolver => CoursierRepoResolvers.repository( resolver, logger, credentialsByHost ) - }) + } }, scalafixScalaBinaryVersion := "2.12", scalafixJGitCompletion := new JGitCompletion(baseDirectory.value.toPath) From 17df69210c94895bf4b8cbcf06a2fd80b0f37f2d Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 16:23:27 +0800 Subject: [PATCH 16/24] import style --- src/main/scala/scalafix/sbt/ScalafixPlugin.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index 30587ed9..4de8720d 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -5,7 +5,7 @@ import java.nio.file.{Path, Paths} import coursierapi.Repository import sbt.KeyRanks.Invisible import sbt.Keys.* -import sbt.{Def, *} +import sbt.* import sbt.internal.sbtscalafix.JLineAccess import sbt.plugins.JvmPlugin import scalafix.interfaces.{ScalafixError, ScalafixMainCallback} From cb156738df530107a508e49ef078b27b578c1017 Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 16:26:50 +0800 Subject: [PATCH 17/24] reorder the resolvers in order to prioritize scalafixResolvers --- src/main/scala/scalafix/sbt/ScalafixPlugin.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index 4de8720d..d0efbc60 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -437,7 +437,7 @@ object ScalafixPlugin extends AutoPlugin { } else { val scalafixConf = (config / scalafixConfig).value.map(_.toPath) val resolvers = - ((ThisBuild / scalafixAdaptSbtResolvers).value ++ (ThisBuild / scalafixResolvers).value).distinct + ((ThisBuild / scalafixResolvers).value ++ (ThisBuild / scalafixAdaptSbtResolvers).value).distinct val (shell, mainInterface0) = scalafixArgsFromShell( shellArgs, () => scalafixInterfaceProvider.value(resolvers), @@ -475,7 +475,7 @@ object ScalafixPlugin extends AutoPlugin { private def scalafixHelp: Def.Initialize[Task[Unit]] = Def.task { val resolvers = - ((ThisBuild / scalafixAdaptSbtResolvers).value ++ (ThisBuild / scalafixResolvers).value).distinct + ((ThisBuild / scalafixResolvers).value ++ (ThisBuild / scalafixAdaptSbtResolvers).value).distinct scalafixInterfaceProvider .value(resolvers) .withArgs(Arg.ParsedArgs(List("--help"))) From edc6b1259da08e41ad9f6136f0807ee4b11a278b Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 16:41:05 +0800 Subject: [PATCH 18/24] make sure scalafix actually ran on test file --- src/sbt-test/sbt-scalafix/resolvers/test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sbt-test/sbt-scalafix/resolvers/test b/src/sbt-test/sbt-scalafix/resolvers/test index 44419892..eaeac052 100644 --- a/src/sbt-test/sbt-scalafix/resolvers/test +++ b/src/sbt-test/sbt-scalafix/resolvers/test @@ -3,5 +3,5 @@ # once the proper resolver is setup via sbt, dependency fetching works fine and scalafix can be used normally > set ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots") -> scalafix SyntacticRule -> scalafix --check SyntacticRule \ No newline at end of file +-> scalafix --check SyntacticRule +> scalafix SyntacticRule \ No newline at end of file From 7be4ab93f01007ff87eee7ae4942ee272522d9ec Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 16:48:49 +0800 Subject: [PATCH 19/24] recover from any errors when loadRules --- .../scala/scalafix/sbt/ScalafixPlugin.scala | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index d0efbc60..c2dbd195 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -16,6 +16,8 @@ import scala.collection.JavaConverters.collectionAsScalaIterableConverter import scala.util.control.NoStackTrace import sbt.librarymanagement.ResolveException +import scala.util.Try + object ScalafixPlugin extends AutoPlugin { override def trigger: PluginTrigger = allRequirements override def requires: Plugins = JvmPlugin @@ -339,10 +341,15 @@ object ScalafixPlugin extends AutoPlugin { new ScalafixCompletions( workingDirectory = (ThisBuild / baseDirectory).value.toPath, loadedRules = () => - scalafixInterfaceProvider - // sbt Credentials is a task, so unfortunately it cannot be showed up here - .value((ThisBuild / scalafixResolvers).value) - .availableRules(), + // since the introduce of scalafixSbtResolversAsCoursierRepositories + // loading rules here without converted sbt resolvers could cause trying to download dependencies that unable to resolve + // we simply recover it to empty external rules to maintain the main task runs well + Try { + scalafixInterfaceProvider + // sbt Credentials is a task, so unfortunately it cannot be showed up here + .value((ThisBuild / scalafixResolvers).value) + .availableRules() + }.getOrElse(Seq.empty), terminalWidth = Some(JLineAccess.terminalWidth), allowedTargetFilesPrefixes = Nil, jgitCompletion = scalafixJGitCompletion.value @@ -396,10 +403,15 @@ object ScalafixPlugin extends AutoPlugin { new ScalafixCompletions( workingDirectory = (ThisBuild / baseDirectory).value.toPath, loadedRules = () => - // sbt Credentials is a task, so unfortunately it cannot be showed up here - scalafixInterfaceProvider - .value((ThisBuild / scalafixResolvers).value) - .availableRules(), + // since the introduce of scalafixSbtResolversAsCoursierRepositories + // loading rules here without converted sbt resolvers could cause trying to download dependencies that unable to resolve + // we simply recover it to empty external rules to maintain the main task runs well + Try { + scalafixInterfaceProvider + // sbt Credentials is a task, so unfortunately it cannot be showed up here + .value((ThisBuild / scalafixResolvers).value) + .availableRules() + }.getOrElse(Seq.empty), terminalWidth = Some(JLineAccess.terminalWidth), allowedTargetFilesPrefixes = (scalafix / unmanagedSourceDirectories).value.map(_.toPath), From 687b3e17493e25c22310bef77c768675bdb0d963 Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 16:49:36 +0800 Subject: [PATCH 20/24] rename task --- src/main/scala/scalafix/sbt/ScalafixPlugin.scala | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index c2dbd195..1d871848 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -151,8 +151,9 @@ object ScalafixPlugin extends AutoPlugin { Invisible ) - private val scalafixAdaptSbtResolvers: TaskKey[Seq[Repository]] = TaskKey( - "scalafixAdaptSbtResolvers", + private val scalafixSbtResolversAsCoursierRepositories + : TaskKey[Seq[Repository]] = TaskKey( + "scalafixSbtResolversAsCoursierRepositories", "Implementation detail - do not use", Invisible ) @@ -254,7 +255,7 @@ object ScalafixPlugin extends AutoPlugin { override def buildSettings: Seq[Def.Setting[_]] = Seq( - scalafixAdaptSbtResolvers := { + scalafixSbtResolversAsCoursierRepositories := { val logger = streams.value.log val credentialsByHost = Credentials @@ -449,7 +450,7 @@ object ScalafixPlugin extends AutoPlugin { } else { val scalafixConf = (config / scalafixConfig).value.map(_.toPath) val resolvers = - ((ThisBuild / scalafixResolvers).value ++ (ThisBuild / scalafixAdaptSbtResolvers).value).distinct + ((ThisBuild / scalafixResolvers).value ++ (ThisBuild / scalafixSbtResolversAsCoursierRepositories).value).distinct val (shell, mainInterface0) = scalafixArgsFromShell( shellArgs, () => scalafixInterfaceProvider.value(resolvers), @@ -487,7 +488,7 @@ object ScalafixPlugin extends AutoPlugin { private def scalafixHelp: Def.Initialize[Task[Unit]] = Def.task { val resolvers = - ((ThisBuild / scalafixResolvers).value ++ (ThisBuild / scalafixAdaptSbtResolvers).value).distinct + ((ThisBuild / scalafixResolvers).value ++ (ThisBuild / scalafixSbtResolversAsCoursierRepositories).value).distinct scalafixInterfaceProvider .value(resolvers) .withArgs(Arg.ParsedArgs(List("--help"))) From bf64b784623d59fb4d3aeccabf3d4b90164c63e0 Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 17:15:15 +0800 Subject: [PATCH 21/24] use compatible keys --- src/sbt-test/sbt-scalafix/resolvers/test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sbt-test/sbt-scalafix/resolvers/test b/src/sbt-test/sbt-scalafix/resolvers/test index eaeac052..69e89301 100644 --- a/src/sbt-test/sbt-scalafix/resolvers/test +++ b/src/sbt-test/sbt-scalafix/resolvers/test @@ -2,6 +2,6 @@ -> scalafix SyntacticRule # once the proper resolver is setup via sbt, dependency fetching works fine and scalafix can be used normally -> set ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots") +> set ThisBuild / resolvers += Resolver.sonatypeRepo("snapshots") -> scalafix --check SyntacticRule > scalafix SyntacticRule \ No newline at end of file From e24799e70d09a95ededec2c33f3015c14008e5a2 Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 17:19:01 +0800 Subject: [PATCH 22/24] extract parser into dedicated def --- .../scala/scalafix/sbt/ScalafixPlugin.scala | 64 +++++++------------ 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index 1d871848..3a83b5f0 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -7,6 +7,7 @@ import sbt.KeyRanks.Invisible import sbt.Keys.* import sbt.* import sbt.internal.sbtscalafix.JLineAccess +import sbt.internal.util.complete.Parser import sbt.plugins.JvmPlugin import scalafix.interfaces.{ScalafixError, ScalafixMainCallback} import scalafix.internal.sbt.Arg.ToolClasspath @@ -141,6 +142,27 @@ object ScalafixPlugin extends AutoPlugin { Invisible ) + private def scalafixParser: Def.Initialize[Parser[ShellArgs]] = + Def.setting( + new ScalafixCompletions( + workingDirectory = (ThisBuild / baseDirectory).value.toPath, + loadedRules = () => + // `scalafixDependencies` might be resolvable only from one of the + // `scalafixSbtResolversAsCoursierRepositories` that we can't look up + // here, as it's a task and we are in a settings context. Therefore + // we fallback to an empty list of rules in case of resolution error + // to keep providing completions for the rest. + Try { + scalafixInterfaceProvider + .value((ThisBuild / scalafixResolvers).value) + .availableRules() + }.getOrElse(Seq.empty), + terminalWidth = Some(JLineAccess.terminalWidth), + allowedTargetFilesPrefixes = Nil, + jgitCompletion = scalafixJGitCompletion.value + ) + )(_.parser) + // Memoize ScalafixInterface instances initialized with a custom tool classpath across projects & configurations // during task execution, to amortize the classloading cost when invoking scalafix concurrently on many targets private val scalafixInterfaceCache @@ -338,26 +360,8 @@ object ScalafixPlugin extends AutoPlugin { } private def scalafixAllInputTask(): Def.Initialize[InputTask[Unit]] = { - val parser = Def.setting( - new ScalafixCompletions( - workingDirectory = (ThisBuild / baseDirectory).value.toPath, - loadedRules = () => - // since the introduce of scalafixSbtResolversAsCoursierRepositories - // loading rules here without converted sbt resolvers could cause trying to download dependencies that unable to resolve - // we simply recover it to empty external rules to maintain the main task runs well - Try { - scalafixInterfaceProvider - // sbt Credentials is a task, so unfortunately it cannot be showed up here - .value((ThisBuild / scalafixResolvers).value) - .availableRules() - }.getOrElse(Seq.empty), - terminalWidth = Some(JLineAccess.terminalWidth), - allowedTargetFilesPrefixes = Nil, - jgitCompletion = scalafixJGitCompletion.value - ) - )(_.parser) // workaround https://github.com/sbt/sbt/issues/3572 by invoking directly what Def.inputTaskDyn would via macro - InputTask.createDyn(InputTask.initParserAsInput(parser))( + InputTask.createDyn(InputTask.initParserAsInput(scalafixParser))( Def.task(shellArgs => scalafixAllTask(shellArgs, thisProject.value, resolvedScoped.value) ) @@ -400,29 +404,9 @@ object ScalafixPlugin extends AutoPlugin { private def scalafixInputTask( config: Configuration ): Def.Initialize[InputTask[Unit]] = { - val parser = Def.setting( - new ScalafixCompletions( - workingDirectory = (ThisBuild / baseDirectory).value.toPath, - loadedRules = () => - // since the introduce of scalafixSbtResolversAsCoursierRepositories - // loading rules here without converted sbt resolvers could cause trying to download dependencies that unable to resolve - // we simply recover it to empty external rules to maintain the main task runs well - Try { - scalafixInterfaceProvider - // sbt Credentials is a task, so unfortunately it cannot be showed up here - .value((ThisBuild / scalafixResolvers).value) - .availableRules() - }.getOrElse(Seq.empty), - terminalWidth = Some(JLineAccess.terminalWidth), - allowedTargetFilesPrefixes = - (scalafix / unmanagedSourceDirectories).value.map(_.toPath), - jgitCompletion = scalafixJGitCompletion.value - ) - )(_.parser) - // workaround https://github.com/sbt/sbt/issues/3572 by invoking directly what Def.inputTaskDyn would via macro InputTask - .createDyn(InputTask.initParserAsInput(parser))( + .createDyn(InputTask.initParserAsInput(scalafixParser))( Def.task(shellArgs => scalafixTask(shellArgs, config)) ) } From 05538e2a4557ae83d091c751b45ad1e04f1203d3 Mon Sep 17 00:00:00 2001 From: GreyPlane <709327148@qq.com> Date: Wed, 17 Apr 2024 17:29:13 +0800 Subject: [PATCH 23/24] refactor test --- src/sbt-test/sbt-scalafix/resolvers/test | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sbt-test/sbt-scalafix/resolvers/test b/src/sbt-test/sbt-scalafix/resolvers/test index 69e89301..e97030e8 100644 --- a/src/sbt-test/sbt-scalafix/resolvers/test +++ b/src/sbt-test/sbt-scalafix/resolvers/test @@ -4,4 +4,5 @@ # once the proper resolver is setup via sbt, dependency fetching works fine and scalafix can be used normally > set ThisBuild / resolvers += Resolver.sonatypeRepo("snapshots") -> scalafix --check SyntacticRule -> scalafix SyntacticRule \ No newline at end of file +> scalafix SyntacticRule +> scalafix --check SyntacticRule \ No newline at end of file From 2ddd9cc5e8ace38053d371274cb43e05aafe0804 Mon Sep 17 00:00:00 2001 From: Brice Jaglin Date: Wed, 17 Apr 2024 12:40:03 +0200 Subject: [PATCH 24/24] allowedTargetFilesPrefixes should be non-empty for scalafix task --- .../scala/scalafix/sbt/ScalafixPlugin.scala | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala index 3a83b5f0..6fd38862 100644 --- a/src/main/scala/scalafix/sbt/ScalafixPlugin.scala +++ b/src/main/scala/scalafix/sbt/ScalafixPlugin.scala @@ -143,7 +143,11 @@ object ScalafixPlugin extends AutoPlugin { ) private def scalafixParser: Def.Initialize[Parser[ShellArgs]] = - Def.setting( + Def.setting { + val allowedTargetFilesPrefixes = + // only set in a config-level scope (i.e. scalafix, and not scalafixAll) + (scalafix / unmanagedSourceDirectories).?.value.toSeq.flatten + .map(_.toPath) new ScalafixCompletions( workingDirectory = (ThisBuild / baseDirectory).value.toPath, loadedRules = () => @@ -158,10 +162,10 @@ object ScalafixPlugin extends AutoPlugin { .availableRules() }.getOrElse(Seq.empty), terminalWidth = Some(JLineAccess.terminalWidth), - allowedTargetFilesPrefixes = Nil, + allowedTargetFilesPrefixes = allowedTargetFilesPrefixes, jgitCompletion = scalafixJGitCompletion.value ) - )(_.parser) + }(_.parser) // Memoize ScalafixInterface instances initialized with a custom tool classpath across projects & configurations // during task execution, to amortize the classloading cost when invoking scalafix concurrently on many targets @@ -405,10 +409,9 @@ object ScalafixPlugin extends AutoPlugin { config: Configuration ): Def.Initialize[InputTask[Unit]] = { // workaround https://github.com/sbt/sbt/issues/3572 by invoking directly what Def.inputTaskDyn would via macro - InputTask - .createDyn(InputTask.initParserAsInput(scalafixParser))( - Def.task(shellArgs => scalafixTask(shellArgs, config)) - ) + InputTask.createDyn(InputTask.initParserAsInput(scalafixParser))( + Def.task(shellArgs => scalafixTask(shellArgs, config)) + ) } private def scalafixTask(