From afe99fcaea4c3df7c68cd00529890e29c88a2961 Mon Sep 17 00:00:00 2001 From: "Mathias R. Jessen" Date: Tue, 17 May 2022 18:54:26 +0200 Subject: [PATCH] SemanticChecks: Avoid repeated type resolution of `[ordered]` (#17328) --- .../engine/parser/SemanticChecks.cs | 7 +++++ .../Scripting/Scripting.Followup.Tests.ps1 | 27 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/System.Management.Automation/engine/parser/SemanticChecks.cs b/src/System.Management.Automation/engine/parser/SemanticChecks.cs index b792530193..2e2dcadd64 100644 --- a/src/System.Management.Automation/engine/parser/SemanticChecks.cs +++ b/src/System.Management.Automation/engine/parser/SemanticChecks.cs @@ -920,6 +920,13 @@ namespace System.Management.Automation.Language ParserStrings.OrderedAttributeOnlyOnHashLiteralNode, convertExpressionAst.Type.TypeName.FullName); } + + // Currently, the type name '[ordered]' is handled specially in PowerShell. + // When used in a conversion expression, it's only allowed on a hashliteral node, and it's + // always interpreted as an initializer for a case-insensitive + // 'System.Collections.Specialized.OrderedDictionary' by the compiler. + // So, we can return early from here. + return AstVisitAction.Continue; } if (typeof(PSReference) == convertExpressionAst.Type.TypeName.GetReflectionType()) diff --git a/test/powershell/Language/Scripting/Scripting.Followup.Tests.ps1 b/test/powershell/Language/Scripting/Scripting.Followup.Tests.ps1 index 9a691fa20d..933c53de6d 100644 --- a/test/powershell/Language/Scripting/Scripting.Followup.Tests.ps1 +++ b/test/powershell/Language/Scripting/Scripting.Followup.Tests.ps1 @@ -41,4 +41,31 @@ Describe "Scripting.Followup.Tests" -Tags "CI" { $obj.ForEach('p', 32) | Should -BeNullOrEmpty $obj.p | Should -Be 32 } + + It "Test the special type name 'ordered'" { + class ordered { + [hashtable] $Member + ordered([hashtable] $hash) { + $this.Member = $hash + } + } + + ## ` -as\-is [ordered]` resolves 'ordered' as a normal type name. + $hash = @{ key = 2 } + $result = $hash -as [ordered] + $result.GetType().FullName | Should -BeExactly ([ordered].FullName) + $result -is [ordered] | Should -BeTrue + $result.Member['key'] | Should -Be 2 + $result.Member.Count | Should -Be 1 + + ## `[ordered]$hash` causes parsing error. + $err = $null + $null = [System.Management.Automation.Language.Parser]::ParseInput('[ordered]$hash', [ref]$null, [ref]$err) + $err.Count | Should -Be 1 + $err[0].ErrorId | Should -BeExactly 'OrderedAttributeOnlyOnHashLiteralNode' + + ## `[ordered]@{ key = 1 }` creates 'OrderedDictionary' + $result = [ordered]@{ key = 1 } + $result | Should -BeOfType 'System.Collections.Specialized.OrderedDictionary' + } }