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