From 62b4b29a321df832934c257946f3141e53aff63b Mon Sep 17 00:00:00 2001 From: Piotr Chabelski Date: Mon, 4 Nov 2024 15:09:32 +0100 Subject: [PATCH 1/2] Deprecate the `--source` command line option for the `package` sub-command --- .../commands/RestrictedCommandsParser.scala | 14 +++++++++++-- .../commands/package0/PackageOptions.scala | 7 ++++--- .../scala/scala/cli/util/ArgHelpers.scala | 21 +++++++++++++++++-- .../scala/cli/doc/GenerateReferenceDoc.scala | 6 +++++- .../integration/PackageTestDefinitions.scala | 15 ++++++++----- .../cli/commands/SpecificationLevel.scala | 7 ++++++- website/docs/reference/cli-options.md | 4 ++-- 7 files changed, 58 insertions(+), 16 deletions(-) diff --git a/modules/cli/src/main/scala/scala/cli/commands/RestrictedCommandsParser.scala b/modules/cli/src/main/scala/scala/cli/commands/RestrictedCommandsParser.scala index 09670fabc6..f49ba7b2e2 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/RestrictedCommandsParser.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/RestrictedCommandsParser.scala @@ -3,13 +3,13 @@ package scala.cli.commands import caseapp.Name import caseapp.core.app.Command import caseapp.core.parser.Parser -import caseapp.core.util.Formatter +import caseapp.core.util.{CaseUtil, Formatter} import caseapp.core.{Arg, Error} import scala.build.Logger import scala.build.input.ScalaCliInvokeData import scala.build.internal.util.WarningMessages -import scala.build.internals.FeatureType +import scala.build.internals.{ConsoleUtils, FeatureType} import scala.cli.ScalaCli import scala.cli.util.ArgHelpers.* @@ -57,6 +57,16 @@ object RestrictedCommandsParser { if arg.isExperimental && !shouldSuppressExperimentalWarnings => logger.experimentalWarning(passedOption, FeatureType.Option) r + case (r @ Right(Some(_, arg: Arg, _)), passedOption :: _) + if arg.isDeprecated => + // TODO implement proper deprecation logic: https://github.com/VirtusLab/scala-cli/issues/3258 + arg.deprecatedOptionAliases.find(_ == passedOption) + .foreach { deprecatedAlias => + logger.message( + s"""[${Console.YELLOW}warn${Console.RESET}] The $deprecatedAlias option alias has been deprecated and may be removed in a future version.""" + ) + } + r case (other, _) => other } diff --git a/modules/cli/src/main/scala/scala/cli/commands/package0/PackageOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/package0/PackageOptions.scala index b3a578a89d..4bcae6397d 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/package0/PackageOptions.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/package0/PackageOptions.scala @@ -49,10 +49,11 @@ final case class PackageOptions( @Group(HelpGroup.Package.toString) @HelpMessage("Generate a source JAR rather than an executable JAR") @Name("sources") - @Name("src") + @Name("source") + @Tag(tags.deprecated("source")) // alias to be removed in 1.6.x @Tag(tags.restricted) @Tag(tags.inShortHelp) - source: Boolean = false, + src: Boolean = false, @Group(HelpGroup.Package.toString) @HelpMessage("Generate a scaladoc JAR rather than an executable JAR") @ExtraName("scaladoc") @@ -144,7 +145,7 @@ final case class PackageOptions( def packageTypeOpt: Option[PackageType] = forcedPackageTypeOpt.orElse { if (library) Some(PackageType.LibraryJar) - else if (source) Some(PackageType.SourceJar) + else if (src) Some(PackageType.SourceJar) else if (assembly) Some( PackageType.Assembly( addPreamble = preamble, diff --git a/modules/cli/src/main/scala/scala/cli/util/ArgHelpers.scala b/modules/cli/src/main/scala/scala/cli/util/ArgHelpers.scala index 0af1067145..879c920a49 100644 --- a/modules/cli/src/main/scala/scala/cli/util/ArgHelpers.scala +++ b/modules/cli/src/main/scala/scala/cli/util/ArgHelpers.scala @@ -2,6 +2,7 @@ package scala.cli.util import caseapp.core.Arg import caseapp.core.help.HelpFormat +import caseapp.core.util.CaseUtil import scala.build.input.ScalaCliInvokeData import scala.build.internal.util.WarningMessages @@ -12,8 +13,24 @@ import scala.cli.commands.{SpecificationLevel, tags} object ArgHelpers { extension (arg: Arg) { private def hasTag(tag: String): Boolean = arg.tags.exists(_.name == tag) - def isExperimental: Boolean = arg.hasTag(tags.experimental) - def isRestricted: Boolean = arg.hasTag(tags.restricted) + private def hasTagPrefix(tagPrefix: String): Boolean = + arg.tags.exists(_.name.startsWith(tagPrefix)) + def isExperimental: Boolean = arg.hasTag(tags.experimental) + def isRestricted: Boolean = arg.hasTag(tags.restricted) + def isDeprecated: Boolean = arg.hasTagPrefix(tags.deprecatedPrefix) + + def deprecatedNames: List[String] = arg.tags + .filter(_.name.startsWith(tags.deprecatedPrefix)) + .map(_.name.stripPrefix(s"${tags.deprecatedPrefix}${tags.valueSeparator}")) + .toList + + def deprecatedOptionAliases: List[String] = arg.deprecatedNames.map { + case name if name.startsWith("-") => name + case name if name.length == 1 => "-" + name + case name => "--" + CaseUtil.pascalCaseSplit(name.toCharArray.toList).map( + _.toLowerCase + ).mkString("-") + } def isExperimentalOrRestricted: Boolean = arg.isRestricted || arg.isExperimental diff --git a/modules/generate-reference-doc/src/main/scala/scala/cli/doc/GenerateReferenceDoc.scala b/modules/generate-reference-doc/src/main/scala/scala/cli/doc/GenerateReferenceDoc.scala index 5878a14351..13398552b0 100644 --- a/modules/generate-reference-doc/src/main/scala/scala/cli/doc/GenerateReferenceDoc.scala +++ b/modules/generate-reference-doc/src/main/scala/scala/cli/doc/GenerateReferenceDoc.scala @@ -207,7 +207,11 @@ object GenerateReferenceDoc extends CaseApp[InternalDocOptions] { names .tail .sortBy(_.dropWhile(_ == '-')) - .map(n => s"`$n`") + .map { + case name if arg.deprecatedOptionAliases.contains(name) => + s"[deprecated] `$name`" + case name => s"`$name`" + } .mkString("Aliases: ", ", ", "\n\n") ) diff --git a/modules/integration/src/test/scala/scala/cli/integration/PackageTestDefinitions.scala b/modules/integration/src/test/scala/scala/cli/integration/PackageTestDefinitions.scala index f92f18532d..fe54f6cd62 100644 --- a/modules/integration/src/test/scala/scala/cli/integration/PackageTestDefinitions.scala +++ b/modules/integration/src/test/scala/scala/cli/integration/PackageTestDefinitions.scala @@ -859,11 +859,16 @@ abstract class PackageTestDefinitions extends ScalaCliSuite with TestScalaVersio test("source JAR") { val dest = os.rel / "sources.jar" simpleInputWithScalaAndSc.fromRoot { root => - os.proc(TestUtil.cli, "--power", "package", extraOptions, ".", "-o", dest, "--source").call( - cwd = root, - stdin = os.Inherit, - stdout = os.Inherit - ) + val r = + os.proc(TestUtil.cli, "--power", "package", extraOptions, ".", "-o", dest, "--source").call( + cwd = root, + stdin = os.Inherit, + stdout = os.Inherit, + stderr = os.Pipe + ) + expect(r.err.trim().contains( + "The --source option alias has been deprecated and may be removed in a future version" + )) expect(os.isFile(root / dest)) diff --git a/modules/specification-level/src/main/scala/scala/cli/commands/SpecificationLevel.scala b/modules/specification-level/src/main/scala/scala/cli/commands/SpecificationLevel.scala index 3aa488863a..2b3d29fa1f 100644 --- a/modules/specification-level/src/main/scala/scala/cli/commands/SpecificationLevel.scala +++ b/modules/specification-level/src/main/scala/scala/cli/commands/SpecificationLevel.scala @@ -58,6 +58,8 @@ object SpecificationLevel { } object tags { + val valueSeparator: String = ":" // separates values in a tag + // specification level tags val experimental: String = SpecificationLevel.EXPERIMENTAL.toString val restricted: String = SpecificationLevel.RESTRICTED.toString @@ -68,7 +70,10 @@ object tags { // other tags // the `inShortHelp` tag whitelists options to be included in --help // this is in contrast to blacklisting options in --help with the @Hidden annotation - val inShortHelp: String = "inShortHelp" // included in --help by default + val inShortHelp: String = "inShortHelp" // included in --help by default + val deprecatedPrefix: String = "deprecated" + def deprecated(name: String): String = + s"$deprecatedPrefix$valueSeparator$name" // produces a deprecated warning for the given name def levelFor(name: String): Option[SpecificationLevel] = name match { case `experimental` => Some(SpecificationLevel.EXPERIMENTAL) diff --git a/website/docs/reference/cli-options.md b/website/docs/reference/cli-options.md index a092661578..83bb1ed3ea 100644 --- a/website/docs/reference/cli-options.md +++ b/website/docs/reference/cli-options.md @@ -749,9 +749,9 @@ Overwrite the destination file, if it exists Generate a library JAR rather than an executable JAR -### `--source` +### `--src` -Aliases: `--sources`, `--src` +Aliases: [deprecated] `--source`, `--sources` Generate a source JAR rather than an executable JAR From 404763c7d5b9ab24339546e09d2b6f8bac1eeffe Mon Sep 17 00:00:00 2001 From: Piotr Chabelski Date: Tue, 5 Nov 2024 12:17:33 +0100 Subject: [PATCH 2/2] Add `--jar-sources` and `--sources-jar` as aliases for `--src` --- .../main/scala/scala/cli/commands/package0/PackageOptions.scala | 2 ++ website/docs/reference/cli-options.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/cli/src/main/scala/scala/cli/commands/package0/PackageOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/package0/PackageOptions.scala index 4bcae6397d..917579ae11 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/package0/PackageOptions.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/package0/PackageOptions.scala @@ -48,6 +48,8 @@ final case class PackageOptions( library: Boolean = false, @Group(HelpGroup.Package.toString) @HelpMessage("Generate a source JAR rather than an executable JAR") + @Name("sourcesJar") + @Name("jarSources") @Name("sources") @Name("source") @Tag(tags.deprecated("source")) // alias to be removed in 1.6.x diff --git a/website/docs/reference/cli-options.md b/website/docs/reference/cli-options.md index 83bb1ed3ea..117fa1a420 100644 --- a/website/docs/reference/cli-options.md +++ b/website/docs/reference/cli-options.md @@ -751,7 +751,7 @@ Generate a library JAR rather than an executable JAR ### `--src` -Aliases: [deprecated] `--source`, `--sources` +Aliases: `--jar-sources`, [deprecated] `--source`, `--sources`, `--sources-jar` Generate a source JAR rather than an executable JAR