Skip to content

Commit 095cc09

Browse files
authored
Merge pull request #3253 from Gedochao/maintenance/scalac-options-tweaks
Misc improvements in compiler options handling
2 parents b8ab90d + 8e44678 commit 095cc09

File tree

13 files changed

+379
-131
lines changed

13 files changed

+379
-131
lines changed

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import scala.build.input.{ScalaCliInvokeData, SubCommand}
2121
import scala.build.internal.util.WarningMessages
2222
import scala.build.internal.{Constants, Runner}
2323
import scala.build.internals.{EnvVar, FeatureType}
24+
import scala.build.options.ScalacOpt.noDashPrefixes
2425
import scala.build.options.{BuildOptions, ScalacOpt, Scope}
2526
import scala.build.{Artifacts, Directories, Logger, Positioned, ReplArtifacts}
2627
import scala.cli.commands.default.LegacyScalaOptions
@@ -175,9 +176,13 @@ abstract class ScalaCommand[T <: HasGlobalOptions](implicit myParser: Parser[T],
175176
val logger = options.global.logging.logger
176177
sharedOptions(options).foreach { so =>
177178
val scalacOpts = so.scalacOptions.toScalacOptShadowingSeq
178-
if scalacOpts.keys.contains(ScalacOpt(YScriptRunnerOption)) then
179-
logger.message(
180-
LegacyScalaOptions.yScriptRunnerWarning(scalacOpts.getOption(YScriptRunnerOption))
179+
scalacOpts.keys
180+
.find(k =>
181+
k == ScalacOpt(s"-$YScriptRunnerOption") || k == ScalacOpt(s"--$YScriptRunnerOption")
182+
)
183+
.map(_.value)
184+
.foreach(k =>
185+
logger.message(LegacyScalaOptions.yScriptRunnerWarning(k, scalacOpts.getOption(k)))
181186
)
182187
}
183188
}
@@ -192,7 +197,7 @@ abstract class ScalaCommand[T <: HasGlobalOptions](implicit myParser: Parser[T],
192197
shared <- sharedOptions(options)
193198
scalacOptions = shared.scalacOptions
194199
updatedScalacOptions = scalacOptions.withScalacExtraOptions(shared.scalacExtra)
195-
if updatedScalacOptions.exists(ScalacOptions.ScalacPrintOptions)
200+
if updatedScalacOptions.map(_.noDashPrefixes).exists(ScalacOptions.ScalacPrintOptions)
196201
logger = shared.logger
197202
fixedBuildOptions = buildOptions.copy(scalaOptions =
198203
buildOptions.scalaOptions.copy(defaultScalaVersion = Some(ScalaCli.getDefaultScalaVersion))

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import scala.cli.commands.default.LegacyScalaOptions.*
1111
import scala.cli.commands.package0.Package
1212
import scala.cli.commands.shared.HelpGroup
1313
import scala.cli.commands.shared.HelpMessages.PowerString
14-
import scala.cli.commands.shared.ScalacOptions.YScriptRunnerOption
1514
import scala.cli.commands.tags
1615

1716
/** Options covering backwards compatibility with the old scala runner.
@@ -168,7 +167,7 @@ object LegacyScalaOptions {
168167
implicit lazy val parser: Parser[LegacyScalaOptions] = Parser.derive
169168
implicit lazy val help: Help[LegacyScalaOptions] = Help.derive
170169

171-
def yScriptRunnerWarning(yScriptRunnerValue: Option[String]): String = {
170+
def yScriptRunnerWarning(yScriptRunnerKey: String, yScriptRunnerValue: Option[String]): String = {
172171
val valueSpecificMsg = yScriptRunnerValue match {
173172
case Some(v @ "default") =>
174173
s"scala.tools.nsc.DefaultScriptRunner (the $v script runner) is no longer available."
@@ -185,7 +184,7 @@ object LegacyScalaOptions {
185184
s"Using $className as the script runner is no longer supported and will not be attempted."
186185
case _ => ""
187186
}
188-
s"""Deprecated option '$YScriptRunnerOption' is ignored.
187+
s"""Deprecated option '$yScriptRunnerKey' is ignored.
189188
|The script runner can no longer be picked as before.
190189
|$valueSpecificMsg""".stripMargin
191190
}

modules/cli/src/main/scala/scala/cli/commands/package0/PackageOptions.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ final case class PackageOptions(
5151
@Name("sourcesJar")
5252
@Name("jarSources")
5353
@Name("sources")
54-
@Name("source")
55-
@Tag(tags.deprecated("source")) // alias to be removed in 1.6.x
5654
@Tag(tags.restricted)
5755
@Tag(tags.inShortHelp)
5856
src: Boolean = false,

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

Lines changed: 62 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import caseapp.core.{Arg, Error}
88
import com.github.plokhotnyuk.jsoniter_scala.core.*
99
import com.github.plokhotnyuk.jsoniter_scala.macros.*
1010

11+
import scala.build.options.ScalacOpt.noDashPrefixes
1112
import scala.cli.commands.tags
1213

1314
// format: off
@@ -26,6 +27,13 @@ final case class ScalacOptions(
2627
// format: on
2728

2829
object ScalacOptions {
30+
extension (opt: String) {
31+
private def hasValidScalacOptionDashes: Boolean =
32+
opt.startsWith("-") && opt.length > 1 && (
33+
if opt.length > 2 then opt.charAt(2) != '-'
34+
else opt.charAt(1) != '-'
35+
)
36+
}
2937

3038
private val scalacOptionsArg = Arg("scalacOption").copy(
3139
extraNames = Seq(Name("scala-opt"), Name("O"), Name("scala-option")),
@@ -37,46 +45,58 @@ object ScalacOptions {
3745
origin = Some("ScalacOptions")
3846
)
3947
// .withIsFlag(true) // The scalac options we handle accept no value after the -… argument
40-
val YScriptRunnerOption = "-Yscriptrunner"
41-
private val scalacOptionsPurePrefixes =
42-
Set("-V", "-W", "-X", "-Y")
43-
private val scalacOptionsPrefixes =
44-
Set("-g", "-language", "-opt", "-P", "-target", "-source") ++ scalacOptionsPurePrefixes
48+
val YScriptRunnerOption = "Yscriptrunner"
49+
private val scalacOptionsPurePrefixes = Set("V", "W", "X", "Y")
50+
private val scalacOptionsPrefixes = Set("P") ++ scalacOptionsPurePrefixes
4551
private val scalacAliasedOptions = // these options don't require being passed after -O and accept an arg
46-
Set("-encoding", "-release", "-color", YScriptRunnerOption)
52+
Set(
53+
"coverage-exclude-classlikes",
54+
"coverage-exclude-files",
55+
"encoding",
56+
"release",
57+
"color",
58+
"g",
59+
"language",
60+
"opt",
61+
"target",
62+
"source",
63+
YScriptRunnerOption
64+
)
4765
private val scalacNoArgAliasedOptions = // these options don't require being passed after -O and don't accept an arg
4866
Set(
49-
"-unchecked",
50-
"-nowarn",
51-
"-feature",
52-
"-deprecation",
53-
"-rewrite",
54-
"-old-syntax",
55-
"-new-syntax",
56-
"-indent",
57-
"-no-indent"
67+
"experimental",
68+
"explain",
69+
"unchecked",
70+
"nowarn",
71+
"feature",
72+
"deprecation",
73+
"rewrite",
74+
"old-syntax",
75+
"new-syntax",
76+
"indent",
77+
"no-indent"
5878
)
5979

6080
/** This includes all the scalac options which disregard inputs and print a help and/or context
6181
* message instead.
6282
*/
6383
val ScalacPrintOptions: Set[String] =
6484
scalacOptionsPurePrefixes ++ Set(
65-
"-help",
66-
"-opt:help",
67-
"-Xshow-phases",
68-
"-Xsource:help",
69-
"-Xplugin-list",
70-
"-Xmixin-force-forwarders:help",
71-
"-Xlint:help",
72-
"-Vphases"
85+
"help",
86+
"opt:help",
87+
"Xshow-phases",
88+
"Xsource:help",
89+
"Xplugin-list",
90+
"Xmixin-force-forwarders:help",
91+
"Xlint:help",
92+
"Vphases"
7393
)
7494

7595
/** This includes all the scalac options which are redirected to native Scala CLI options. */
76-
val ScalaCliRedirectedOptions = Set(
77-
"-classpath",
78-
"-cp", // redirected to --extra-jars
79-
"-d" // redirected to --compilation-output
96+
val ScalaCliRedirectedOptions: Set[String] = Set(
97+
"classpath",
98+
"cp", // redirected to --extra-jars
99+
"d" // redirected to --compilation-output
80100
)
81101
val ScalacDeprecatedOptions: Set[String] = Set(
82102
YScriptRunnerOption // old 'scala' runner specific, no longer supported
@@ -99,12 +119,20 @@ object ScalacOptions {
99119
): Either[(Error, List[String]), Option[(Option[List[String]], List[String])]] =
100120
args match {
101121
case h :: t
102-
if scalacOptionsPrefixes.exists(h.startsWith) &&
103-
!ScalacDeprecatedOptions.contains(h) =>
122+
if h.hasValidScalacOptionDashes &&
123+
scalacOptionsPrefixes.exists(h.noDashPrefixes.startsWith) &&
124+
!ScalacDeprecatedOptions.contains(h.noDashPrefixes) =>
104125
Right(Some((Some(acc.getOrElse(Nil) :+ h), t)))
105-
case h :: t if scalacNoArgAliasedOptions.contains(h) =>
126+
case h :: t
127+
if h.hasValidScalacOptionDashes &&
128+
scalacNoArgAliasedOptions.contains(h.noDashPrefixes) =>
106129
Right(Some((Some(acc.getOrElse(Nil) :+ h), t)))
107-
case h :: t if scalacAliasedOptions.contains(h) =>
130+
case h :: t
131+
if h.hasValidScalacOptionDashes &&
132+
scalacAliasedOptions.exists(o => h.noDashPrefixes.startsWith(o + ":")) &&
133+
h.count(_ == ':') == 1 => Right(Some((Some(acc.getOrElse(Nil) :+ h), t)))
134+
case h :: t
135+
if h.hasValidScalacOptionDashes && scalacAliasedOptions.contains(h.noDashPrefixes) =>
108136
// check if the next scalac arg is a different option or a param to the current option
109137
val maybeOptionArg = t.headOption.filter(!_.startsWith("-"))
110138
// if it's a param, it'll be treated as such and considered already parsed
@@ -118,8 +146,8 @@ object ScalacOptions {
118146
}
119147

120148
implicit lazy val parser: Parser[ScalacOptions] = {
121-
val baseParser = scalacOptionsArgument :: NilParser
122-
implicit val p = ArgFileOption.parser
149+
val baseParser = scalacOptionsArgument :: NilParser
150+
implicit val p: Parser[List[ArgFileOption]] = ArgFileOption.parser
123151
baseParser.addAll[List[ArgFileOption]].to[ScalacOptions]
124152
}
125153

@@ -130,7 +158,7 @@ object ScalacOptions {
130158
case class ArgFileOption(file: String) extends AnyVal
131159

132160
object ArgFileOption {
133-
val arg = Arg(
161+
val arg: Arg = Arg(
134162
name = Name("args-file"),
135163
valueDescription = Some(ValueDescription("@arguments-file")),
136164
helpMessage = Some(HelpMessage("File with scalac options.")),

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

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

33
import scala.build.Logger
4-
import scala.build.options.ScalacOpt.filterScalacOptionKeys
4+
import scala.build.options.ScalacOpt.{filterScalacOptionKeys, noDashPrefixes}
55
import scala.build.options.{ScalacOpt, ShadowingSeq}
66
import scala.cli.commands.bloop.BloopExit
77
import scala.cli.commands.default.LegacyScalaOptions
@@ -33,9 +33,13 @@ object ScalacOptionsUtil {
3333

3434
extension (opts: ShadowingSeq[ScalacOpt]) {
3535
def filterNonRedirected: ShadowingSeq[ScalacOpt] =
36-
opts.filterScalacOptionKeys(!ScalacOptions.ScalaCliRedirectedOptions.contains(_))
36+
opts.filterScalacOptionKeys(k =>
37+
!ScalacOptions.ScalaCliRedirectedOptions.contains(k.noDashPrefixes)
38+
)
3739
def filterNonDeprecated: ShadowingSeq[ScalacOpt] =
38-
opts.filterScalacOptionKeys(!ScalacOptions.ScalacDeprecatedOptions.contains(_))
40+
opts.filterScalacOptionKeys(k =>
41+
!ScalacOptions.ScalacDeprecatedOptions.contains(k.noDashPrefixes)
42+
)
3943
def getOption(key: String): Option[String] =
4044
opts.get(ScalacOpt(key)).headOption.map(_.value)
4145
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1712,7 +1712,7 @@ abstract class BspTestDefinitions extends ScalaCliSuite with TestScalaVersionArg
17121712
"--power",
17131713
"package",
17141714
jarSources,
1715-
"--source",
1715+
"--src",
17161716
"-o",
17171717
sourceJarPath,
17181718
extraOptions

0 commit comments

Comments
 (0)