From 049e4f6b4299479887cd4977aa26c03cc827af9e Mon Sep 17 00:00:00 2001 From: Meriam Lachkar Date: Thu, 10 Jun 2021 15:05:58 +0200 Subject: [PATCH] Improve messages for migrate-libs fixes #181 --- .../migrate/interfaces/MigratedLibImp.scala | 28 ++++++++++----- .../migrate/interfaces/MigratedLibsImpl.scala | 6 ++-- .../scala/migrate/internal/InitialLib.scala | 10 +++--- .../scala/migrate/internal/MigratedLib.scala | 6 +++- .../scala/migrate/utils/CoursierHelper.scala | 2 +- .../test/scala/migrate/MigrateLibsSuite.scala | 13 +++++-- .../main/scala/migrate/LibsMigration.scala | 35 +++++++++++-------- 7 files changed, 65 insertions(+), 35 deletions(-) diff --git a/migrate/src/main/scala/migrate/interfaces/MigratedLibImp.scala b/migrate/src/main/scala/migrate/interfaces/MigratedLibImp.scala index dd507ac9..a42e3637 100644 --- a/migrate/src/main/scala/migrate/interfaces/MigratedLibImp.scala +++ b/migrate/src/main/scala/migrate/interfaces/MigratedLibImp.scala @@ -1,6 +1,8 @@ package migrate.interfaces +import migrate.interfaces.InitialLibImp.Revision import migrate.interfaces.MigratedLibImp._ +import migrate.internal.ScalaVersion trait MigratedLibImp extends MigratedLib { def reason: Reason @@ -14,15 +16,23 @@ object MigratedLibImp { object Reason { case object ScalacOptionEquivalent - extends Reason("This compiler plugin has a scalacOption equivalent. Add it to your scalacOptions") - case object MacroLibrary extends Reason("Contains Macros and is not yet published for Scala 3") - case object FullVersionNotAvailable extends Reason("Requires a full version and is not yet for scala 3 ") + extends Reason("This compiler plugin has a scalacOption equivalent. Add it to your scalacOptions.") + case object MacroLibrary extends Reason("Contains Macros and is not yet published for Scala 3.") + case class FullVersionNotAvailable(scalaVersion: ScalaVersion) + extends Reason(s"This dependency hasn't been published for ${scalaVersion.value}.") case object CompilerPlugin - extends Reason("Scala 2 compiler plugins are not supported in scala 3. You need to find an alternative") - case object Scala3LibAvailable extends Reason("This dependency is published for Scala 3. ") - case object JavaLibrary extends Reason("This dependency is a Java library. It can be kept as it is. ") - case object IsAlreadyValid extends Reason("") - case object For3Use2_13 - extends Reason("This dependency is not yet published for scala 3 but the 2.13 version can be used") + extends Reason("Scala 2 compiler plugins are not supported in scala 3. You need to find an alternative.") + case class Scala3LibAvailable(otherRevisions: Seq[Revision]) + extends Reason( + if (otherRevisions.nonEmpty) s"Other versions are avaialble for Scala 3: ${printRevisions(otherRevisions)}" + else "" + ) + case object JavaLibrary extends Reason("Java libraries are compatible.") + case object IsAlreadyValid extends Reason("") + case object For3Use2_13 extends Reason("It's only safe to use the 2.13 version if it's inside an application.") + + private def printRevisions(r: Seq[Revision]): String = + if (r.size >= 3) s""""${r.head.value}", ..., "${r.last.value}"""" + else r.map(_.value).mkString("\"", "\", \"", "\"") } } diff --git a/migrate/src/main/scala/migrate/interfaces/MigratedLibsImpl.scala b/migrate/src/main/scala/migrate/interfaces/MigratedLibsImpl.scala index e5442f97..76c6a93f 100644 --- a/migrate/src/main/scala/migrate/interfaces/MigratedLibsImpl.scala +++ b/migrate/src/main/scala/migrate/interfaces/MigratedLibsImpl.scala @@ -29,9 +29,9 @@ case class MigratedLibsImpl( private def initialLibSameThanCompatible(initialLib: InitialLib, compatible: CompatibleWithScala3): Boolean = compatible match { - case keptInitialLib: CompatibleWithScala3.Lib // maybe need to be fixed - if initialLib.crossVersion == keptInitialLib.crossVersion => - true + case keptInitialLib: CompatibleWithScala3.Lib => + initialLib.crossVersion == keptInitialLib.crossVersion && + initialLib.revision == keptInitialLib.revision case _ => false } diff --git a/migrate/src/main/scala/migrate/internal/InitialLib.scala b/migrate/src/main/scala/migrate/internal/InitialLib.scala index 6f722273..464f86f6 100644 --- a/migrate/src/main/scala/migrate/internal/InitialLib.scala +++ b/migrate/src/main/scala/migrate/internal/InitialLib.scala @@ -75,7 +75,7 @@ case class InitialLib( case Some(value) => CompatibleWithScala3.ScalacOption(value) case None => this.toUncompatible(Reason.CompilerPlugin) } - } else this.toCompatibleLib(CrossVersion.Full("", ""), Reason.Scala3LibAvailable, revisions) + } else this.toCompatibleLib(CrossVersion.Full("", ""), Reason.Scala3LibAvailable(revisions.tail), revisions) } private def getCompatibleWhenBinaryCrossVersion(lib: InitialLib): MigratedLibImp = { @@ -93,7 +93,7 @@ case class InitialLib( compatibleRevisionsForScala3, CrossVersion.Binary("", ""), lib.configurations, - Reason.Scala3LibAvailable + Reason.Scala3LibAvailable(compatibleRevisionsForScala3.tail) ) else CompatibleWithScala3.Lib( @@ -102,7 +102,7 @@ case class InitialLib( compatibleRevisionsForScala3, CrossVersion.For2_13Use3("", ""), lib.configurations, - Reason.Scala3LibAvailable + Reason.Scala3LibAvailable(compatibleRevisionsForScala3.tail) ) } @@ -110,7 +110,7 @@ case class InitialLib( private def getCompatibleWhenFullCrossVersion(lib: InitialLib): MigratedLibImp = CoursierHelper.getCompatibleForScala3Full(lib) match { - case Nil => lib.toUncompatible(Reason.FullVersionNotAvailable) + case Nil => lib.toUncompatible(Reason.FullVersionNotAvailable(CoursierHelper.scala3Full)) case revisions => CompatibleWithScala3.Lib( lib.organization, @@ -118,7 +118,7 @@ case class InitialLib( revisions, CrossVersion.For2_13Use3("", ""), lib.configurations, - Reason.Scala3LibAvailable + Reason.Scala3LibAvailable(revisions.tail) ) } } diff --git a/migrate/src/main/scala/migrate/internal/MigratedLib.scala b/migrate/src/main/scala/migrate/internal/MigratedLib.scala index 78578222..dbf51fb7 100644 --- a/migrate/src/main/scala/migrate/internal/MigratedLib.scala +++ b/migrate/src/main/scala/migrate/internal/MigratedLib.scala @@ -31,9 +31,13 @@ object MigratedLib { val orgQuoted = withQuote(organization.value) val revisionQuoted = withQuote(revision.value) crossVersion match { - case CrossVersion.Disabled => s"$orgQuoted % ${withQuote(name.value)} % $revisionQuoted$configuration" + case CrossVersion.Disabled => s"$orgQuoted % ${withQuote(name.value)} % $revisionQuoted$configuration" + case CrossVersion.Binary("", "") => s"$orgQuoted %% ${withQuote(name.value)} % $revisionQuoted$configuration" + case CrossVersion.Full("", "") => s"$orgQuoted %% ${withQuote(name.value)} % $revisionQuoted$configuration" case CrossVersion.For3Use2_13(_, _) => s"$orgQuoted %% ${withQuote(name.value)} % $revisionQuoted$configuration cross CrossVersion.for3Use2_13" + case CrossVersion.For2_13Use3(_, _) => + s"$orgQuoted %% ${withQuote(name.value)} % $revisionQuoted$configuration cross CrossVersion.for2_13Use3" case _ => s"$orgQuoted % ${withQuote(name.value)} % $revisionQuoted$configuration" } } diff --git a/migrate/src/main/scala/migrate/utils/CoursierHelper.scala b/migrate/src/main/scala/migrate/utils/CoursierHelper.scala index 221c0d91..6d7179a4 100644 --- a/migrate/src/main/scala/migrate/utils/CoursierHelper.scala +++ b/migrate/src/main/scala/migrate/utils/CoursierHelper.scala @@ -11,7 +11,7 @@ import migrate.internal.ScalaVersion object CoursierHelper { implicit val ec: ExecutionContextExecutor = ExecutionContext.global - private val scala3Full: ScalaVersion = ScalaVersion.from(BuildInfo.scala3Version).get + val scala3Full: ScalaVersion = ScalaVersion.from(BuildInfo.scala3Version).get def getCompatibleForScala3Binary(lib: InitialLib): Seq[Revision] = { val revisions = searchRevisionsFor(lib, scala3Full.binary) diff --git a/migrate/src/test/scala/migrate/MigrateLibsSuite.scala b/migrate/src/test/scala/migrate/MigrateLibsSuite.scala index f0eb42c5..09eedcdf 100644 --- a/migrate/src/test/scala/migrate/MigrateLibsSuite.scala +++ b/migrate/src/test/scala/migrate/MigrateLibsSuite.scala @@ -2,7 +2,7 @@ package migrate import migrate.interfaces.InitialLibImp._ import migrate.interfaces.MigratedLib -import migrate.interfaces.MigratedLibImp +import migrate.interfaces.MigratedLibImp._ import migrate.internal.InitialLib import migrate.internal.MigratedLib._ import org.scalatest.funsuite.AnyFunSuiteLike @@ -36,7 +36,7 @@ class MigrateLibsSuite extends AnyFunSuiteLike with DiffAssertions { val migrated = Scala3Migrate.migrateLibs(Seq(opentelemetry)).allLibs val res = migrated(opentelemetry) assert(res.isCompatibleWithScala3) - assert(res.getReasonWhy == MigratedLibImp.Reason.JavaLibrary.why) + assert(res.getReasonWhy == Reason.JavaLibrary.why) assert(isTheSame(opentelemetry, res)) } test("java lib2") { @@ -82,6 +82,15 @@ class MigrateLibsSuite extends AnyFunSuiteLike with DiffAssertions { val migratedLib = Scala3Migrate.migrateLibs(Seq(scalaLib, scalajs)).allLibs assert(migratedLib.isEmpty) } + test("message for Scala3LibAvailable") { + val revisions = Seq(Revision("1"), Revision("2"), Revision("3"), Revision("4")) + val message = Reason.Scala3LibAvailable(revisions).why + assert(message == "Other versions are avaialble for Scala 3: \"1\", ..., \"4\"") + val revisions2 = Seq(Revision("1"), Revision("2")) + val message2 = Reason.Scala3LibAvailable(revisions2).why + println(s"message2 = ${message2}") + assert(message2 == "Other versions are avaialble for Scala 3: \"1\", \"2\"") + } private def isTheSame(lib: InitialLib, migrated: MigratedLib) = migrated match { diff --git a/plugin/src/main/scala/migrate/LibsMigration.scala b/plugin/src/main/scala/migrate/LibsMigration.scala index 377dae7c..57905d77 100644 --- a/plugin/src/main/scala/migrate/LibsMigration.scala +++ b/plugin/src/main/scala/migrate/LibsMigration.scala @@ -31,7 +31,7 @@ private[migrate] object LibsMigration { val validLibs = migratedLibs.getValidLibs.toSeq - log.info(migrationMessage(notMigrated, validLibs, libsToUpdate)) + log.info(migrationMessage(notMigrated, validLibs, libsToUpdate.toSeq)) } private def welcomeMessage(projectId: String): String = @@ -43,31 +43,38 @@ private[migrate] object LibsMigration { private def migrationMessage( incompatibleLibs: Seq[MigratedLib], validLibs: Seq[MigratedLib], - toUpdate: Map[Lib, MigratedLib] + toUpdate: Seq[(Lib, MigratedLib)] ): String = { val removedSign = s"""${BOLD}${RED}X${RESET}""" val validSign = s"""${BOLD}${CYAN}Valid${RESET}""" val toBeUpdated = s"""${BOLD}${BLUE}To be updated${RESET}""" - val spacesForLib = computeLongestValue((incompatibleLibs ++ validLibs ++ toUpdate.keys).map(_.toString)) + val spacesForLib = computeLongestValue((incompatibleLibs ++ validLibs ++ toUpdate.map(_._1)).map(_.toString)) def reasonWhy(lib: MigratedLib) = if (lib.getReasonWhy.isEmpty) "" else s": ${YELLOW}${lib.getReasonWhy}${RESET}" - def formatIncompatibleLibs: String = incompatibleLibs.map { lib => - s"""${formatValueWithSpace(lib.toString, spacesForLib)} -> $removedSign ${reasonWhy(lib)}""" - }.mkString("\n") + def formatIncompatibleLibs: String = incompatibleLibs + .sortBy(_.getReasonWhy) + .map { lib => + s"""${formatValueWithSpace(lib.toString, spacesForLib)} -> $removedSign ${reasonWhy(lib)}""" + } + .mkString("\n") def formatValid: String = - validLibs.map { lib => - s"""${formatValueWithSpace(lib.toString, spacesForLib)} -> $validSign ${reasonWhy(lib)}""" - } + validLibs + .sortBy(_.getReasonWhy) + .map { lib => + s"""${formatValueWithSpace(lib.toString, spacesForLib)} -> $validSign ${reasonWhy(lib)}""" + } .mkString("\n") def formatLibToUpdate: String = - toUpdate.map { case (initial, migrated) => - s"""${formatValueWithSpace(initial.toString, spacesForLib)} -> ${BLUE}${migrated.toString}$RESET ${reasonWhy( - migrated - )}""" - } + toUpdate + .sortBy(_._2.getReasonWhy) + .map { case (initial, migrated) => + s"""${formatValueWithSpace(initial.toString, spacesForLib)} -> ${BLUE}${migrated.toString}$RESET ${reasonWhy( + migrated + )}""" + } .mkString("\n") val spacesForHelp = computeLongestValue(Seq(removedSign, validSign, toBeUpdated))