@@ -252,13 +252,14 @@ private bool IsStringOrStringArray(object val)
252
252
return val == null ? false : valArr . All ( x => x is string ) ;
253
253
}
254
254
255
- private List < string > ParseSettingValueStringOrStrings ( object value , string settingName )
255
+ private List < string > ParseSettingValueStringOrStrings ( object value , string settingName , IList < Exception > exceptions )
256
256
{
257
257
if ( value == null )
258
258
{
259
- throw new InvalidDataException ( string . Format (
259
+ exceptions . Add ( new InvalidDataException ( string . Format (
260
260
Strings . SettingValueIsNull ,
261
- settingName ) ) ;
261
+ settingName ) ) ) ;
262
+ return null ;
262
263
}
263
264
264
265
if ( value is string )
@@ -268,9 +269,10 @@ private List<string> ParseSettingValueStringOrStrings(object value, string setti
268
269
269
270
if ( ! ( value is ICollection ) )
270
271
{
271
- throw new InvalidDataException ( string . Format (
272
+ exceptions . Add ( new InvalidDataException ( string . Format (
272
273
Strings . SettingValueIsNotStringOrStringsType ,
273
- settingName ) ) ;
274
+ settingName ) ) ) ;
275
+ return null ;
274
276
}
275
277
var values = value as ICollection ;
276
278
@@ -280,19 +282,21 @@ private List<string> ParseSettingValueStringOrStrings(object value, string setti
280
282
{
281
283
if ( element is null )
282
284
{
283
- throw new InvalidDataException ( string . Format (
285
+ exceptions . Add ( new InvalidDataException ( string . Format (
284
286
Strings . SettingValueElementIsNull ,
285
287
settingName ,
286
- elementIndex ) ) ;
288
+ elementIndex ) ) ) ;
289
+ continue ;
287
290
}
288
291
289
292
if ( ! ( element is string ) )
290
293
{
291
- throw new InvalidDataException ( string . Format (
294
+ exceptions . Add ( new InvalidDataException ( string . Format (
292
295
Strings . SettingValueElementIsNotStringType ,
293
296
settingName ,
294
297
elementIndex ,
295
- element ) ) ;
298
+ element ) ) ) ;
299
+ continue ;
296
300
}
297
301
strings . Add ( element as string ) ;
298
302
@@ -302,92 +306,138 @@ private List<string> ParseSettingValueStringOrStrings(object value, string setti
302
306
return strings ;
303
307
}
304
308
305
- private bool ParseSettingValueBoolean ( object value , string settingName )
309
+ private bool ? ParseSettingValueBoolean ( object value , string settingName , IList < Exception > exceptions )
306
310
{
307
311
if ( value == null )
308
312
{
309
- throw new InvalidDataException ( string . Format (
313
+ exceptions . Add ( new InvalidDataException ( string . Format (
310
314
Strings . SettingValueIsNull ,
311
- settingName ) ) ;
315
+ settingName ) ) ) ;
316
+ return null ;
312
317
}
313
318
314
319
if ( ! ( value is bool ) )
315
320
{
316
- throw new InvalidDataException ( string . Format (
321
+ exceptions . Add ( new InvalidDataException ( string . Format (
317
322
Strings . SettingValueIsNotBooleanType ,
318
323
settingName ,
319
- value ) ) ;
324
+ value ) ) ) ;
325
+ return null ;
320
326
}
321
327
322
328
return ( bool ) value ;
323
329
}
324
330
325
331
private void ParseSettingsHashtable ( Hashtable settings )
326
332
{
333
+ IList < Exception > exceptions = new List < Exception > ( ) ;
334
+
327
335
ISet < string > uniqueSettingKeys = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
328
336
foreach ( DictionaryEntry setting in settings )
329
337
{
330
338
if ( setting . Key is null )
331
339
{
332
- throw new InvalidDataException ( Strings . SettingKeyIsNull ) ;
340
+ exceptions . Add ( new InvalidDataException (
341
+ Strings . SettingKeyIsNull ) ) ;
342
+ continue ;
333
343
}
334
344
335
345
if ( ! ( setting . Key is string ) )
336
346
{
337
- throw new InvalidDataException ( string . Format (
347
+ exceptions . Add ( new InvalidDataException ( string . Format (
338
348
Strings . SettingKeyIsNotStringType ,
339
- setting . Key ) ) ;
349
+ setting . Key ) ) ) ;
350
+ continue ;
340
351
}
341
352
string settingName = setting . Key as string ;
342
353
343
354
if ( ! uniqueSettingKeys . Add ( settingName ) )
344
355
{
345
356
// setting.Key should be used instead of settingName because the former preserves information about the source casing.
346
- throw new InvalidDataException ( string . Format (
357
+ exceptions . Add ( new InvalidDataException ( string . Format (
347
358
Strings . SettingKeyIsNotUniqueIgnoringCase ,
348
- setting . Key ) ) ;
359
+ setting . Key ) ) ) ;
360
+ continue ;
349
361
}
350
362
351
363
if ( setting . Value is null )
352
364
{
353
- throw new InvalidDataException ( string . Format (
365
+ exceptions . Add ( new InvalidDataException ( string . Format (
354
366
Strings . SettingValueIsNull ,
355
- settingName ) ) ;
367
+ settingName ) ) ) ;
368
+ continue ;
356
369
}
357
370
358
371
// ToLowerInvariant is important to also work with turkish culture, see https://github.com/PowerShell/PSScriptAnalyzer/issues/1095
359
372
switch ( settingName . ToLowerInvariant ( ) )
360
373
{
361
374
case "severity" :
362
- this . severities = ParseSettingValueStringOrStrings ( setting . Value , settingName ) ;
375
+ var maybeSeverity = ParseSettingValueStringOrStrings ( setting . Value , settingName , exceptions ) ;
376
+ if ( maybeSeverity is null )
377
+ {
378
+ continue ;
379
+ }
380
+
381
+ this . severities = maybeSeverity ;
363
382
break ;
364
383
365
384
case "includerules" :
366
- this . includeRules = ParseSettingValueStringOrStrings ( setting . Value , settingName ) ;
385
+ var maybeIncludeRules = ParseSettingValueStringOrStrings ( setting . Value , settingName , exceptions ) ;
386
+ if ( maybeIncludeRules is null )
387
+ {
388
+ continue ;
389
+ }
390
+
391
+ this . includeRules = maybeIncludeRules ;
367
392
break ;
368
393
369
394
case "excluderules" :
370
- this . excludeRules = ParseSettingValueStringOrStrings ( setting . Value , settingName ) ;
395
+ var maybeExcludeRules = ParseSettingValueStringOrStrings ( setting . Value , settingName , exceptions ) ;
396
+ if ( maybeExcludeRules is null )
397
+ {
398
+ continue ;
399
+ }
400
+
401
+ this . excludeRules = maybeExcludeRules ;
371
402
break ;
372
403
373
404
case "customrulepath" :
374
- this . customRulePath = ParseSettingValueStringOrStrings ( setting . Value , settingName ) ;
405
+ var maybeCustomRulePath = ParseSettingValueStringOrStrings ( setting . Value , settingName , exceptions ) ;
406
+ if ( maybeCustomRulePath is null )
407
+ {
408
+ continue ;
409
+ }
410
+
411
+ this . customRulePath = maybeCustomRulePath ;
375
412
break ;
376
413
377
414
case "includedefaultrules" :
378
- this . includeDefaultRules = ParseSettingValueBoolean ( setting . Value , settingName ) ;
415
+ bool ? maybeIncludeDefaultRules = ParseSettingValueBoolean ( setting . Value , settingName , exceptions ) ;
416
+ if ( maybeIncludeDefaultRules is null )
417
+ {
418
+ continue ;
419
+ }
420
+
421
+ this . includeDefaultRules = ( bool ) maybeIncludeDefaultRules ;
379
422
break ;
380
423
381
424
case "recursecustomrulepath" :
382
- this . recurseCustomRulePath = ParseSettingValueBoolean ( setting . Value , settingName ) ;
425
+ bool ? maybeRecurseCustomRulePath = ParseSettingValueBoolean ( setting . Value , settingName , exceptions ) ;
426
+ if ( maybeRecurseCustomRulePath is null )
427
+ {
428
+ continue ;
429
+ }
430
+
431
+ this . recurseCustomRulePath = ( bool ) maybeRecurseCustomRulePath ;
383
432
break ;
384
433
385
434
case "rules" :
386
435
if ( ! ( setting . Value is System . Collections . IDictionary ) )
387
436
{
388
- throw new InvalidDataException ( string . Format (
437
+ exceptions . Add ( new InvalidDataException ( string . Format (
389
438
Strings . SettingRulesValueIsNotDictionaryType ,
390
- setting . Value ) ) ;
439
+ setting . Value ) ) ) ;
440
+ continue ;
391
441
}
392
442
Hashtable rules = setting . Value as Hashtable ;
393
443
@@ -397,38 +447,44 @@ private void ParseSettingsHashtable(Hashtable settings)
397
447
{
398
448
if ( rule . Key is null )
399
449
{
400
- throw new InvalidDataException ( Strings . SettingRuleKeyIsNull ) ;
450
+ exceptions . Add ( new InvalidDataException (
451
+ Strings . SettingRuleKeyIsNull ) ) ;
452
+ continue ;
401
453
}
402
454
403
455
if ( ! ( rule . Key is string ) )
404
456
{
405
- throw new InvalidDataException ( string . Format (
457
+ exceptions . Add ( new InvalidDataException ( string . Format (
406
458
Strings . SettingRuleKeyIsNotStringType ,
407
- rule . Key ) ) ;
459
+ rule . Key ) ) ) ;
460
+ continue ;
408
461
}
409
462
string ruleName = rule . Key as string ;
410
463
411
464
if ( ! uniqueRuleKeys . Add ( ruleName ) )
412
465
{
413
466
// rule.Key should be used instead of ruleName because the former preserves information about the source casing.
414
- throw new InvalidDataException ( string . Format (
467
+ exceptions . Add ( new InvalidDataException ( string . Format (
415
468
Strings . SettingRuleKeyIsNotUniqueIgnoringCase ,
416
- rule . Key ) ) ;
469
+ rule . Key ) ) ) ;
470
+ continue ;
417
471
}
418
472
419
473
if ( rule . Value is null )
420
474
{
421
- throw new InvalidDataException ( string . Format (
475
+ exceptions . Add ( new InvalidDataException ( string . Format (
422
476
Strings . SettingRuleValueIsNull ,
423
- ruleName ) ) ;
477
+ ruleName ) ) ) ;
478
+ continue ;
424
479
}
425
480
426
481
if ( ! ( rule . Value is System . Collections . IDictionary ) )
427
482
{
428
- throw new InvalidDataException ( string . Format (
483
+ exceptions . Add ( new InvalidDataException ( string . Format (
429
484
Strings . SettingRuleValueIsNotDictionaryType ,
430
485
ruleName ,
431
- rule . Value ) ) ;
486
+ rule . Value ) ) ) ;
487
+ continue ;
432
488
}
433
489
Hashtable arguments = rule . Value as Hashtable ;
434
490
@@ -438,35 +494,39 @@ private void ParseSettingsHashtable(Hashtable settings)
438
494
{
439
495
if ( argument . Key is null )
440
496
{
441
- throw new InvalidDataException ( string . Format (
497
+ exceptions . Add ( new InvalidDataException ( string . Format (
442
498
Strings . SettingRuleArgumentKeyIsNull ,
443
- ruleName ) ) ;
499
+ ruleName ) ) ) ;
500
+ continue ;
444
501
}
445
502
446
503
if ( ! ( argument . Key is string ) )
447
504
{
448
- throw new InvalidDataException ( string . Format (
505
+ exceptions . Add ( new InvalidDataException ( string . Format (
449
506
Strings . SettingRuleArgumentKeyIsNotStringType ,
450
507
ruleName ,
451
- argument . Key ) ) ;
508
+ argument . Key ) ) ) ;
509
+ continue ;
452
510
}
453
511
string argumentName = argument . Key as string ;
454
512
455
513
if ( ! uniqueArgumentKeys . Add ( argumentName ) )
456
514
{
457
515
// argument.Key should be used instead of argumentName because the former preserves information about the source casing.
458
- throw new InvalidDataException ( string . Format (
516
+ exceptions . Add ( new InvalidDataException ( string . Format (
459
517
Strings . SettingRuleArgumentKeyIsNotUniqueIgnoringCase ,
460
518
ruleName ,
461
- argument . Key ) ) ;
519
+ argument . Key ) ) ) ;
520
+ continue ;
462
521
}
463
522
464
523
if ( argument . Value is null )
465
524
{
466
- throw new InvalidDataException ( string . Format (
525
+ exceptions . Add ( new InvalidDataException ( string . Format (
467
526
Strings . SettingRuleArgumentValueIsNull ,
468
527
ruleName ,
469
- argumentName ) ) ;
528
+ argumentName ) ) ) ;
529
+ continue ;
470
530
}
471
531
472
532
parsedArguments [ argumentName ] = argument . Value ;
@@ -479,11 +539,17 @@ private void ParseSettingsHashtable(Hashtable settings)
479
539
break ;
480
540
481
541
default :
482
- throw new InvalidDataException ( string . Format (
542
+ exceptions . Add ( new InvalidDataException ( string . Format (
483
543
Strings . WrongKeyHashTable ,
484
- settingName ) ) ;
544
+ settingName ) ) ) ;
545
+ continue ;
485
546
}
486
547
}
548
+
549
+ if ( exceptions . Count > 0 )
550
+ {
551
+ throw new AggregateException ( exceptions ) ;
552
+ }
487
553
}
488
554
489
555
private void ParseSettingsFile ( string settingsFilePath )
0 commit comments