@@ -8,6 +8,7 @@ import caseapp.core.{Arg, Error}
8
8
import com .github .plokhotnyuk .jsoniter_scala .core .*
9
9
import com .github .plokhotnyuk .jsoniter_scala .macros .*
10
10
11
+ import scala .build .options .ScalacOpt .noDashPrefixes
11
12
import scala .cli .commands .tags
12
13
13
14
// format: off
@@ -26,6 +27,13 @@ final case class ScalacOptions(
26
27
// format: on
27
28
28
29
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
+ }
29
37
30
38
private val scalacOptionsArg = Arg (" scalacOption" ).copy(
31
39
extraNames = Seq (Name (" scala-opt" ), Name (" O" ), Name (" scala-option" )),
@@ -37,46 +45,58 @@ object ScalacOptions {
37
45
origin = Some (" ScalacOptions" )
38
46
)
39
47
// .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
45
51
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
+ )
47
65
private val scalacNoArgAliasedOptions = // these options don't require being passed after -O and don't accept an arg
48
66
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"
58
78
)
59
79
60
80
/** This includes all the scalac options which disregard inputs and print a help and/or context
61
81
* message instead.
62
82
*/
63
83
val ScalacPrintOptions : Set [String ] =
64
84
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"
73
93
)
74
94
75
95
/** 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
80
100
)
81
101
val ScalacDeprecatedOptions : Set [String ] = Set (
82
102
YScriptRunnerOption // old 'scala' runner specific, no longer supported
@@ -99,12 +119,20 @@ object ScalacOptions {
99
119
): Either [(Error , List [String ]), Option [(Option [List [String ]], List [String ])]] =
100
120
args match {
101
121
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) =>
104
125
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) =>
106
129
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) =>
108
136
// check if the next scalac arg is a different option or a param to the current option
109
137
val maybeOptionArg = t.headOption.filter(! _.startsWith(" -" ))
110
138
// if it's a param, it'll be treated as such and considered already parsed
@@ -118,8 +146,8 @@ object ScalacOptions {
118
146
}
119
147
120
148
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
123
151
baseParser.addAll[List [ArgFileOption ]].to[ScalacOptions ]
124
152
}
125
153
@@ -130,7 +158,7 @@ object ScalacOptions {
130
158
case class ArgFileOption (file : String ) extends AnyVal
131
159
132
160
object ArgFileOption {
133
- val arg = Arg (
161
+ val arg : Arg = Arg (
134
162
name = Name (" args-file" ),
135
163
valueDescription = Some (ValueDescription (" @arguments-file" )),
136
164
helpMessage = Some (HelpMessage (" File with scalac options." )),
0 commit comments