From 9b5ac40f1f3a29109781c87036dc1724f7ebd782 Mon Sep 17 00:00:00 2001 From: MartinGC94 Date: Fri, 26 Jan 2024 13:31:18 +0100 Subject: [PATCH 1/4] Improve assignment type inference --- .../engine/parser/TypeInferenceVisitor.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs b/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs index 1e1ff771ac5..c242f32deb9 100644 --- a/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs +++ b/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs @@ -1036,7 +1036,12 @@ object ICustomAstVisitor.VisitDoUntilStatement(DoUntilStatementAst doUntilStatem object ICustomAstVisitor.VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst) { - return assignmentStatementAst.Left.Accept(this); + if (assignmentStatementAst.Left is ConvertExpressionAst convertExpression) + { + return new List() { new(convertExpression.Type.TypeName) }; + } + + return assignmentStatementAst.Right.Accept(this); } object ICustomAstVisitor.VisitPipeline(PipelineAst pipelineAst) From 9e31c29c2fcefeab6748c64f73bb1c1ab1e12e21 Mon Sep 17 00:00:00 2001 From: MartinGC94 Date: Wed, 19 Feb 2025 17:46:01 +0100 Subject: [PATCH 2/4] Handle attributed assignments --- .../engine/parser/TypeInferenceVisitor.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs b/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs index 4bef79983ab..5e52372c176 100644 --- a/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs +++ b/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs @@ -1077,9 +1077,23 @@ object ICustomAstVisitor.VisitDoUntilStatement(DoUntilStatementAst doUntilStatem object ICustomAstVisitor.VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst) { - if (assignmentStatementAst.Left is ConvertExpressionAst convertExpression) + if (assignmentStatementAst.Left is AttributedExpressionAst attributedExpression) { - return new List() { new(convertExpression.Type.TypeName) }; + if (attributedExpression is ConvertExpressionAst convertExpression) + { + return new List() { new(convertExpression.Type.TypeName) }; + } + + ExpressionAst child = attributedExpression.Child; + while (child is AttributedExpressionAst attributeChild) + { + if (attributeChild is ConvertExpressionAst convert) + { + return new List() { new(convert.Type.TypeName) }; + } + + child = attributeChild; + } } return assignmentStatementAst.Right.Accept(this); From aa74ecf47e964d902f16e847eca9f58a0e8a54dd Mon Sep 17 00:00:00 2001 From: MartinGC94 Date: Thu, 13 Mar 2025 19:56:02 +0100 Subject: [PATCH 3/4] Add test --- .../engine/Api/TypeInference.Tests.ps1 | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/powershell/engine/Api/TypeInference.Tests.ps1 b/test/powershell/engine/Api/TypeInference.Tests.ps1 index 2ab5681dddb..e134cfb97ed 100644 --- a/test/powershell/engine/Api/TypeInference.Tests.ps1 +++ b/test/powershell/engine/Api/TypeInference.Tests.ps1 @@ -1469,6 +1469,26 @@ Describe "Type inference Tests" -tags "CI" { $res.Count | Should -Be 0 } + It 'Infers right side of assignment expression' { + $res = [AstTypeInference]::InferTypeOf( { $Test1 = "Hello" }.Ast.Find({param($ast) $ast -is [Language.AssignmentStatementAst]}, $true)) + $res.Count | Should -Be 1 + $res.Name | Should -Be "System.String" + } + + It 'Infers left side of assignment expression when it is a ConvertExpression' { + $res = [AstTypeInference]::InferTypeOf( { [string]$Test1 = 42 }.Ast.Find({param($ast) $ast -is [Language.AssignmentStatementAst]}, $true)) + $res.Count | Should -Be 1 + $res.Name | Should -Be "System.String" + } + + It 'Infers left side of assignment expression when there is a ConvertExpression among other attributes' { + $res = [AstTypeInference]::InferTypeOf( { + [ValidateLength()] [string] [ValidatePattern()]$Test1 = 42 + }.Ast.Find({param($ast) $ast -is [Language.AssignmentStatementAst]}, $true)) + $res.Count | Should -Be 1 + $res.Name | Should -Be "System.String" + } + It 'Infers type of all scope variable after variable assignment' { $res = [AstTypeInference]::InferTypeOf( { $true = "Hello";$true }.Ast) $res.Count | Should -Be 1 From c96b4d428f14466175bcb6a9b2de7a6f411480f0 Mon Sep 17 00:00:00 2001 From: MartinGC94 <42123497+MartinGC94@users.noreply.github.com> Date: Fri, 14 Mar 2025 08:31:41 +0100 Subject: [PATCH 4/4] Update src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs Co-authored-by: Ilya --- .../engine/parser/TypeInferenceVisitor.cs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs b/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs index 767e4ba12b6..9d14d2a1b38 100644 --- a/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs +++ b/src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs @@ -1241,23 +1241,15 @@ object ICustomAstVisitor.VisitDoUntilStatement(DoUntilStatementAst doUntilStatem object ICustomAstVisitor.VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst) { - if (assignmentStatementAst.Left is AttributedExpressionAst attributedExpression) + ExpressionAst child = assignmentStatementAst.Left; + while (child is AttributedExpressionAst attributeChild) { - if (attributedExpression is ConvertExpressionAst convertExpression) + if (attributeChild is ConvertExpressionAst convert) { - return new List() { new(convertExpression.Type.TypeName) }; + return new List() { new(convert.Type.TypeName) }; } - ExpressionAst child = attributedExpression.Child; - while (child is AttributedExpressionAst attributeChild) - { - if (attributeChild is ConvertExpressionAst convert) - { - return new List() { new(convert.Type.TypeName) }; - } - - child = attributeChild; - } + child = attributeChild.Child; } return assignmentStatementAst.Right.Accept(this);