@@ -475,7 +475,7 @@ private void parseSettingsFile(string settingsFilePath)
475
475
{
476
476
// ideally we should use HashtableAst.SafeGetValue() but since
477
477
// it is not available on PSv3, we resort to our own narrow implementation.
478
- hashtable = GetSafeValueFromHashtableAst ( hashTableAst ) ;
478
+ hashtable = Helper . GetSafeValueFromHashtableAst ( hashTableAst ) ;
479
479
}
480
480
catch ( InvalidOperationException e )
481
481
{
@@ -494,187 +494,6 @@ private void parseSettingsFile(string settingsFilePath)
494
494
parseSettingsHashtable ( hashtable ) ;
495
495
}
496
496
497
- /// <summary>
498
- /// Evaluates all statically evaluable, side-effect-free expressions under an
499
- /// expression AST to return a value.
500
- /// Throws if an expression cannot be safely evaluated.
501
- /// Attempts to replicate the GetSafeValue() method on PowerShell AST methods from PSv5.
502
- /// </summary>
503
- /// <param name="exprAst">The expression AST to try to evaluate.</param>
504
- /// <returns>The .NET value represented by the PowerShell expression.</returns>
505
- private static object GetSafeValueFromExpressionAst ( ExpressionAst exprAst )
506
- {
507
- switch ( exprAst )
508
- {
509
- case ConstantExpressionAst constExprAst :
510
- // Note, this parses top-level command invocations as bareword strings
511
- // However, forbidding this causes hashtable parsing to fail
512
- // It is probably not worth the complexity to isolate this case
513
- return constExprAst . Value ;
514
-
515
- case VariableExpressionAst varExprAst :
516
- // $true and $false are VariableExpressionAsts, so look for them here
517
- switch ( varExprAst . VariablePath . UserPath . ToLowerInvariant ( ) )
518
- {
519
- case "true" :
520
- return true ;
521
-
522
- case "false" :
523
- return false ;
524
-
525
- case "null" :
526
- return null ;
527
-
528
- default :
529
- throw CreateInvalidDataExceptionFromAst ( varExprAst ) ;
530
- }
531
-
532
- case ArrayExpressionAst arrExprAst :
533
-
534
- // Most cases are handled by the inner array handling,
535
- // but we may have an empty array
536
- if ( arrExprAst . SubExpression ? . Statements == null )
537
- {
538
- throw CreateInvalidDataExceptionFromAst ( arrExprAst ) ;
539
- }
540
-
541
- if ( arrExprAst . SubExpression . Statements . Count == 0 )
542
- {
543
- return new object [ 0 ] ;
544
- }
545
-
546
- var listComponents = new List < object > ( ) ;
547
- // Arrays can either be array expressions (1, 2, 3) or array literals with statements @(1 `n 2 `n 3)
548
- // Or they can be a combination of these
549
- // We go through each statement (line) in an array and read the whole subarray
550
- // This will also mean that @(1; 2) is parsed as an array of two elements, but there's not much point defending against this
551
- foreach ( StatementAst statement in arrExprAst . SubExpression . Statements )
552
- {
553
- if ( ! ( statement is PipelineAst pipelineAst ) )
554
- {
555
- throw CreateInvalidDataExceptionFromAst ( arrExprAst ) ;
556
- }
557
-
558
- ExpressionAst pipelineExpressionAst = pipelineAst . GetPureExpression ( ) ;
559
- if ( pipelineExpressionAst == null )
560
- {
561
- throw CreateInvalidDataExceptionFromAst ( arrExprAst ) ;
562
- }
563
-
564
- object arrayValue = GetSafeValueFromExpressionAst ( pipelineExpressionAst ) ;
565
- // We might hit arrays like @(\n1,2,3\n4,5,6), which the parser sees as two statements containing array expressions
566
- if ( arrayValue is object [ ] subArray )
567
- {
568
- listComponents . AddRange ( subArray ) ;
569
- continue ;
570
- }
571
-
572
- listComponents . Add ( arrayValue ) ;
573
- }
574
- return listComponents . ToArray ( ) ;
575
-
576
-
577
- case ArrayLiteralAst arrLiteralAst :
578
- return GetSafeValuesFromArrayAst ( arrLiteralAst ) ;
579
-
580
- case HashtableAst hashtableAst :
581
- return GetSafeValueFromHashtableAst ( hashtableAst ) ;
582
-
583
- default :
584
- // Other expression types are too complicated or fundamentally unsafe
585
- throw CreateInvalidDataExceptionFromAst ( exprAst ) ;
586
- }
587
- }
588
-
589
- /// <summary>
590
- /// Process a PowerShell array literal with statically evaluable/safe contents
591
- /// into a .NET value.
592
- /// </summary>
593
- /// <param name="arrLiteralAst">The PowerShell array AST to turn into a value.</param>
594
- /// <returns>The .NET value represented by PowerShell syntax.</returns>
595
- private static object [ ] GetSafeValuesFromArrayAst ( ArrayLiteralAst arrLiteralAst )
596
- {
597
- if ( arrLiteralAst == null )
598
- {
599
- throw new ArgumentNullException ( nameof ( arrLiteralAst ) ) ;
600
- }
601
-
602
- if ( arrLiteralAst . Elements == null )
603
- {
604
- throw CreateInvalidDataExceptionFromAst ( arrLiteralAst ) ;
605
- }
606
-
607
- var elements = new List < object > ( ) ;
608
- foreach ( ExpressionAst exprAst in arrLiteralAst . Elements )
609
- {
610
- elements . Add ( GetSafeValueFromExpressionAst ( exprAst ) ) ;
611
- }
612
-
613
- return elements . ToArray ( ) ;
614
- }
615
-
616
- /// <summary>
617
- /// Create a hashtable value from a PowerShell AST representing one,
618
- /// provided that the PowerShell expression is statically evaluable and safe.
619
- /// </summary>
620
- /// <param name="hashtableAst">The PowerShell representation of the hashtable value.</param>
621
- /// <returns>The Hashtable as a hydrated .NET value.</returns>
622
- private static Hashtable GetSafeValueFromHashtableAst ( HashtableAst hashtableAst )
623
- {
624
- if ( hashtableAst == null )
625
- {
626
- throw new ArgumentNullException ( nameof ( hashtableAst ) ) ;
627
- }
628
-
629
- if ( hashtableAst . KeyValuePairs == null )
630
- {
631
- throw CreateInvalidDataExceptionFromAst ( hashtableAst ) ;
632
- }
633
-
634
- var hashtable = new Hashtable ( ) ;
635
- foreach ( Tuple < ExpressionAst , StatementAst > entry in hashtableAst . KeyValuePairs )
636
- {
637
- // Get the key
638
- object key = GetSafeValueFromExpressionAst ( entry . Item1 ) ;
639
- if ( key == null )
640
- {
641
- throw CreateInvalidDataExceptionFromAst ( entry . Item1 ) ;
642
- }
643
-
644
- // Get the value
645
- ExpressionAst valueExprAst = ( entry . Item2 as PipelineAst ) ? . GetPureExpression ( ) ;
646
- if ( valueExprAst == null )
647
- {
648
- throw CreateInvalidDataExceptionFromAst ( entry . Item2 ) ;
649
- }
650
-
651
- // Add the key/value entry into the hydrated hashtable
652
- hashtable [ key ] = GetSafeValueFromExpressionAst ( valueExprAst ) ;
653
- }
654
-
655
- return hashtable ;
656
- }
657
-
658
- private static InvalidDataException CreateInvalidDataExceptionFromAst ( Ast ast )
659
- {
660
- if ( ast == null )
661
- {
662
- throw new ArgumentNullException ( nameof ( ast ) ) ;
663
- }
664
-
665
- return CreateInvalidDataException ( ast . Extent ) ;
666
- }
667
-
668
- private static InvalidDataException CreateInvalidDataException ( IScriptExtent extent )
669
- {
670
- return new InvalidDataException ( string . Format (
671
- CultureInfo . CurrentCulture ,
672
- Strings . WrongValueFormat ,
673
- extent . StartLineNumber ,
674
- extent . StartColumnNumber ,
675
- extent . File ?? "" ) ) ;
676
- }
677
-
678
497
private static bool IsBuiltinSettingPreset ( object settingPreset )
679
498
{
680
499
var preset = settingPreset as string ;
0 commit comments