Skip to content

Commit afe99fc

Browse files
authored
SemanticChecks: Avoid repeated type resolution of [ordered] (PowerShell#17328)
1 parent 391e080 commit afe99fc

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

src/System.Management.Automation/engine/parser/SemanticChecks.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,13 @@ public override AstVisitAction VisitConvertExpression(ConvertExpressionAst conve
920920
ParserStrings.OrderedAttributeOnlyOnHashLiteralNode,
921921
convertExpressionAst.Type.TypeName.FullName);
922922
}
923+
924+
// Currently, the type name '[ordered]' is handled specially in PowerShell.
925+
// When used in a conversion expression, it's only allowed on a hashliteral node, and it's
926+
// always interpreted as an initializer for a case-insensitive
927+
// 'System.Collections.Specialized.OrderedDictionary' by the compiler.
928+
// So, we can return early from here.
929+
return AstVisitAction.Continue;
923930
}
924931

925932
if (typeof(PSReference) == convertExpressionAst.Type.TypeName.GetReflectionType())

test/powershell/Language/Scripting/Scripting.Followup.Tests.ps1

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,31 @@ Describe "Scripting.Followup.Tests" -Tags "CI" {
4141
$obj.ForEach('p', 32) | Should -BeNullOrEmpty
4242
$obj.p | Should -Be 32
4343
}
44+
45+
It "Test the special type name 'ordered'" {
46+
class ordered {
47+
[hashtable] $Member
48+
ordered([hashtable] $hash) {
49+
$this.Member = $hash
50+
}
51+
}
52+
53+
## `<expr> -as\-is [ordered]` resolves 'ordered' as a normal type name.
54+
$hash = @{ key = 2 }
55+
$result = $hash -as [ordered]
56+
$result.GetType().FullName | Should -BeExactly ([ordered].FullName)
57+
$result -is [ordered] | Should -BeTrue
58+
$result.Member['key'] | Should -Be 2
59+
$result.Member.Count | Should -Be 1
60+
61+
## `[ordered]$hash` causes parsing error.
62+
$err = $null
63+
$null = [System.Management.Automation.Language.Parser]::ParseInput('[ordered]$hash', [ref]$null, [ref]$err)
64+
$err.Count | Should -Be 1
65+
$err[0].ErrorId | Should -BeExactly 'OrderedAttributeOnlyOnHashLiteralNode'
66+
67+
## `[ordered]@{ key = 1 }` creates 'OrderedDictionary'
68+
$result = [ordered]@{ key = 1 }
69+
$result | Should -BeOfType 'System.Collections.Specialized.OrderedDictionary'
70+
}
4471
}

0 commit comments

Comments
 (0)