Skip to content

Add support for deprecated Scala 2.13.x-specific scala runner options #1774

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import caseapp.core.Error
import caseapp.core.help.{Help, HelpCompanion, RuntimeCommandsHelp}
import caseapp.core.parser.Parser

import scala.cli.commands.default.DefaultOptions
import scala.cli.commands.default.{DefaultOptions, LegacyScalaOptions}
import scala.cli.commands.shared.{HasLoggingOptions, ScalaCliHelp}
import scala.cli.commands.util.HelpUtils.*
import scala.cli.launcher.LauncherOptions
Expand All @@ -18,12 +18,23 @@ abstract class ScalaCommandWithCustomHelp[T <: HasLoggingOptions](
) extends ScalaCommand[T] {
private def launcherHelp: Help[LauncherOptions] = HelpCompanion.deriveHelp[LauncherOptions]

private def legacyScalaHelp: Help[LegacyScalaOptions] =
HelpCompanion.deriveHelp[LegacyScalaOptions]

protected def customHelp(showHidden: Boolean): String = {
val helpString = actualHelp.help(helpFormat, showHidden)
val launcherHelpString = launcherHelp.optionsHelp(helpFormat, showHidden)
val helpString = actualHelp.help(helpFormat, showHidden)
val launcherHelpString = launcherHelp.optionsHelp(helpFormat, showHidden)
val legacyScalaHelpString = legacyScalaHelp.optionsHelp(helpFormat, showHidden)
val legacyScalaHelpStringWithPadding =
if legacyScalaHelpString.nonEmpty then
s"""
|$legacyScalaHelpString
|""".stripMargin
else ""
s"""$helpString
|
|$launcherHelpString""".stripMargin
|$launcherHelpString
|$legacyScalaHelpStringWithPadding""".stripMargin
}

protected def customHelpAsked(showHidden: Boolean): Nothing = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class Default(

private lazy val defaultCommandHelp: String =
s"""
|
|When no subcommand is passed explicitly, an implicit subcommand is used based on context:
| - if the '--version' option is passed, it prints the 'version' subcommand output, unmodified by any other options
| - if any inputs were passed, it defaults to the 'run' subcommand
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import caseapp.core.Indexed

import scala.build.Logger
import scala.cli.ScalaCli
import scala.cli.ScalaCli.fullRunnerName
import scala.cli.commands.default.LegacyScalaOptions.*
import scala.cli.commands.package0.Package
import scala.cli.commands.tags
Expand All @@ -13,16 +14,38 @@ import scala.cli.commands.tags
*/
// format: off
case class LegacyScalaOptions(
@Group("Scala")
@Group("Legacy Scala runner")
@HelpMessage(s"Ignored legacy option. Deprecated equivalent of running a subsequent `$PowerString${Package.name}` command.")
@Tag(tags.must)
@Hidden
@Name("-save")
save: Option[Indexed[Boolean]] = None,
@Group("Scala")
@Group("Legacy Scala runner")
@HelpMessage("Ignored legacy option. Deprecated override canceling the `-nosave` option.")
@Tag(tags.must)
@Hidden
@Name("-nosave")
nosave: Option[Indexed[Boolean]] = None,
@Group("Legacy Scala runner")
@HelpMessage("Ignored legacy option. Deprecated override defining how the runner should treat the input. Use the appropriate sub-command instead.")
@Tag(tags.must)
@Hidden
@ValueDescription("object|script|jar|repl|guess")
@Name("-howtorun")
howToRun: Option[Indexed[String]] = None,
@Group("Legacy Scala runner")
@HelpMessage("Ignored legacy option. Deprecated option allowing to preload inputs for the repl or command execution.")
@Tag(tags.must)
@Hidden
@ValueDescription("file")
I: Option[Indexed[List[String]]] = None,
@Group("Legacy Scala runner")
@HelpMessage("Ignored legacy option. Deprecated option allowing to prevent the use of the legacy fsc compilation daemon.")
@Tag(tags.must)
@Hidden
@Name("-nc")
@Name("-nocompdaemon")
noCompilationDaemon: Option[Indexed[Boolean]] = None,
) {
// format: on

Expand All @@ -36,9 +59,14 @@ case class LegacyScalaOptions(
progName: String,
logger: Logger
): Array[String] = {
val saveOptionString = save.findArg(args)
val noSaveOptionString = nosave.findArg(args)
val deprecatedArgs = Seq(saveOptionString, noSaveOptionString).flatten
val saveOptionString = save.findArg(args)
val noSaveOptionString = nosave.findArg(args)
val howToRunString = howToRun.findArg(args)
val iString = I.findArg(args)
val noCompilationDaemonString = noCompilationDaemon.findArg(args)
val deprecatedArgs =
Seq(saveOptionString, noSaveOptionString, howToRunString, iString, noCompilationDaemonString)
.flatten
val filteredArgs = args.filterNot(deprecatedArgs.contains)
val filteredArgsString = filteredArgs.mkString(" ")
saveOptionString.foreach { s =>
Expand All @@ -55,6 +83,49 @@ case class LegacyScalaOptions(
|A jar file is not saved unless the '$PowerString${Package.name}' sub-command is called.""".stripMargin
)
}
for {
htrString <- howToRunString
htrValue <- howToRun.map(_.value)
} {
logger.message(s"Deprecated option '$htrString' is ignored.".stripMargin)
val passedValueExplanation = htrValue match {
case v @ ("object" | "script" | "jar") =>
s"""$fullRunnerName does not support explicitly forcing an input to be run as '$v'.
|Just make sure your inputs have the correct format and extension.""".stripMargin
case "guess" =>
s"""$fullRunnerName does not support `guess` mode.
|Just make sure your inputs have the correct format and extension.""".stripMargin
case "repl" =>
s"""In order to explicitly run the repl, use the 'repl' sub-command.
| ${Console.BOLD}$progName repl $filteredArgsString${Console.RESET}
|""".stripMargin
case invalid @ _ =>
s"""'$invalid' is not an accepted value for the '$htrString' option.
|$fullRunnerName uses an equivalent of the old 'guess' mode by default at all times.""".stripMargin
}
logger.message(passedValueExplanation)
logger.message(
s"""Instead of the deprecated '$htrString' option, $fullRunnerName now uses a sub-command system.
|To learn more, try viewing the help.
| ${Console.BOLD}$progName -help${Console.RESET}""".stripMargin
)
}
for {
optionName <- iString
optionValues <- I.map(_.value)
exampleReplInputs = optionValues.mkString(" ")
} {
logger.message(s"Deprecated option '$optionName' is ignored.".stripMargin)
logger.message(
s"""To preload the extra files for the repl, try passing them as inputs for the repl sub-command.
| ${Console.BOLD}$progName repl $exampleReplInputs${Console.RESET}
|""".stripMargin
)
}
noCompilationDaemonString.foreach { nc =>
logger.message(s"Deprecated option '$nc' is ignored.")
logger.message("The script runner can no longer be picked as before.")
}
filteredArgs
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ final case class VerbosityOptions(
@HelpMessage("Increase verbosity (can be specified multiple times)")
@Tag(tags.implementation)
@Name("v")
@Name("-verbose")
verbose: Int @@ Counter = Tag.of(0),
@Group("Logging")
@HelpMessage("Interactive mode")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package scala.cli.integration

import com.eed3si9n.expecty.Expecty.expect

class DefaultTests extends WithWarmUpScalaCliSuite {
class DefaultTests extends WithWarmUpScalaCliSuite with LegacyScalaRunnerTestDefinitions {
override def warmUpExtraTestOptions: Seq[String] = TestUtil.extraOptions

test("running scala-cli with no args should default to repl") {
Expand Down Expand Up @@ -36,17 +36,6 @@ class DefaultTests extends WithWarmUpScalaCliSuite {
}
}

test("default to the run sub-command when a script snippet is passed with -e") {
TestInputs.empty.fromRoot { root =>
val msg = "Hello world"
val quotation = TestUtil.argQuotationMark
val res =
os.proc(TestUtil.cli, "-e", s"println($quotation$msg$quotation)", TestUtil.extraOptions)
.call(cwd = root)
expect(res.out.trim() == msg)
}
}

test("default to the run sub-command when a scala snippet is passed with --execute-scala") {
TestInputs.empty.fromRoot { root =>
val msg = "Hello world"
Expand Down Expand Up @@ -99,23 +88,6 @@ class DefaultTests extends WithWarmUpScalaCliSuite {
}
}

test("running scala-cli with a script snippet passed with -e shouldn't allow repl-only options") {
TestInputs.empty.fromRoot { root =>
val replSpecificOption = "--repl-dry-run"
val res =
os.proc(
TestUtil.cli,
"-e",
"println()",
replSpecificOption,
TestUtil.extraOptions
)
.call(cwd = root, mergeErrIntoOut = true, check = false)
expect(res.exitCode == 1)
expect(res.out.lines().endsWith(unrecognizedArgMessage(replSpecificOption)))
}
}

test("default to the run sub-command if -classpath and --main-class are passed") {
val expectedOutput = "Hello"
val mainClassName = "Main"
Expand Down Expand Up @@ -183,49 +155,13 @@ class DefaultTests extends WithWarmUpScalaCliSuite {
}
}

test("ensure -save/--save works with the default command") {
val msg = "Hello world"
TestInputs(os.rel / "s.sc" -> s"""println("$msg")""").fromRoot { root =>
val legacySaveOption = "-save"
val res1 =
os.proc(TestUtil.cli, ".", legacySaveOption, TestUtil.extraOptions)
.call(cwd = root, stderr = os.Pipe)
expect(res1.out.trim() == msg)
expect(res1.err.trim().contains(s"Deprecated option '$legacySaveOption' is ignored"))
val doubleDashSaveOption = "--save"
val res2 =
os.proc(TestUtil.cli, ".", doubleDashSaveOption, TestUtil.extraOptions)
.call(cwd = root, stderr = os.Pipe)
expect(res2.out.trim() == msg)
expect(res2.err.trim().contains(s"Deprecated option '$doubleDashSaveOption' is ignored"))
}
}

test("ensure -nosave/--nosave works with the default command") {
val msg = "Hello world"
TestInputs(os.rel / "s.sc" -> s"""println("$msg")""").fromRoot { root =>
val legacyNoSaveOption = "-nosave"
val res1 =
os.proc(TestUtil.cli, ".", legacyNoSaveOption, TestUtil.extraOptions)
.call(cwd = root, stderr = os.Pipe)
expect(res1.out.trim() == msg)
expect(res1.err.trim().contains(s"Deprecated option '$legacyNoSaveOption' is ignored"))
val doubleDashNoSaveOption = "--nosave"
val res2 =
os.proc(TestUtil.cli, ".", doubleDashNoSaveOption, TestUtil.extraOptions)
.call(cwd = root, stderr = os.Pipe)
expect(res2.out.trim() == msg)
expect(res2.err.trim().contains(s"Deprecated option '$doubleDashNoSaveOption' is ignored"))
}
}

private def unrecognizedArgMessage(argName: String) =
protected def unrecognizedArgMessage(argName: String): Vector[String] =
s"""
|Unrecognized argument: $argName
|
|To list all available options, run
| ${Console.BOLD}${TestUtil.detectCliPath} --help${Console.RESET}
|""".stripMargin.trim.linesIterator.toVector

private lazy val replDryRunOutput = "Dry run, not running REPL."
protected lazy val replDryRunOutput = "Dry run, not running REPL."
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,46 @@ class HelpTests extends ScalaCliSuite {
test(s"$helpOptionsString output includes launcher options") {
expect(helpOutput.contains("--power"))
}

test(s"$helpOptionsString output does not include legacy scala runner options") {
expect(!helpOutput.contains("Legacy Scala runner options"))
}
}

for (fullHelpOptions <- HelpTests.fullHelpVariants) {
lazy val fullHelp = os.proc(TestUtil.cli, fullHelpOptions).call(check = false)
lazy val fullHelpOutput = fullHelp.out.trim()
val fullHelpOptionsString = fullHelpOptions.mkString(" ")
test(s"$fullHelpOptionsString works correctly") {
assert(
fullHelp.exitCode == 0,
clues(fullHelpOptions, fullHelp.out.text(), fullHelp.err.text(), fullHelp.exitCode)
)
expect(fullHelpOutput.contains("Usage:"))
}
test(s"$fullHelpOptionsString output includes legacy scala runner options") {
expect(fullHelpOutput.contains("Legacy Scala runner options"))
}
}
}

object HelpTests {
val variants =
Seq(Seq("help"), Seq("help", "-help"), Seq("help", "--help"), Seq("-help"), Seq("--help"))
Seq(
Seq("help"),
Seq("help", "-help"),
Seq("help", "--help"),
Seq("-help"),
Seq("--help")
)
val fullHelpVariants =
Seq(
Seq("help", "--full-help"),
Seq("help", "-full-help"),
Seq("help", "--help-full"),
Seq("help", "-help-full"),
Seq("--full-help"),
Seq("-full-help"),
Seq("-help-full")
)
}
Loading