From 3dee01e9ff73deeb1024a54eeb5610af794d8b9a Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Wed, 30 Aug 2023 13:30:04 +0200 Subject: [PATCH 1/5] Fix Migrate classloader --- .../interfaces/CompilationUnit.java | 2 +- .../interfaces/FileWithErrorReporter.java | 2 +- .../interfaces/MigrateReporter.java | 4 ++-- .../{ => compiler}/interfaces/QuietReporter.java | 2 +- .../interfaces/Scala3Compiler.java | 2 +- .../{ => compiler}/interfaces/Scala3Driver.java | 2 +- .../main/java/migrate/interfaces/Migrate.java | 16 +++++++--------- .../src/main/scala/migrate/Scala3Migrate.scala | 4 ++-- .../scala/migrate/internal/FileMigration.scala | 2 +- .../migrate/internal/FileMigrationState.scala | 4 ++-- migrate/src/test/scala/migrate/Values.scala | 2 +- .../main/scala/migrate/ScalaMigratePlugin.scala | 7 ++++--- 12 files changed, 24 insertions(+), 25 deletions(-) rename interfaces/compiler/src/main/java/migrate/{ => compiler}/interfaces/CompilationUnit.java (83%) rename interfaces/compiler/src/main/java/migrate/{ => compiler}/interfaces/FileWithErrorReporter.java (94%) rename interfaces/compiler/src/main/java/migrate/{ => compiler}/interfaces/MigrateReporter.java (93%) rename interfaces/compiler/src/main/java/migrate/{ => compiler}/interfaces/QuietReporter.java (87%) rename interfaces/compiler/src/main/java/migrate/{ => compiler}/interfaces/Scala3Compiler.java (98%) rename interfaces/compiler/src/main/java/migrate/{ => compiler}/interfaces/Scala3Driver.java (93%) diff --git a/interfaces/compiler/src/main/java/migrate/interfaces/CompilationUnit.java b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/CompilationUnit.java similarity index 83% rename from interfaces/compiler/src/main/java/migrate/interfaces/CompilationUnit.java rename to interfaces/compiler/src/main/java/migrate/compiler/interfaces/CompilationUnit.java index bba920da..4395933a 100644 --- a/interfaces/compiler/src/main/java/migrate/interfaces/CompilationUnit.java +++ b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/CompilationUnit.java @@ -1,4 +1,4 @@ -package migrate.interfaces; +package migrate.compiler.interfaces; public class CompilationUnit { public String content; diff --git a/interfaces/compiler/src/main/java/migrate/interfaces/FileWithErrorReporter.java b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/FileWithErrorReporter.java similarity index 94% rename from interfaces/compiler/src/main/java/migrate/interfaces/FileWithErrorReporter.java rename to interfaces/compiler/src/main/java/migrate/compiler/interfaces/FileWithErrorReporter.java index 93187e9b..29aa9af6 100644 --- a/interfaces/compiler/src/main/java/migrate/interfaces/FileWithErrorReporter.java +++ b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/FileWithErrorReporter.java @@ -1,4 +1,4 @@ -package migrate.interfaces; +package migrate.compiler.interfaces; import dotty.tools.dotc.core.Contexts.Context; import dotty.tools.dotc.reporting.Diagnostic; diff --git a/interfaces/compiler/src/main/java/migrate/interfaces/MigrateReporter.java b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/MigrateReporter.java similarity index 93% rename from interfaces/compiler/src/main/java/migrate/interfaces/MigrateReporter.java rename to interfaces/compiler/src/main/java/migrate/compiler/interfaces/MigrateReporter.java index 13a40ec8..2886f654 100644 --- a/interfaces/compiler/src/main/java/migrate/interfaces/MigrateReporter.java +++ b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/MigrateReporter.java @@ -1,8 +1,8 @@ -package migrate.interfaces; +package migrate.compiler.interfaces; import dotty.tools.dotc.reporting.*; import dotty.tools.dotc.core.Contexts.*; - +import migrate.interfaces.Logger; // a copy of DelegatingReporter // https://github.com/lampepfl/dotty/blob/b9b1f2a083c4b3ef130fbb70c7da1956b144e2a1/sbt-bridge/src/xsbt/DelegatingReporter.java diff --git a/interfaces/compiler/src/main/java/migrate/interfaces/QuietReporter.java b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/QuietReporter.java similarity index 87% rename from interfaces/compiler/src/main/java/migrate/interfaces/QuietReporter.java rename to interfaces/compiler/src/main/java/migrate/compiler/interfaces/QuietReporter.java index 73f617ee..7f0ea32e 100644 --- a/interfaces/compiler/src/main/java/migrate/interfaces/QuietReporter.java +++ b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/QuietReporter.java @@ -1,4 +1,4 @@ -package migrate.interfaces; +package migrate.compiler.interfaces; import dotty.tools.dotc.core.Contexts.Context; import dotty.tools.dotc.reporting.Diagnostic; diff --git a/interfaces/compiler/src/main/java/migrate/interfaces/Scala3Compiler.java b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/Scala3Compiler.java similarity index 98% rename from interfaces/compiler/src/main/java/migrate/interfaces/Scala3Compiler.java rename to interfaces/compiler/src/main/java/migrate/compiler/interfaces/Scala3Compiler.java index 49a88990..267a54c3 100644 --- a/interfaces/compiler/src/main/java/migrate/interfaces/Scala3Compiler.java +++ b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/Scala3Compiler.java @@ -1,4 +1,4 @@ -package migrate.interfaces; +package migrate.compiler.interfaces; import dotty.tools.dotc.Compiler; import dotty.tools.dotc.Run; diff --git a/interfaces/compiler/src/main/java/migrate/interfaces/Scala3Driver.java b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/Scala3Driver.java similarity index 93% rename from interfaces/compiler/src/main/java/migrate/interfaces/Scala3Driver.java rename to interfaces/compiler/src/main/java/migrate/compiler/interfaces/Scala3Driver.java index ec9361db..1d294ac0 100644 --- a/interfaces/compiler/src/main/java/migrate/interfaces/Scala3Driver.java +++ b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/Scala3Driver.java @@ -1,4 +1,4 @@ -package migrate.interfaces; +package migrate.compiler.interfaces; import dotty.tools.dotc.Driver; import dotty.tools.dotc.core.Contexts.Context; diff --git a/interfaces/migrate/src/main/java/migrate/interfaces/Migrate.java b/interfaces/migrate/src/main/java/migrate/interfaces/Migrate.java index 42399e66..505a9e6a 100644 --- a/interfaces/migrate/src/main/java/migrate/interfaces/Migrate.java +++ b/interfaces/migrate/src/main/java/migrate/interfaces/Migrate.java @@ -36,19 +36,16 @@ void migrateSyntax(List unmanagedSources, List scala2CompilerOptions, Path baseDirectory); - - // Todo: Maybe using ServiceLoader could simplify this code a bit: - // https://www.baeldung.com/java-spi - static Migrate fetchAndClassloadInstance(String migrateVersion, String scalaVersion, Logger logger) throws Exception { + static ClassLoader getClassLoader(String migrateVersion, String scalaVersion) throws Exception { List jars = getJars(migrateVersion, scalaVersion); - ClassLoader parent = new MigrateClassloader(Migrate.class.getClassLoader()); URLClassLoader classLoader = new URLClassLoader(jars.stream().toArray(URL[]::new), parent); - - return classloadInstance(classLoader, logger); + return classLoader; } - static Migrate classloadInstance(URLClassLoader classLoader, Logger logger) throws Exception { + // Todo: Maybe using ServiceLoader could simplify this code a bit: + // https://www.baeldung.com/java-spi + static Migrate getInstance(ClassLoader classLoader, Logger logger) throws Exception { Class cls = classLoader.loadClass("migrate.interfaces.MigrateImpl"); Constructor ctor = cls.getDeclaredConstructor(Logger.class); ctor.setAccessible(true); @@ -59,7 +56,8 @@ static Migrate classloadInstance(URLClassLoader classLoader, Logger logger) thro static List getJars(String migrateVersion, String scalaVersion) throws Exception { ScalaVersion scalaV = ScalaVersion.of(scalaVersion); Dependency migrate = Dependency.parse("ch.epfl.scala::scala3-migrate-core:" + migrateVersion, scalaV); - return fetch(Collections.singletonList(migrate), ResolutionParams.create()); + List jars = fetch(Collections.singletonList(migrate), ResolutionParams.create()); + return jars; } static List fetch(List dependencies, ResolutionParams resolutionParams) throws Exception { diff --git a/migrate/src/main/scala/migrate/Scala3Migrate.scala b/migrate/src/main/scala/migrate/Scala3Migrate.scala index 6248a511..9a648d39 100644 --- a/migrate/src/main/scala/migrate/Scala3Migrate.scala +++ b/migrate/src/main/scala/migrate/Scala3Migrate.scala @@ -4,9 +4,9 @@ import scala.util.Failure import scala.util.Success import scala.util.Try -import migrate.interfaces.CompilationUnit +import migrate.compiler.interfaces.CompilationUnit +import migrate.compiler.interfaces.Scala3Compiler import migrate.interfaces.Logger -import migrate.interfaces.Scala3Compiler import migrate.internal._ import migrate.utils.FileUtils import migrate.utils.Format._ diff --git a/migrate/src/main/scala/migrate/internal/FileMigration.scala b/migrate/src/main/scala/migrate/internal/FileMigration.scala index 5f9f6ccc..edf0bf72 100644 --- a/migrate/src/main/scala/migrate/internal/FileMigration.scala +++ b/migrate/src/main/scala/migrate/internal/FileMigration.scala @@ -6,8 +6,8 @@ import scala.util.Success import scala.util.Try import scala.util.control.NonFatal +import migrate.compiler.interfaces.Scala3Compiler import migrate.interfaces.Logger -import migrate.interfaces.Scala3Compiler import migrate.utils.Format._ import migrate.utils.Timer._ import scalafix.interfaces.ScalafixPatch diff --git a/migrate/src/main/scala/migrate/internal/FileMigrationState.scala b/migrate/src/main/scala/migrate/internal/FileMigrationState.scala index 8741952b..3f0f1b36 100644 --- a/migrate/src/main/scala/migrate/internal/FileMigrationState.scala +++ b/migrate/src/main/scala/migrate/internal/FileMigrationState.scala @@ -3,9 +3,9 @@ package migrate.internal import scala.jdk.OptionConverters._ import scala.util.Try -import migrate.interfaces.CompilationUnit +import migrate.compiler.interfaces.CompilationUnit +import migrate.compiler.interfaces.Scala3Compiler import migrate.interfaces.Logger -import migrate.interfaces.Scala3Compiler import migrate.utils.ScalaExtensions._ import scalafix.interfaces._ diff --git a/migrate/src/test/scala/migrate/Values.scala b/migrate/src/test/scala/migrate/Values.scala index b07d30a0..c6cb4c0b 100644 --- a/migrate/src/test/scala/migrate/Values.scala +++ b/migrate/src/test/scala/migrate/Values.scala @@ -1,6 +1,6 @@ package migrate -import migrate.interfaces.Scala3Compiler +import migrate.compiler.interfaces.Scala3Compiler import migrate.internal.AbsolutePath import migrate.internal.Classpath import migrate.test.BuildInfo diff --git a/plugin/src/main/scala/migrate/ScalaMigratePlugin.scala b/plugin/src/main/scala/migrate/ScalaMigratePlugin.scala index 049ffe17..8536ff5d 100644 --- a/plugin/src/main/scala/migrate/ScalaMigratePlugin.scala +++ b/plugin/src/main/scala/migrate/ScalaMigratePlugin.scala @@ -33,12 +33,13 @@ case class Scala2Inputs( ) object ScalaMigratePlugin extends AutoPlugin { - private[migrate] val syntheticsOn = "-P:semanticdb:synthetics:on" - private[migrate] val migrationOn = "-source:3.0-migration" + private val syntheticsOn = "-P:semanticdb:synthetics:on" + private val migrationOn = "-source:3.0-migration" + private val classLoader = Migrate.getClassLoader(BuildInfo.version, BuildInfo.scalaBinaryVersion) private[migrate] def getMigrateInstance(logger: Logger) = { val migrateLogger = new ScalaMigrateLogger(logger) - Migrate.fetchAndClassloadInstance(BuildInfo.version, BuildInfo.scalaBinaryVersion, migrateLogger) + Migrate.getInstance(classLoader, migrateLogger) } private[migrate] val inputsStore: mutable.Map[Scope, Scala2Inputs] = mutable.Map() From 8bb4c347ccc26a0618061a58de200b87f3cae049 Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Wed, 30 Aug 2023 15:41:55 +0200 Subject: [PATCH 2/5] Fix formatting of implicit conversion --- .../input/src/main/scala/implicits/Clue.scala | 16 +++++++++ .../src/main/scala/implicits/Clue.scala | 15 ++++++++ .../output/src/main/scala/implicits/Mix.scala | 2 +- .../scala/incompat/ScalafixIncompat11.scala | 2 +- .../src/main/scala/migrate/Simple.scala | 2 +- .../main/scala/types/ImplicitConversion.scala | 2 +- .../scala/migrate/ExplicitImplicitsRule.scala | 36 ++++++++++--------- .../src/main/scala/migrate/MigrateRule.scala | 7 ++-- 8 files changed, 58 insertions(+), 24 deletions(-) create mode 100644 scalafix/input/src/main/scala/implicits/Clue.scala create mode 100644 scalafix/output/src/main/scala/implicits/Clue.scala diff --git a/scalafix/input/src/main/scala/implicits/Clue.scala b/scalafix/input/src/main/scala/implicits/Clue.scala new file mode 100644 index 00000000..60072f4d --- /dev/null +++ b/scalafix/input/src/main/scala/implicits/Clue.scala @@ -0,0 +1,16 @@ +/* +rule = [MigrationRule] +*/ +package implicits + +class Clue + +object Clue { + implicit def generate(any: Any): Clue = new Clue +} + +object TestClue { + def test(clue: Clue): Unit = () + + test("foo") +} diff --git a/scalafix/output/src/main/scala/implicits/Clue.scala b/scalafix/output/src/main/scala/implicits/Clue.scala new file mode 100644 index 00000000..6229d489 --- /dev/null +++ b/scalafix/output/src/main/scala/implicits/Clue.scala @@ -0,0 +1,15 @@ +package implicits + +class Clue + +object Clue { + implicit def generate(any: Any): Clue = new Clue +} + +object TestClue { + def test(clue: Clue): Unit = () + + test(implicits.Clue.generate("foo")) +} + + diff --git a/scalafix/output/src/main/scala/implicits/Mix.scala b/scalafix/output/src/main/scala/implicits/Mix.scala index 4ec632d9..1dc7697e 100644 --- a/scalafix/output/src/main/scala/implicits/Mix.scala +++ b/scalafix/output/src/main/scala/implicits/Mix.scala @@ -8,7 +8,7 @@ object Mix { def firstFunction()(implicit listAge: List[Int], name: String): String = s"$name" - val test: Int = FromStrinToInt(firstFunction()(listInt, name)) + val test: Int = implicits.OptionalConversion.FromStrinToInt(firstFunction()(listInt, name)) } diff --git a/scalafix/output/src/main/scala/incompat/ScalafixIncompat11.scala b/scalafix/output/src/main/scala/incompat/ScalafixIncompat11.scala index 641b13d9..9b2a3a5b 100644 --- a/scalafix/output/src/main/scala/incompat/ScalafixIncompat11.scala +++ b/scalafix/output/src/main/scala/incompat/ScalafixIncompat11.scala @@ -9,7 +9,7 @@ object Incompat11 { val status: Int = 0 } implicit class RichFuture[T](future: Future[T]) { - def await(implicit duration: Duration = DurationInt(10).seconds): T = Await.result[T](future, duration) + def await(implicit duration: Duration = scala.concurrent.duration.DurationInt(10).seconds): T = Await.result[T](future, duration) } def test: Int = incompat.Incompat11.RichFuture(Future.apply[Foo](new Foo())(global)).await.status } \ No newline at end of file diff --git a/scalafix/output/src/main/scala/migrate/Simple.scala b/scalafix/output/src/main/scala/migrate/Simple.scala index 82f6fb28..ec58d793 100644 --- a/scalafix/output/src/main/scala/migrate/Simple.scala +++ b/scalafix/output/src/main/scala/migrate/Simple.scala @@ -16,7 +16,7 @@ object Simple { import Person._ implicit val crazy1: Int = implicitly[Int](age) - val minute: FiniteDuration = DurationInt(1).minute + val minute: FiniteDuration = scala.concurrent.duration.DurationInt(1).minute } object Person { diff --git a/scalafix/output/src/main/scala/types/ImplicitConversion.scala b/scalafix/output/src/main/scala/types/ImplicitConversion.scala index c734d1bd..86a2237a 100644 --- a/scalafix/output/src/main/scala/types/ImplicitConversion.scala +++ b/scalafix/output/src/main/scala/types/ImplicitConversion.scala @@ -6,5 +6,5 @@ import cats.syntax.option._ final case class IorT[F[_], A, B](value: F[Ior[A, B]]) { final def fromOptionF[F[_], E, A](foption: F[Option[A]], ifNone: => E)(implicit F: Functor[F]): IorT[F, E, A] = - IorT.apply[F, E, A](F.map[Option[A], Ior[E,A]](foption)(catsSyntaxOption(_).toRightIor[E](ifNone))) + IorT.apply[F, E, A](F.map[Option[A], Ior[E,A]](foption)(cats.syntax.option.catsSyntaxOption(_).toRightIor[E](ifNone))) } \ No newline at end of file diff --git a/scalafix/rules/src/main/scala/migrate/ExplicitImplicitsRule.scala b/scalafix/rules/src/main/scala/migrate/ExplicitImplicitsRule.scala index 8937f553..25b95f51 100644 --- a/scalafix/rules/src/main/scala/migrate/ExplicitImplicitsRule.scala +++ b/scalafix/rules/src/main/scala/migrate/ExplicitImplicitsRule.scala @@ -16,6 +16,7 @@ import utils.ScalaExtensions._ import utils.SyntheticHelper class ExplicitImplicitsRule[G <: Global](g: G) { + private val printer = new PrettyPrinter[g.type](g) def fix(implicit doc: SemanticDocument, compilerService: CompilerService[g.type]): Patch = { val implicitParams = doc.synthetics.collect { @@ -50,32 +51,35 @@ class ExplicitImplicitsRule[G <: Global](g: G) { for { context <- compilerSrv.getContext(originalTree) (funcTree, symbols) <- collectImplicit(context.tree, originalTree) - pretty = new PrettyPrinter[g.type](g) - args <- symbols.map(gsym => pretty.print(gsym, context)).sequence + args <- symbols.map(gsym => printer.print(gsym, context)).sequence patch <- implicitParamsPatch(funcTree, originalTree, args) } yield patch def getImplicitConversions(originalTree: Tree)(implicit compilerSrv: CompilerService[g.type]): Option[String] = for { (tree, _) <- compilerSrv.getGlobalTree(originalTree) - function <- collectImplicitConversion(tree, originalTree) + function <- collectImplicitConverter(tree, originalTree) } yield function - private def collectImplicitConversion(globalTree: g.Tree, original: Tree): Option[String] = { - val collectedTree: Seq[g.Tree] = - globalTree.collect { - case t if CompilerService.equalForPositions(t.pos, original.pos) => t - }.filter(_.isInstanceOf[g.ApplyImplicitView]) - - collectedTree.collectFirst { - case g.Apply(fun: g.Select, _) => - if (fun.qualifier.symbol.isStatic) fun.name.toString - else fun.toString - case g.Apply(fun: g.TypeApply, _) => - if (fun.symbol.isStatic) fun.symbol.fullName.toString - else fun.symbol.name.toString + private def collectImplicitConverter(globalTree: g.Tree, originalTree: Tree): Option[String] = { + def funOf(tree: g.Tree): g.Tree = tree match { + case g.Apply(fun, _) => funOf(fun) + case g.TypeApply(fun, _) => funOf(fun) + case tree => tree } + def skipPackageObject(sym: g.Symbol): g.Symbol = + if (sym.isPackageObject) sym.owner + else sym + + globalTree.collect { + case t: g.ApplyImplicitView if CompilerService.equalForPositions(t.pos, originalTree.pos) => + funOf(t) match { + case fun @ g.Select(qual, _) if qual.symbol.isStatic => + skipPackageObject(qual.symbol).fullName.toString + "." + fun.name.toString + case fun => fun.toString + } + }.headOption } private def collectImplicit(globalTree: g.Tree, original: Tree): Option[(G#Tree, List[g.Symbol])] = { diff --git a/scalafix/rules/src/main/scala/migrate/MigrateRule.scala b/scalafix/rules/src/main/scala/migrate/MigrateRule.scala index 0cd1d658..f2a1a778 100644 --- a/scalafix/rules/src/main/scala/migrate/MigrateRule.scala +++ b/scalafix/rules/src/main/scala/migrate/MigrateRule.scala @@ -40,10 +40,9 @@ class MigrateRule(g: Global) extends SemanticRule("MigrationRule") { } override def fix(implicit doc: SemanticDocument): Patch = { - implicit lazy val compilerService: CompilerService[g.type] = new CompilerService(g, doc) - - val inferType = new InferTypes[g.type](g) - val explicitImplicit = new ExplicitImplicitsRule[g.type](g) + implicit val compilerService: CompilerService[g.type] = new CompilerService(g, doc) + val inferType = new InferTypes[g.type](g) + val explicitImplicit = new ExplicitImplicitsRule[g.type](g) inferType.fix + explicitImplicit.fix } } From 587d0374a1be0f5e9b055bce0443fa679c198d96 Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Wed, 30 Aug 2023 17:24:12 +0200 Subject: [PATCH 3/5] Introduce MigrationSourceFile to avoid null jpath --- .../compiler/interfaces/CompilationUnit.java | 8 ++++++-- .../compiler/interfaces/MigrationFile.java | 19 +++++++++++++++++++ .../interfaces/MigrationSourceFile.java | 18 ++++++++++++++++++ .../compiler/interfaces/Scala3Compiler.java | 2 +- .../main/scala/migrate/Scala3Migrate.scala | 4 ++-- .../migrate/internal/FileMigrationState.scala | 4 ++-- 6 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 interfaces/compiler/src/main/java/migrate/compiler/interfaces/MigrationFile.java create mode 100644 interfaces/compiler/src/main/java/migrate/compiler/interfaces/MigrationSourceFile.java diff --git a/interfaces/compiler/src/main/java/migrate/compiler/interfaces/CompilationUnit.java b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/CompilationUnit.java index 4395933a..83db3a9d 100644 --- a/interfaces/compiler/src/main/java/migrate/compiler/interfaces/CompilationUnit.java +++ b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/CompilationUnit.java @@ -1,11 +1,15 @@ package migrate.compiler.interfaces; +import java.nio.file.Path; + public class CompilationUnit { public String content; - public String name; + public String name; + public Path path; - public CompilationUnit(String name, String content) { + public CompilationUnit(String name, String content, Path path) { this.name = name; this.content = content; + this.path = path; } } diff --git a/interfaces/compiler/src/main/java/migrate/compiler/interfaces/MigrationFile.java b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/MigrationFile.java new file mode 100644 index 00000000..d113b901 --- /dev/null +++ b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/MigrationFile.java @@ -0,0 +1,19 @@ +package migrate.compiler.interfaces; + +import dotty.tools.io.VirtualFile; +import java.nio.file.Path; + +class MigrationFile extends VirtualFile { + private Path _jpath; + + public MigrationFile(String name, Path path) { + super(name, path.toString()); + this._jpath = path; + } + + @Override + public Path jpath() { + return _jpath; + } + +} diff --git a/interfaces/compiler/src/main/java/migrate/compiler/interfaces/MigrationSourceFile.java b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/MigrationSourceFile.java new file mode 100644 index 00000000..c40083b1 --- /dev/null +++ b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/MigrationSourceFile.java @@ -0,0 +1,18 @@ +package migrate.compiler.interfaces; + +import dotty.tools.dotc.util.SourceFile; +import java.nio.file.Path; + +class MigrationSourceFile extends SourceFile { + private char[] _content; + + public MigrationSourceFile(String content, String name, Path path) { + super(new MigrationFile(name, path), null); + this._content = content.toCharArray(); + } + + @Override + public char[] content() { + return _content; + } +} diff --git a/interfaces/compiler/src/main/java/migrate/compiler/interfaces/Scala3Compiler.java b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/Scala3Compiler.java index 267a54c3..9150bcc7 100644 --- a/interfaces/compiler/src/main/java/migrate/compiler/interfaces/Scala3Compiler.java +++ b/interfaces/compiler/src/main/java/migrate/compiler/interfaces/Scala3Compiler.java @@ -26,7 +26,7 @@ public class Scala3Compiler { private Function1 toSourceFile = new AbstractFunction1() { public SourceFile apply(CompilationUnit unit) { - return SourceFile$.MODULE$.virtual(unit.name, unit.content, false); + return new MigrationSourceFile(unit.content, unit.name, unit.path); } }; diff --git a/migrate/src/main/scala/migrate/Scala3Migrate.scala b/migrate/src/main/scala/migrate/Scala3Migrate.scala index 9a648d39..2619c073 100644 --- a/migrate/src/main/scala/migrate/Scala3Migrate.scala +++ b/migrate/src/main/scala/migrate/Scala3Migrate.scala @@ -115,7 +115,7 @@ class Scala3Migrate(scalafixSrv: ScalafixService, logger: Logger) { ): Try[Unit] = for { cuUnmanagedSources <- migrationFiles.map(_.previewAllPatches()).sequence - cuManagedSources = managedSources.map(path => new CompilationUnit(path.value, FileUtils.read(path))) + cuManagedSources = managedSources.map(path => new CompilationUnit(path.value, FileUtils.read(path), path.toNio)) _ <- timeAndLog(Try(compiler.compileAndReport((cuUnmanagedSources ++ cuManagedSources).toList, logger))) { case (finiteDuration, Success(_)) => logger.info(s"Scala 3 compilation succeeded after $finiteDuration") @@ -128,7 +128,7 @@ class Scala3Migrate(scalafixSrv: ScalafixService, logger: Logger) { files: Seq[AbsolutePath], compiler: Scala3Compiler ): Seq[AbsolutePath] = { - val compilationUnits = files.map(path => new CompilationUnit(path.value, FileUtils.read(path))) + val compilationUnits = files.map(path => new CompilationUnit(path.value, FileUtils.read(path), path.toNio)) val res = compiler.compileAndReportFilesWithErrors(compilationUnits.toList).toSeq res.map(AbsolutePath.from(_)).sequence.getOrElse(Nil) } diff --git a/migrate/src/main/scala/migrate/internal/FileMigrationState.scala b/migrate/src/main/scala/migrate/internal/FileMigrationState.scala index 3f0f1b36..fcf7f492 100644 --- a/migrate/src/main/scala/migrate/internal/FileMigrationState.scala +++ b/migrate/src/main/scala/migrate/internal/FileMigrationState.scala @@ -20,7 +20,7 @@ sealed trait FileMigrationState { evaluation .previewPatches() .map { content => - new CompilationUnit(source.value, content) + new CompilationUnit(source.value, content, source.toNio) } .toScala .toTry { @@ -35,7 +35,7 @@ sealed trait FileMigrationState { evaluation .previewPatches(patches.toArray) .map { content => - new CompilationUnit(source.value, content) + new CompilationUnit(source.value, content, source.toNio) } .toScala .toTry { From 7570216bd60da0c4bbae584e688a99ab03e2df0e Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Wed, 30 Aug 2023 18:28:40 +0200 Subject: [PATCH 4/5] Rework migrateTypes logs --- .../main/scala/migrate/Scala3Migrate.scala | 66 +++++++-------- .../migrate/interfaces/MigrateImpl.scala | 4 +- .../migrate/internal/FileMigration.scala | 15 ++-- .../migrate/internal/FileMigrationState.scala | 32 ++++---- migrate/src/test/scala/migrate/Values.scala | 6 +- .../main/scala/migrate/SyntaxMigration.scala | 4 +- .../migrate/TypeInferenceMigration.scala | 81 ++++++------------- 7 files changed, 85 insertions(+), 123 deletions(-) diff --git a/migrate/src/main/scala/migrate/Scala3Migrate.scala b/migrate/src/main/scala/migrate/Scala3Migrate.scala index 2619c073..b805d3e1 100644 --- a/migrate/src/main/scala/migrate/Scala3Migrate.scala +++ b/migrate/src/main/scala/migrate/Scala3Migrate.scala @@ -15,28 +15,26 @@ import migrate.utils.ScalafixService import migrate.utils.Timer._ import scalafix.interfaces.ScalafixEvaluation -class Scala3Migrate(scalafixSrv: ScalafixService, logger: Logger) { +class Scala3Migrate(scalafixSrv: ScalafixService, baseDirectory: AbsolutePath, logger: Logger) { def previewMigration( unmanagedSources: Seq[AbsolutePath], managedSources: Seq[AbsolutePath], compiler: Scala3Compiler ): Try[Map[AbsolutePath, FileMigrationState.FinalState]] = { - unmanagedSources.foreach(f => logger.info(s"Migrating $f")) val (scalaFiles, javaFiles) = unmanagedSources.partition(_.value.endsWith("scala")) // first try to compile without adding any patch val filesWithErr = compileInScala3AndGetFilesWithErrors(unmanagedSources ++ managedSources, compiler) - if (filesWithErr.isEmpty) { - logger.info("The project compiles successfully in Scala 3") - Success(Map[AbsolutePath, FileMigrationState.FinalState]()) - } else { + if (filesWithErr.isEmpty) { Success(Map[AbsolutePath, FileMigrationState.FinalState]()) } + else { val filesWithoutErrors = scalaFiles.diff(filesWithErr) - (for { + for { initialFileToMigrate <- buildMigrationFiles(filesWithErr) _ <- compileInScala3(initialFileToMigrate, filesWithoutErrors ++ javaFiles ++ managedSources, compiler) - migratedFiles <- - initialFileToMigrate.map(f => f.migrate(compiler, logger).map(success => (f.source, success))).sequence - } yield migratedFiles.toMap) + migratedFiles <- initialFileToMigrate + .map(f => f.migrate(compiler, logger).map(success => (f.source, success))) + .sequence + } yield migratedFiles.toMap } } @@ -48,13 +46,11 @@ class Scala3Migrate(scalafixSrv: ScalafixService, logger: Logger) { scala3ClassDirectory: AbsolutePath ): Try[Unit] = for { - compiler <- setupScala3Compiler(scala3Classpath, scala3ClassDirectory, scala3CompilerOptions) - migratedFiles <- - previewMigration(unmanagedSources, managedSources, compiler) + compiler <- setupScala3Compiler(scala3Classpath, scala3ClassDirectory, scala3CompilerOptions) + migratedFiles <- previewMigration(unmanagedSources, managedSources, compiler) _ <- migratedFiles.map { case (file, migrated) => migrated.newFileContent.flatMap(FileUtils.writeFile(file, _)) }.sequence - _ = migratedFiles.keys.map(file => logger.info(s"${file.value} has been successfully migrated")) _ <- compileWithRewrite( scala3Classpath, scala3ClassDirectory, @@ -67,11 +63,11 @@ class Scala3Migrate(scalafixSrv: ScalafixService, logger: Logger) { def previewSyntaxMigration(unmanagedSources: Seq[AbsolutePath]): Try[ScalafixEvaluation] = for { scalafixEval <- timeAndLog(scalafixSrv.fixSyntaxForScala3(unmanagedSources)) { - case (finiteDuration, Success(_)) => + case (_, Success(_)) => logger.info( - s"Run syntactic rules in ${plural(unmanagedSources.size, "file")} successfully after $finiteDuration") + s"Run syntactic rules in ${plural(unmanagedSources.size, "Scala source")} successfully") case (_, Failure(e)) => - logger.info(s"Failed running syntactic rules because: ${e.getMessage}") + logger.error(s"Failed running syntactic rules because: ${e.getMessage}") } } yield scalafixEval @@ -101,7 +97,7 @@ class Scala3Migrate(scalafixSrv: ScalafixService, logger: Logger) { unmanaged: Seq[AbsolutePath], managed: Seq[AbsolutePath] ): Try[Unit] = { - logger.info(s"Compiling in scala 3 with -rewrite option") + logger.info(s"Compiling to Scala 3 with -source:3.0-migration -rewrite") for { compilerWithRewrite <- setupScala3Compiler(classpath3, classDir3, settings3 :+ "-rewrite") _ <- Try(compilerWithRewrite.compileWithRewrite((unmanaged ++ managed).map(_.value).toList)) @@ -117,10 +113,13 @@ class Scala3Migrate(scalafixSrv: ScalafixService, logger: Logger) { cuUnmanagedSources <- migrationFiles.map(_.previewAllPatches()).sequence cuManagedSources = managedSources.map(path => new CompilationUnit(path.value, FileUtils.read(path), path.toNio)) _ <- timeAndLog(Try(compiler.compileAndReport((cuUnmanagedSources ++ cuManagedSources).toList, logger))) { - case (finiteDuration, Success(_)) => - logger.info(s"Scala 3 compilation succeeded after $finiteDuration") case (_, Failure(_)) => - logger.error("Scala 3 compilation failed. Try to fix the error(s) manually") + logger.error("Failed inferring meaningful types because: Scala 3 compilation error") + case _ => + val count = migrationFiles.map(_.patches.size).sum + val message = + s"Found ${plural(count, "patch", "patches")} in ${plural(migrationFiles.size, "Scala source")}" + logger.info(message) } } yield () @@ -137,23 +136,18 @@ class Scala3Migrate(scalafixSrv: ScalafixService, logger: Logger) { if (unmanagedSources.isEmpty) Success(Seq()) else for { - fileEvaluations <- - timeAndLog(scalafixSrv.inferTypesAndImplicits(unmanagedSources)) { - case (duration, Success(files)) => - val fileEvaluationsSeq = files.getFileEvaluations().toSeq - val count = fileEvaluationsSeq.map(_.getPatches().size).sum - logger.info( - s"Found ${plural(count, "patch", "patches")} in ${plural(unmanagedSources.size, "file")} after $duration") - case (_, Failure(e)) => - logger.error(s"Failed inferring types because: ${e.getMessage()}.") - } - fileEvaluationMap <- fileEvaluations - .getFileEvaluations() - .toSeq - .map(e => AbsolutePath.from(e.getEvaluatedFile()).map(file => file -> e)) + fileEvaluations <- timeAndLog(scalafixSrv.inferTypesAndImplicits(unmanagedSources)) { + case (_, Failure(e)) => + logger.error(s"Failed inferring types because: ${e.getMessage}") + case _ => + } + fileEvaluationMap <- fileEvaluations.getFileEvaluations.toSeq + .map(e => AbsolutePath.from(e.getEvaluatedFile).map(file => file -> e)) .sequence .map(_.toMap) fileToMigrate <- - unmanagedSources.map(src => fileEvaluationMap.get(src).map(FileMigrationState.Initial).toTry).sequence + unmanagedSources + .map(src => fileEvaluationMap.get(src).map(FileMigrationState.Initial(_, baseDirectory)).toTry) + .sequence } yield fileToMigrate } diff --git a/migrate/src/main/scala/migrate/interfaces/MigrateImpl.scala b/migrate/src/main/scala/migrate/interfaces/MigrateImpl.scala index 63fc6ff3..4b18bada 100644 --- a/migrate/src/main/scala/migrate/interfaces/MigrateImpl.scala +++ b/migrate/src/main/scala/migrate/interfaces/MigrateImpl.scala @@ -44,7 +44,7 @@ final class MigrateImpl(logger: Logger) extends Migrate { targetRootAbs, baseDirectory, logger) - scalaMigrate = new Scala3Migrate(configuredScalafixSrv, logger) + scalaMigrate = new Scala3Migrate(configuredScalafixSrv, baseDirectory, logger) _ <- scalaMigrate .migrate( unmanagedSources = unmanagedSourcesAbs, @@ -83,7 +83,7 @@ final class MigrateImpl(logger: Logger) extends Migrate { targetRootAbs, baseDirectory, logger) - scalaMigrate = new Scala3Migrate(configuredScalafixSrv, logger) + scalaMigrate = new Scala3Migrate(configuredScalafixSrv, baseDirectory, logger) _ <- scalaMigrate.migrateSyntax(unmanagedSourcesAbs) } yield ()).get } diff --git a/migrate/src/main/scala/migrate/internal/FileMigration.scala b/migrate/src/main/scala/migrate/internal/FileMigration.scala index edf0bf72..f21ab2bf 100644 --- a/migrate/src/main/scala/migrate/internal/FileMigration.scala +++ b/migrate/src/main/scala/migrate/internal/FileMigration.scala @@ -8,6 +8,7 @@ import scala.util.control.NonFatal import migrate.compiler.interfaces.Scala3Compiler import migrate.interfaces.Logger +import migrate.utils.Format import migrate.utils.Format._ import migrate.utils.Timer._ import scalafix.interfaces.ScalafixPatch @@ -22,17 +23,15 @@ private[migrate] class FileMigration( logger: Logger) { def migrate(): Try[FileMigrationState.FinalState] = { + logger.info(s"Starting migration of ${fileToMigrate.relativePath}") val initialState = CompilingState(fileToMigrate.patches, Seq.empty) timeAndLog(loopUntilNoCandidates(Success(initialState))) { - case (timeMs, Success(finalState)) => - logger.info( - s"Found ${finalState.necessaryPatches.size} required patch(es) in ${fileToMigrate.source} after $timeMs ms" - ) - case (timeMs, Failure(e)) => - logger.info( - s"Failed finding the required patches in ${fileToMigrate.source} after $timeMs ms because ${e.getMessage()}" - ) + case (_, Success(finalState)) => + val formattedPatches = Format.plural(finalState.necessaryPatches.size, "required patch", "required patches") + logger.info(s"Found $formattedPatches in ${fileToMigrate.relativePath}") + case (_, Failure(e)) => + logger.error(s"Failed to reduce the patches in ${fileToMigrate.relativePath} because: ${e.getMessage}") }.map(finalState => fileToMigrate.success(finalState.necessaryPatches)) } diff --git a/migrate/src/main/scala/migrate/internal/FileMigrationState.scala b/migrate/src/main/scala/migrate/internal/FileMigrationState.scala index fcf7f492..2ad5fb79 100644 --- a/migrate/src/main/scala/migrate/internal/FileMigrationState.scala +++ b/migrate/src/main/scala/migrate/internal/FileMigrationState.scala @@ -11,51 +11,49 @@ import scalafix.interfaces._ sealed trait FileMigrationState { val evaluation: ScalafixFileEvaluation + def baseDirectory: AbsolutePath def source: AbsolutePath = AbsolutePath.from(evaluation.getEvaluatedFile).get + def relativePath: String = source.relativize(baseDirectory).getOrElse(source).toString def patches: Seq[ScalafixPatch] = evaluation.getPatches().toSeq def previewAllPatches(): Try[CompilationUnit] = evaluation .previewPatches() - .map { content => - new CompilationUnit(source.value, content, source.toNio) - } + .map(content => new CompilationUnit(source.value, content, source.toNio)) .toScala .toTry { - val msg = - s"""|Cannot apply patch on file $source because: - |${evaluation.getErrorMessage.toScala.getOrElse("Unexpected error")} - |""".stripMargin + val error = evaluation.getErrorMessage.toScala.getOrElse("unknown error") + val msg = s"Cannot apply patch on file $relativePath because: $error" new ScalafixException(msg) } def previewPatches(patches: Seq[ScalafixPatch]): Try[CompilationUnit] = evaluation .previewPatches(patches.toArray) - .map { content => - new CompilationUnit(source.value, content, source.toNio) - } + .map(content => new CompilationUnit(source.value, content, source.toNio)) .toScala .toTry { - val msg = - s"""|Cannot apply patch on file $source because: - |${evaluation.getErrorMessage.toScala.getOrElse("Unexpected error")} - |""".stripMargin + val error = evaluation.getErrorMessage.toScala.getOrElse("unknown error") + val msg = s"Cannot apply patch on file $relativePath because: $error" new ScalafixException(msg) } } object FileMigrationState { - case class Initial(evaluation: ScalafixFileEvaluation) extends FileMigrationState { + case class Initial(evaluation: ScalafixFileEvaluation, baseDirectory: AbsolutePath) extends FileMigrationState { def migrate(compiler: Scala3Compiler, logger: Logger): Try[FileMigrationState.FinalState] = new FileMigration(this, compiler, logger).migrate() - def success(necessaryPatches: Seq[ScalafixPatch]): FinalState = FinalState(evaluation, necessaryPatches) + def success(necessaryPatches: Seq[ScalafixPatch]): FinalState = + FinalState(evaluation, necessaryPatches, baseDirectory) } - case class FinalState(evaluation: ScalafixFileEvaluation, necessaryPatches: Seq[ScalafixPatch]) + case class FinalState( + evaluation: ScalafixFileEvaluation, + necessaryPatches: Seq[ScalafixPatch], + baseDirectory: AbsolutePath) extends FileMigrationState { def newFileContent: Try[String] = previewPatches(necessaryPatches).map(_.content) } diff --git a/migrate/src/test/scala/migrate/Values.scala b/migrate/src/test/scala/migrate/Values.scala index c6cb4c0b..9154bdf1 100644 --- a/migrate/src/test/scala/migrate/Values.scala +++ b/migrate/src/test/scala/migrate/Values.scala @@ -18,11 +18,11 @@ object Values { val scala3Classpath: Classpath = Classpath.from(BuildInfo.scala3Classpath).get val scala3CompilerOptions = BuildInfo.scala3CompilerOptions val scala3ClassDirectory: AbsolutePath = AbsolutePath.from(BuildInfo.scala3ClassDirectory) - val baseDirecotry: AbsolutePath = AbsolutePath.from(BuildInfo.baseDirectory) + val baseDirectory: AbsolutePath = AbsolutePath.from(BuildInfo.baseDirectory) lazy val scalafixSrv: ScalafixService = - ScalafixService.from(scala2CompilerOptions, scala2Classpath, semanticdbTargetRoot, baseDirecotry, PrintLogger).get - val scalaMigrat = new Scala3Migrate(scalafixSrv, PrintLogger) + ScalafixService.from(scala2CompilerOptions, scala2Classpath, semanticdbTargetRoot, baseDirectory, PrintLogger).get + val scalaMigrat = new Scala3Migrate(scalafixSrv, baseDirectory, PrintLogger) val scala3Compiler: Scala3Compiler = scalaMigrat.setupScala3Compiler(scala3Classpath, scala3ClassDirectory, scala3CompilerOptions).get } diff --git a/plugin/src/main/scala/migrate/SyntaxMigration.scala b/plugin/src/main/scala/migrate/SyntaxMigration.scala index 3f614dae..ecf11967 100644 --- a/plugin/src/main/scala/migrate/SyntaxMigration.scala +++ b/plugin/src/main/scala/migrate/SyntaxMigration.scala @@ -19,7 +19,7 @@ private[migrate] object SyntaxMigration { if (!sv.startsWith("2.13.")) throw new MessageOnlyException(Messages.notScala213(sv, projectId)) - log.info(s"${BOLD}Starting migration of syntax in $projectId / [${configs.mkString(", ")}]${RESET}") + log.info(s"${BOLD}Starting migration of syntax in $projectId$RESET") Def.task { val log = streams.value.log @@ -46,7 +46,7 @@ private[migrate] object SyntaxMigration { throw cause } - log.info(s"Migration of syntax in $projectId / [${configs.mkString(", ")}] succeeded.") + log.info(s"Migration of syntax in $projectId succeeded.") } } } diff --git a/plugin/src/main/scala/migrate/TypeInferenceMigration.scala b/plugin/src/main/scala/migrate/TypeInferenceMigration.scala index 8577389f..2ffc1086 100644 --- a/plugin/src/main/scala/migrate/TypeInferenceMigration.scala +++ b/plugin/src/main/scala/migrate/TypeInferenceMigration.scala @@ -2,7 +2,6 @@ package migrate import migrate.interfaces.CompilationException import ScalaMigratePlugin.{Keys, inputsStore} -import migrate.TypeInferenceMigration.{errorMessage, successMessage} import sbt.Keys._ import sbt._ @@ -13,29 +12,20 @@ import java.nio.file.Files private[migrate] object TypeInferenceMigration { val internalImpl = Def.taskDyn { - implicit val projectRef = thisProjectRef.value - val configs = Keys.migrationConfigs.value - val sv = scalaVersion.value - implicit val projectId = projectRef.project + val projectRef = thisProjectRef.value + val configs = Keys.migrationConfigs.value + val sv = scalaVersion.value + val projectId = projectRef.project if (sv != BuildInfo.scala3Version) sys.error(s"Expecting scalaVersion to be ${BuildInfo.scala3Version}") - val logger = streams.value.log - logger.info(welcomeMessage(projectId, configs.map(_.id))) - - Def.sequential { - configs.map(migrateConfig(_)) :+ - Def.task { - val logger = streams.value.log - logger.info(finalMessage(projectId)) - } - } + Def.sequential(configs.map(migrateConfig(projectRef, projectId)(_)) :+ success(projectId)) } - private def migrateConfig( + private def migrateConfig(projectRef: ProjectRef, projectId: String)( config: Configuration - )(implicit projectRef: ProjectRef, projectId: String): Def.Initialize[Task[Unit]] = + ): Def.Initialize[Task[Unit]] = Def.task { val logger = streams.value.log val scala3Inputs = (config / Keys.scala3Inputs).value @@ -43,6 +33,8 @@ private[migrate] object TypeInferenceMigration { val scala2Inputs = inputsStore.getOrElse(scope, sys.error("no input found")) val baseDir = baseDirectory.value + logger.info(startingMessage(projectId, config.id)) + if (scala2Inputs.unmanagedSources.nonEmpty) { if (!Files.exists(scala3Inputs.classDirectory)) Files.createDirectory(scala3Inputs.classDirectory) Try { @@ -60,53 +52,32 @@ private[migrate] object TypeInferenceMigration { ) } match { case Success(_) => - logger.info(successMessage(projectId, config.id)) case Failure(_: CompilationException) => - val message = errorMessage(projectId, config.id, None) - throw new MessageOnlyException(message) - case Failure(exception) => - val message = errorMessage(projectId, config.id, Some(exception)) + val message = + s"""|Migration of $projectId / $config failed because of a compilation error. + |Fix the error and try again. + |""".stripMargin throw new MessageOnlyException(message) + case Failure(cause) => + logger.error(s"Migration of $projectId / $config failed.") + throw cause } } else logger.debug(s"There is no unmanagedSources to migrate for $config") } - private def welcomeMessage(projectId: String, configs: Seq[String]): String = + private def startingMessage(projectId: String, config: String): String = s"""| - |${BOLD}We are going to migrate $projectId / ${configs.mkString( - "[", - ", ", - "]")} to ${BuildInfo.scala3Version}${RESET} + |${BOLD}Migrating types in $projectId / $config$RESET | |""".stripMargin - private def successMessage(projectId: String, config: String): String = - s"""| - |$projectId / $config has been successfully migrated to Scala ${BuildInfo.scala3Version} - | - |""".stripMargin - - private def errorMessage(projectId: String, config: String, exceptionOpt: Option[Throwable]) = { - val exceptionError = exceptionOpt.map { error => - s"""|because of ${error.getMessage} - |${error.getStackTrace.mkString("\n")}""".stripMargin - } - .getOrElse("") - - s"""| - |Migration of $projectId / $config has failed - |$exceptionError - | - |""".stripMargin + private def success(projectId: String) = Def.task { + val logger = streams.value.log + val message = + s"""| + |You can safely upgrade $projectId to Scala 3: + |${YELLOW}scalaVersion := "${BuildInfo.scala3Version}"${RESET} + |""".stripMargin + logger.info(message) } - - private def finalMessage(projectId: String) = - s"""| - |You can now commit the change! - |Then you can permanently change the scalaVersion of $projectId: - | - |crossScalaVersions += "${BuildInfo.scala3Version}" // or - |scalaVersion := "${BuildInfo.scala3Version}" - | - |""".stripMargin } From d1b968150c4a61e72937fa8489dd8c0eca86d790 Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Wed, 30 Aug 2023 18:43:14 +0200 Subject: [PATCH 5/5] Go back to Scala 2 after migrateTypes --- .../main/scala/migrate/CommandStrings.scala | 2 +- .../scala/migrate/ScalaMigratePlugin.scala | 41 ++++++++++++++----- .../aggregate-project/build.sbt | 23 +++++++---- .../sbt-scala3-migrate/aggregate-project/test | 6 +-- .../integration-test/build.sbt | 6 +-- .../sbt-scala3-migrate/integration-test/test | 4 +- .../library-dependencies/build.sbt | 4 -- .../library-dependencies/test | 4 +- .../managed-sources/build.sbt | 4 -- .../sbt-scala3-migrate/managed-sources/test | 4 +- .../sbt-scala3-migrate/syntax-migration/test | 3 +- .../type-inference-migration/build.sbt | 6 +-- .../type-inference-migration/test | 4 +- .../unresolved-dependencies/test | 5 +-- 14 files changed, 63 insertions(+), 53 deletions(-) diff --git a/plugin/src/main/scala/migrate/CommandStrings.scala b/plugin/src/main/scala/migrate/CommandStrings.scala index d550e429..909b0ae4 100644 --- a/plugin/src/main/scala/migrate/CommandStrings.scala +++ b/plugin/src/main/scala/migrate/CommandStrings.scala @@ -54,5 +54,5 @@ object CommandStrings { |- Unclassified: sbt-scala3-migrate does not know how to migrate this dependency |""".stripMargin - val migrateFallback = "migrate-fallback" + val migrateFallback = "migrateFallback" } diff --git a/plugin/src/main/scala/migrate/ScalaMigratePlugin.scala b/plugin/src/main/scala/migrate/ScalaMigratePlugin.scala index 8536ff5d..31c8b440 100644 --- a/plugin/src/main/scala/migrate/ScalaMigratePlugin.scala +++ b/plugin/src/main/scala/migrate/ScalaMigratePlugin.scala @@ -44,7 +44,7 @@ object ScalaMigratePlugin extends AutoPlugin { private[migrate] val inputsStore: mutable.Map[Scope, Scala2Inputs] = mutable.Map() - private[migrate] object Keys { + object Keys { val scala2Version = AttributeKey[String]("scala2Version") val migrationConfigs = @@ -93,7 +93,14 @@ object ScalaMigratePlugin extends AutoPlugin { internalMigrateTypes / aggregate := false, internalMigrateDependencies := LibsMigration.internalImpl.value, internalMigrateDependencies / aggregate := false, - commands ++= Seq(migrateSyntax, migrateScalacOptions, migrateLibDependencies, migrateTypes, fallback), + commands ++= Seq( + migrateSyntax, + migrateScalacOptions, + migrateLibDependencies, + migrateTypes, + fallback, + fallbackAndFail, + migrateFail), inConfig(Compile)(configSettings), inConfig(Test)(configSettings) ) @@ -203,22 +210,36 @@ object ScalaMigratePlugin extends AutoPlugin { lazy val migrateTypes: Command = Command(migrateCommand, migrateBrief, migrateDetailed)(idParser) { (state, projectId) => + val preparedState = state.copy(attributes = state.attributes.remove(Keys.scala2Version)) val commands = List( + StashOnFailure, // stash shell from onFailure + s"$OnFailure migrateFallbackAndFail $projectId", s"$projectId / storeScala2Inputs", - setScalaVersion(projectId, BuildInfo.scala3Version), - StashOnFailure, // prepare onFailure - s"$OnFailure $migrateFallback $projectId", // go back to Scala 2.13 in case of failure + setScalaVersion(projectId, BuildInfo.scala3Version), // set Scala 3 s"$projectId / internalMigrateTypes", - FailureWall, // resume here in case of failure - PopOnFailure // remove onFailure + PopOnFailure, // pop shell to onFailure in case the fallback fails + s"$migrateFallback $projectId" // set Scala 2.13 ) - commands ::: state + commands ::: preparedState } lazy val fallback: Command = Command(migrateFallback)(idParser) { (state, projectId) => - val scala2Version = state.attributes(Keys.scala2Version) - setScalaVersion(projectId, scala2Version) :: state + state.attributes.get(Keys.scala2Version) match { + case Some(scala2Version) => setScalaVersion(projectId, scala2Version) :: state + case None => state + } + } + + lazy val fallbackAndFail: Command = + Command("migrateFallbackAndFail")(idParser) { (state, projectId) => + PopOnFailure :: s"migrateFallback $projectId" :: s"migrateFail $projectId" :: Nil ::: state + } + + lazy val migrateFail: Command = + Command("migrateFail")(idParser) { (state, projectId) => + state.log.error(s"Migration of $projectId failed.") + state.fail } private def setScalaVersion(projectId: String, scalaVersion: String): String = diff --git a/plugin/src/sbt-test/sbt-scala3-migrate/aggregate-project/build.sbt b/plugin/src/sbt-test/sbt-scala3-migrate/aggregate-project/build.sbt index 619ea56e..a3812bc9 100644 --- a/plugin/src/sbt-test/sbt-scala3-migrate/aggregate-project/build.sbt +++ b/plugin/src/sbt-test/sbt-scala3-migrate/aggregate-project/build.sbt @@ -1,15 +1,24 @@ +import migrate.ScalaMigratePlugin.Keys._ + ThisBuild / scalaVersion := "2.13.11" lazy val subproject = project .in(file("subproject")) - .settings(TaskKey[Unit]("checkNotMigrated") := { - assert(scalaVersion.value == "2.13.11") - }) + .settings( + Compile / internalMigrateDependencies := { + throw new Exception("subproject / Compile / internalMigrateDependencies") + }, + Compile / internalMigrateScalacOptions := { + throw new Exception("subproject / Compile / internalMigrateScalacOptions") + }, + Compile / internalMigrateSyntax := { + throw new Exception("subproject / Compile / internalMigrateSyntax") + }, + Compile / internalMigrateTypes := { + throw new Exception("subproject / Compile / internalMigrateTypes") + } + ) lazy val `aggregate-project` = project .in(file(".")) - .settings(TaskKey[Unit]("checkMigration") := { - assert(scalaVersion.value == "3.3.0", s"Wrong scala version ${scalaVersion.value}. Expected 3.3.0") - (Compile / compile).value - }) .aggregate(subproject) diff --git a/plugin/src/sbt-test/sbt-scala3-migrate/aggregate-project/test b/plugin/src/sbt-test/sbt-scala3-migrate/aggregate-project/test index 56901737..b2b473b3 100644 --- a/plugin/src/sbt-test/sbt-scala3-migrate/aggregate-project/test +++ b/plugin/src/sbt-test/sbt-scala3-migrate/aggregate-project/test @@ -4,7 +4,5 @@ > migrateTypes aggregate-project # check aggregate-project is migrated -> aggregate-project / checkMigration - -# check subproject is not migrated -> subproject / checkNotMigrated +> ++3.3.0! +> aggregate-project / compile diff --git a/plugin/src/sbt-test/sbt-scala3-migrate/integration-test/build.sbt b/plugin/src/sbt-test/sbt-scala3-migrate/integration-test/build.sbt index 863bab14..41fbd218 100644 --- a/plugin/src/sbt-test/sbt-scala3-migrate/integration-test/build.sbt +++ b/plugin/src/sbt-test/sbt-scala3-migrate/integration-test/build.sbt @@ -4,9 +4,5 @@ lazy val `integration-test` = project .settings( scalaVersion := "2.13.11", // Enable migration on IntegrationTest config - inConfig(IntegrationTest)(Defaults.itSettings ++ ScalaMigratePlugin.configSettings), - TaskKey[Unit]("checkMigration") := { - assert(scalaVersion.value == "3.3.0") - (IntegrationTest / compile).value - } + inConfig(IntegrationTest)(Defaults.itSettings ++ ScalaMigratePlugin.configSettings) ) diff --git a/plugin/src/sbt-test/sbt-scala3-migrate/integration-test/test b/plugin/src/sbt-test/sbt-scala3-migrate/integration-test/test index 7f89a599..72cd34c1 100644 --- a/plugin/src/sbt-test/sbt-scala3-migrate/integration-test/test +++ b/plugin/src/sbt-test/sbt-scala3-migrate/integration-test/test @@ -3,5 +3,5 @@ > migrateSyntax integration-test > migrateTypes integration-test -# check scalaVersion is Scala 3 and compilation succeeds -> integration-test / checkMigration +> ++3.3.0! +> integration-test / IntegrationTest / compile diff --git a/plugin/src/sbt-test/sbt-scala3-migrate/library-dependencies/build.sbt b/plugin/src/sbt-test/sbt-scala3-migrate/library-dependencies/build.sbt index b2772a29..b6abc4c8 100644 --- a/plugin/src/sbt-test/sbt-scala3-migrate/library-dependencies/build.sbt +++ b/plugin/src/sbt-test/sbt-scala3-migrate/library-dependencies/build.sbt @@ -11,10 +11,6 @@ lazy val `library-dependencies` = project libraryDependencies ++= { if (scalaVersion.value.startsWith("3")) Seq.empty else Seq(compilerPlugin("org.typelevel" % "kind-projector" % V.kindProjector cross CrossVersion.full)) - }, - TaskKey[Unit]("checkMigration") := { - assert(scalaVersion.value == "3.3.0", s"Wrong scala version ${scalaVersion.value}. Expected 3.3.0") - (Compile / compile).value } ) diff --git a/plugin/src/sbt-test/sbt-scala3-migrate/library-dependencies/test b/plugin/src/sbt-test/sbt-scala3-migrate/library-dependencies/test index 15248a4e..91a4cf64 100644 --- a/plugin/src/sbt-test/sbt-scala3-migrate/library-dependencies/test +++ b/plugin/src/sbt-test/sbt-scala3-migrate/library-dependencies/test @@ -3,5 +3,5 @@ > migrateSyntax library-dependencies > migrateTypes library-dependencies -# check scalaVersion is Scala 3 and compilation succeeds -> library-dependencies / checkMigration +> ++3.3.0! +> library-dependencies / compile diff --git a/plugin/src/sbt-test/sbt-scala3-migrate/managed-sources/build.sbt b/plugin/src/sbt-test/sbt-scala3-migrate/managed-sources/build.sbt index b5ff860c..51e1b9f6 100644 --- a/plugin/src/sbt-test/sbt-scala3-migrate/managed-sources/build.sbt +++ b/plugin/src/sbt-test/sbt-scala3-migrate/managed-sources/build.sbt @@ -13,9 +13,5 @@ lazy val `managed-sources` = project |""".stripMargin IO.write(file, buildInfo) Seq(file) - }, - TaskKey[Unit]("checkMigration") := { - assert(scalaVersion.value == "3.3.0", s"Wrong scala version ${scalaVersion.value}. Expected 3.3.0") - (Compile / compile).value } ) diff --git a/plugin/src/sbt-test/sbt-scala3-migrate/managed-sources/test b/plugin/src/sbt-test/sbt-scala3-migrate/managed-sources/test index 0e3e173c..e0cbf765 100644 --- a/plugin/src/sbt-test/sbt-scala3-migrate/managed-sources/test +++ b/plugin/src/sbt-test/sbt-scala3-migrate/managed-sources/test @@ -3,5 +3,5 @@ > migrateSyntax managed-sources > migrateTypes managed-sources -# check scalaVersion is Scala 3 and compilation succeeds -> managed-sources / checkMigration +> ++3.3.0! +> managed-sources / compile diff --git a/plugin/src/sbt-test/sbt-scala3-migrate/syntax-migration/test b/plugin/src/sbt-test/sbt-scala3-migrate/syntax-migration/test index 3d43d93b..c98372c3 100644 --- a/plugin/src/sbt-test/sbt-scala3-migrate/syntax-migration/test +++ b/plugin/src/sbt-test/sbt-scala3-migrate/syntax-migration/test @@ -1,5 +1,4 @@ > migrateSyntax syntax-migration -# check scalaVersion is Scala 3 and compilation succeeds -> set `syntax-migration` / scalaVersion := "3.0.2" +> ++3.3.0! > syntax-migration / Test / compile diff --git a/plugin/src/sbt-test/sbt-scala3-migrate/type-inference-migration/build.sbt b/plugin/src/sbt-test/sbt-scala3-migrate/type-inference-migration/build.sbt index 9c53f1f4..5b565111 100644 --- a/plugin/src/sbt-test/sbt-scala3-migrate/type-inference-migration/build.sbt +++ b/plugin/src/sbt-test/sbt-scala3-migrate/type-inference-migration/build.sbt @@ -1,9 +1,5 @@ lazy val `type-inference-migration` = project .in(file(".")) .settings( - scalaVersion := "2.13.11", - TaskKey[Unit]("checkMigration") := { - assert(scalaVersion.value == "3.3.0", s"Wrong scala version ${scalaVersion.value}. Expected 3.3.0") - (Test / compile).value - } + scalaVersion := "2.13.11" ) diff --git a/plugin/src/sbt-test/sbt-scala3-migrate/type-inference-migration/test b/plugin/src/sbt-test/sbt-scala3-migrate/type-inference-migration/test index 05251c6b..2dc6d6d3 100644 --- a/plugin/src/sbt-test/sbt-scala3-migrate/type-inference-migration/test +++ b/plugin/src/sbt-test/sbt-scala3-migrate/type-inference-migration/test @@ -1,4 +1,4 @@ > migrateTypes type-inference-migration -# check scalaVersion is Scala 3 and compilation succeeds -> type-inference-migration / checkMigration +> ++3.3.0! +> type-inference-migration / Test / compile diff --git a/plugin/src/sbt-test/sbt-scala3-migrate/unresolved-dependencies/test b/plugin/src/sbt-test/sbt-scala3-migrate/unresolved-dependencies/test index 30481ac3..d47c2e8c 100644 --- a/plugin/src/sbt-test/sbt-scala3-migrate/unresolved-dependencies/test +++ b/plugin/src/sbt-test/sbt-scala3-migrate/unresolved-dependencies/test @@ -1,6 +1,5 @@ -# The library dependencies of project foo have not been updated for Scala 3 -# Although migration fails, the command does not because of the fallback. It could be improved. -> migrateTypes unresolved-dependencies +# Cannot migrate types because of unresolved dependencies +-> migrateTypes unresolved-dependencies # check fallback to Scala 2.13 > unresolved-dependencies / checkFallback