Skip to content

Commit 9c2c8d6

Browse files
authored
Add warnings for the -Yscriptrunner legacy scala runner option instead of passing it to scalac (#1804)
1 parent 81c2e3e commit 9c2c8d6

File tree

7 files changed

+76
-4
lines changed

7 files changed

+76
-4
lines changed

modules/cli/src/main/scala/scala/cli/commands/ScalaCommand.scala

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ import scala.build.EitherCps.{either, value}
1515
import scala.build.compiler.SimpleScalaCompiler
1616
import scala.build.errors.BuildException
1717
import scala.build.internal.{Constants, Runner}
18-
import scala.build.options.{BuildOptions, Scope}
18+
import scala.build.options.{BuildOptions, ScalacOpt, Scope}
1919
import scala.build.{Artifacts, Logger, Positioned, ReplArtifacts}
20+
import scala.cli.commands.default.LegacyScalaOptions
2021
import scala.cli.commands.shared.{HasLoggingOptions, ScalaCliHelp, ScalacOptions, SharedOptions}
2122
import scala.cli.commands.util.CommandHelpers
2223
import scala.cli.commands.util.ScalacOptionsUtil.*
@@ -133,6 +134,18 @@ abstract class ScalaCommand[T <: HasLoggingOptions](implicit myParser: Parser[T]
133134
for (shared <- sharedOptions(options))
134135
shared.helpGroups.maybePrintGroupHelp(help, helpFormat)
135136

137+
private def maybePrintWarnings(options: T): Unit = {
138+
import scala.cli.commands.shared.ScalacOptions.YScriptRunnerOption
139+
val logger = options.logging.logger
140+
sharedOptions(options).foreach { so =>
141+
val scalacOpts = so.scalac.scalacOption.toScalacOptShadowingSeq
142+
if scalacOpts.keys.contains(ScalacOpt(YScriptRunnerOption)) then
143+
logger.message(
144+
LegacyScalaOptions.yScriptRunnerWarning(scalacOpts.getOption(YScriptRunnerOption))
145+
)
146+
}
147+
}
148+
136149
/** Print `scalac` output if passed options imply no inputs are necessary and raw `scalac` output
137150
* is required instead. (i.e. `--scalac-option -help`)
138151
* @param options
@@ -265,6 +278,7 @@ abstract class ScalaCommand[T <: HasLoggingOptions](implicit myParser: Parser[T]
265278
*/
266279
final override def run(options: T, remainingArgs: RemainingArgs): Unit = {
267280
CurrentParams.verbosity = options.logging.verbosity
281+
maybePrintWarnings(options)
268282
maybePrintGroupHelp(options)
269283
buildOptions(options).foreach { bo =>
270284
maybePrintSimpleScalacOutput(options, bo)

modules/cli/src/main/scala/scala/cli/commands/default/LegacyScalaOptions.scala

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import caseapp.core.Indexed
55

66
import scala.build.Logger
77
import scala.cli.ScalaCli
8-
import scala.cli.ScalaCli.fullRunnerName
8+
import scala.cli.ScalaCli.{fullRunnerName, progName}
9+
import scala.cli.commands.bloop.BloopExit
910
import scala.cli.commands.default.LegacyScalaOptions.*
1011
import scala.cli.commands.package0.Package
12+
import scala.cli.commands.shared.ScalacOptions.YScriptRunnerOption
1113
import scala.cli.commands.tags
1214

1315
/** Options covering backwards compatibility with the old scala runner.
@@ -164,4 +166,26 @@ object LegacyScalaOptions {
164166

165167
private[default] lazy val PowerString =
166168
if ScalaCli.allowRestrictedFeatures then "" else "--power "
169+
170+
def yScriptRunnerWarning(yScriptRunnerValue: Option[String]): String = {
171+
val valueSpecificMsg = yScriptRunnerValue match {
172+
case Some(v @ "default") =>
173+
s"scala.tools.nsc.DefaultScriptRunner (the $v script runner) is no longer available."
174+
case Some(v @ "resident") =>
175+
s"scala.tools.nsc.fsc.ResidentScriptRunner (the $v script runner) is no longer available."
176+
case Some(v @ "shutdown") =>
177+
val bloopExitCommandName =
178+
BloopExit.names.headOption.map(_.mkString(" ")).getOrElse(BloopExit.name)
179+
s"""scala.tools.nsc.fsc.DaemonKiller (the $v script runner) is no longer available.
180+
|Did you want to stop the $fullRunnerName build server (Bloop) instead?
181+
|If so, consider using the following command:
182+
| ${Console.BOLD}$progName $PowerString$bloopExitCommandName${Console.RESET}""".stripMargin
183+
case Some(className) =>
184+
s"Using $className as the script runner is no longer supported and will not be attempted."
185+
case _ => ""
186+
}
187+
s"""Deprecated option '$YScriptRunnerOption' is ignored.
188+
|The script runner can no longer be picked as before.
189+
|$valueSpecificMsg""".stripMargin
190+
}
167191
}

modules/cli/src/main/scala/scala/cli/commands/shared/ScalacOptions.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@ object ScalacOptions {
3535
origin = Some("ScalacOptions")
3636
)
3737
// .withIsFlag(true) // The scalac options we handle accept no value after the -… argument
38+
val YScriptRunnerOption = "-Yscriptrunner"
3839
private val scalacOptionsPurePrefixes =
3940
Set("-V", "-W", "-X", "-Y")
4041
private val scalacOptionsPrefixes =
4142
Set("-g", "-language", "-opt", "-P", "-target", "-source") ++ scalacOptionsPurePrefixes
4243
private val scalacAliasedOptions = // these options don't require being passed after -O and accept an arg
43-
Set("-encoding", "-release", "-color")
44+
Set("-encoding", "-release", "-color", YScriptRunnerOption)
4445
private val scalacNoArgAliasedOptions = // these options don't require being passed after -O and don't accept an arg
4546
Set(
4647
"-nowarn",
@@ -64,6 +65,9 @@ object ScalacOptions {
6465
"-classpath", // redirected to --extra-jars
6566
"-d" // redirected to --compilation-output
6667
)
68+
val ScalacDeprecatedOptions: Set[String] = Set(
69+
YScriptRunnerOption // old 'scala' runner specific, no longer supported
70+
)
6771

6872
private val scalacOptionsArgument: Argument[List[String]] =
6973
new Argument[List[String]] {
@@ -81,7 +85,9 @@ object ScalacOptions {
8185
formatter: Formatter[Name]
8286
): Either[(Error, List[String]), Option[(Option[List[String]], List[String])]] =
8387
args match {
84-
case h :: t if scalacOptionsPrefixes.exists(h.startsWith) =>
88+
case h :: t
89+
if scalacOptionsPrefixes.exists(h.startsWith) &&
90+
!ScalacDeprecatedOptions.contains(h) =>
8591
Right(Some((Some(h :: acc.getOrElse(Nil)), t)))
8692
case h :: t if scalacNoArgAliasedOptions.contains(h) =>
8793
Right(Some((Some(h :: acc.getOrElse(Nil)), t)))

modules/cli/src/main/scala/scala/cli/commands/shared/SharedOptions.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ final case class SharedOptions(
300300
.withScalacExtraOptions(scalacExtra)
301301
.toScalacOptShadowingSeq
302302
.filterNonRedirected
303+
.filterNonDeprecated
303304
.map(Positioned.commandLine),
304305
compilerPlugins =
305306
SharedOptions.parseDependencies(

modules/cli/src/main/scala/scala/cli/commands/util/ScalacOptionsUtil.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package scala.cli.commands.util
22

3+
import scala.build.Logger
34
import scala.build.options.{ScalacOpt, ShadowingSeq}
5+
import scala.cli.commands.bloop.BloopExit
6+
import scala.cli.commands.default.LegacyScalaOptions
7+
import scala.cli.commands.shared.ScalacOptions.YScriptRunnerOption
48
import scala.cli.commands.shared.{ScalacExtraOptions, ScalacOptions}
59

610
object ScalacOptionsUtil {
@@ -31,6 +35,8 @@ object ScalacOptionsUtil {
3135
opts.filterKeys(_.key.exists(f))
3236
def filterNonRedirected: ShadowingSeq[ScalacOpt] =
3337
opts.filterScalacOptionKeys(!ScalacOptions.ScalaCliRedirectedOptions.contains(_))
38+
def filterNonDeprecated: ShadowingSeq[ScalacOpt] =
39+
opts.filterScalacOptionKeys(!ScalacOptions.ScalacDeprecatedOptions.contains(_))
3440
def getOption(key: String): Option[String] =
3541
opts.get(ScalacOpt(key)).headOption.map(_.value)
3642
}

modules/integration/src/test/scala/scala/cli/integration/LegacyScalaRunnerTestDefinitions.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,26 @@ trait LegacyScalaRunnerTestDefinitions { _: DefaultTests =>
8585
}
8686
}
8787

88+
test("ensure -Yscriptrunner works with the default command") {
89+
legacyOptionBackwardsCompatTest("-Yscriptrunner") {
90+
(legacyOption, inputFile, root) =>
91+
Seq("default", "resident", "shutdown", "scala.tools.nsc.fsc.ResidentScriptRunner").foreach {
92+
legacyOptionValue =>
93+
val res =
94+
os.proc(
95+
TestUtil.cli,
96+
legacyOption,
97+
legacyOptionValue,
98+
inputFile,
99+
TestUtil.extraOptions
100+
)
101+
.call(cwd = root, stderr = os.Pipe)
102+
expect(res.err.trim().contains(deprecatedOptionWarning(legacyOption)))
103+
expect(res.err.trim().contains(legacyOptionValue))
104+
}
105+
}
106+
}
107+
88108
private def simpleLegacyOptionBackwardsCompatTest(optionAliases: String*): Unit =
89109
abstractLegacyOptionBackwardsCompatTest(optionAliases) {
90110
(legacyOption, expectedMsg, _, root) =>

modules/options/src/main/scala/scala/build/options/ShadowingSeq.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ final case class ShadowingSeq[T] private (values: Seq[Seq[T]]) {
2020
case Seq(head, _*) => f(head)
2121
case _ => true
2222
}
23+
def keys: Seq[T] = values.map(_.head)
2324
def ++(other: Seq[T])(implicit key: ShadowingSeq.KeyOf[T]): ShadowingSeq[T] =
2425
addGroups(ShadowingSeq.groups(other, key.groups(other)))
2526
private def addGroups(other: Seq[Seq[T]])(implicit key: ShadowingSeq.KeyOf[T]): ShadowingSeq[T] =

0 commit comments

Comments
 (0)