@@ -15,6 +15,8 @@ import dotty.tools.dotc.config.Settings.Setting.ChoiceWithHelp
15
15
16
16
object Settings :
17
17
18
+ private inline def classTag [T ](using ctag : ClassTag [T ]): ClassTag [T ] = ctag
19
+
18
20
val BooleanTag : ClassTag [Boolean ] = ClassTag .Boolean
19
21
val IntTag : ClassTag [Int ] = ClassTag .Int
20
22
val StringTag : ClassTag [String ] = ClassTag (classOf [String ])
@@ -102,21 +104,25 @@ object Settings:
102
104
assert(legacyArgs || ! choices.exists(_.contains(" " )), s " Empty string is not supported as a choice for setting $name" )
103
105
// Without the following assertion, it would be easy to mistakenly try to pass a file to a setting that ignores invalid args.
104
106
// Example: -opt Main.scala would be interpreted as -opt:Main.scala, and the source file would be ignored.
105
- assert(! (summon[ ClassTag [ T ] ] == ListTag && ignoreInvalidArgs), s " Ignoring invalid args is not supported for multivalue settings: $name" )
107
+ assert(! (classTag[ T ] == ListTag && ignoreInvalidArgs), s " Ignoring invalid args is not supported for multivalue settings: $name" )
106
108
107
109
val allFullNames : List [String ] = s " $name" :: s " - $name" :: aliases
108
110
111
+ def isPresentIn (state : SettingsState ): Boolean = state.wasChanged(idx)
112
+
109
113
def valueIn (state : SettingsState ): T = state.value(idx).asInstanceOf [T ]
110
114
115
+ def userValueIn (state : SettingsState ): Option [T ] = if isPresentIn(state) then Some (valueIn(state)) else None
116
+
111
117
def updateIn (state : SettingsState , x : Any ): SettingsState = x match
112
118
case _ : T => state.update(idx, x)
113
- case _ => throw IllegalArgumentException (s " found: $x of type ${x.getClass.getName}, required: ${summon[ ClassTag [ T ] ]}" )
119
+ case _ => throw IllegalArgumentException (s " found: $x of type ${x.getClass.getName}, required: ${classTag[ T ]}" )
114
120
115
121
def isDefaultIn (state : SettingsState ): Boolean = valueIn(state) == default
116
122
117
- def isMultivalue : Boolean = summon[ ClassTag [ T ] ] == ListTag
123
+ def isMultivalue : Boolean = classTag[ T ] == ListTag
118
124
119
- def acceptsNoArg : Boolean = summon[ ClassTag [ T ]] == BooleanTag || summon[ ClassTag [ T ] ] == OptionTag || choices.exists(_.contains(" " ))
125
+ def acceptsNoArg : Boolean = classTag[ T ] == BooleanTag || classTag[ T ] == OptionTag || choices.exists(_.contains(" " ))
120
126
121
127
def legalChoices : String =
122
128
choices match
@@ -132,7 +138,7 @@ object Settings:
132
138
* Updates the value in state
133
139
*
134
140
* @param getValue it is crucial that this argument is passed by name, as [setOutput] have side effects.
135
- * @param argStringValue string value of currently proccessed argument that will be used to set deprecation replacement
141
+ * @param argStringValue string value of currently processed argument that will be used to set deprecation replacement
136
142
* @param args remaining arguments to process
137
143
* @return new argumment state
138
144
*/
@@ -168,11 +174,17 @@ object Settings:
168
174
169
175
def missingArg =
170
176
val msg = s " missing argument for option $name"
171
- if ignoreInvalidArgs then state.warn(msg + " , the tag was ignored" ) else state.fail(msg)
177
+ if ignoreInvalidArgs then state.warn(s " $msg , the tag was ignored " ) else state.fail(msg)
172
178
173
179
def invalidChoices (invalid : List [String ]) =
174
180
val msg = s " invalid choice(s) for $name: ${invalid.mkString(" ," )}"
175
- if ignoreInvalidArgs then state.warn(msg + " , the tag was ignored" ) else state.fail(msg)
181
+ if ignoreInvalidArgs then state.warn(s " $msg, the tag was ignored " ) else state.fail(msg)
182
+
183
+ def isEmptyDefault = default == null .asInstanceOf [T ] || classTag[T ].match
184
+ case ListTag => default.asInstanceOf [List [? ]].isEmpty
185
+ case StringTag => default.asInstanceOf [String ].isEmpty
186
+ case OptionTag => default.asInstanceOf [Option [? ]].isEmpty
187
+ case _ => false
176
188
177
189
def setBoolean (argValue : String , args : List [String ]) =
178
190
if argValue.equalsIgnoreCase(" true" ) || argValue.isEmpty then update(true , argValue, args)
@@ -201,11 +213,11 @@ object Settings:
201
213
def setOutput (argValue : String , args : List [String ]) =
202
214
val path = Directory (argValue)
203
215
val isJar = path.ext.isJar
204
- if ( ! isJar && ! path.isDirectory) then
216
+ if ! isJar && ! path.isDirectory then
205
217
state.fail(s " ' $argValue' does not exist or is not a directory or .jar file " )
206
218
else
207
219
/* Side effect, do not change this method to evaluate eagerly */
208
- def output = if ( isJar) JarArchive .create(path) else new PlainDirectory (path)
220
+ def output = if isJar then JarArchive .create(path) else new PlainDirectory (path)
209
221
update(output, argValue, args)
210
222
211
223
def setVersion (argValue : String , args : List [String ]) =
@@ -226,22 +238,28 @@ object Settings:
226
238
case _ => update(strings, argValue, args)
227
239
228
240
def doSet (argRest : String ) =
229
- ((summon[ ClassTag [ T ]], args) : @ unchecked) match
230
- case ( BooleanTag , _) =>
241
+ classTag[ T ] match
242
+ case BooleanTag =>
231
243
if sstate.wasChanged(idx) && preferPrevious then ignoreValue(args)
232
244
else setBoolean(argRest, args)
233
- case ( OptionTag , _) =>
245
+ case OptionTag =>
234
246
update(Some (propertyClass.get.getConstructor().newInstance()), " " , args)
235
- case (ct, args) =>
247
+ case ct =>
236
248
val argInArgRest = ! argRest.isEmpty || legacyArgs
237
- val argAfterParam = ! argInArgRest && args.nonEmpty && (ct == IntTag || ! args.head.startsWith(" -" ))
249
+ inline def argAfterParam = ! argInArgRest && args.nonEmpty && (ct == IntTag || ! args.head.startsWith(" -" ))
238
250
if argInArgRest then
239
251
doSetArg(argRest, args)
240
252
else if argAfterParam then
241
253
doSetArg(args.head, args.tail)
242
- else missingArg
254
+ else if isEmptyDefault then
255
+ missingArg
256
+ else
257
+ doSetArg(arg = null , args)
243
258
244
- def doSetArg (arg : String , argsLeft : List [String ]) = summon[ClassTag [T ]] match
259
+ def doSetArg (arg : String , argsLeft : List [String ]) =
260
+ classTag[T ] match
261
+ case ListTag if arg == null =>
262
+ update(default, arg, argsLeft)
245
263
case ListTag =>
246
264
val strings = arg.split(" ," ).toList
247
265
appendList(strings, arg, argsLeft)
@@ -297,6 +315,7 @@ object Settings:
297
315
object Setting :
298
316
extension [T ](setting : Setting [T ])
299
317
def value (using Context ): T = setting.valueIn(ctx.settingsState)
318
+ def userValue (using Context ): Option [T ] = setting.userValueIn(ctx.settingsState)
300
319
def update (x : T )(using Context ): SettingsState = setting.updateIn(ctx.settingsState, x)
301
320
def isDefault (using Context ): Boolean = setting.isDefaultIn(ctx.settingsState)
302
321
@@ -427,7 +446,7 @@ object Settings:
427
446
publish(Setting (category, prependName(name), descr, default, legacyArgs = legacyArgs, deprecation = deprecation))
428
447
429
448
def OptionSetting [T : ClassTag ](category : SettingCategory , name : String , descr : String , aliases : List [String ] = Nil , deprecation : Option [Deprecation ] = None ): Setting [Option [T ]] =
430
- publish(Setting (category, prependName(name), descr, None , propertyClass = Some (summon[ ClassTag [ T ] ].runtimeClass), aliases = aliases, deprecation = deprecation))
449
+ publish(Setting (category, prependName(name), descr, None , propertyClass = Some (classTag[ T ].runtimeClass), aliases = aliases, deprecation = deprecation))
431
450
432
451
end SettingGroup
433
452
end Settings
0 commit comments