Skip to content

Commit

Permalink
Fix typeinference for assignmentstatements inside ParenExpressions. F…
Browse files Browse the repository at this point in the history
…ix type inference for variables that have the same name as unrelated parameters
  • Loading branch information
MartinGC94 committed Dec 2, 2022
1 parent 989134d commit c91e29f
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,17 @@ object ICustomAstVisitor.VisitScriptBlockExpression(ScriptBlockExpressionAst scr

object ICustomAstVisitor.VisitParenExpression(ParenExpressionAst parenExpressionAst)
{
// AssignmentStatements normally return nothing, but when used inside a ParenExpression it returns the left side of the assignment
// For VariableExpressions the right side is used for simplicity, but it doesn't take variable type constraints into consideration
if (parenExpressionAst.Pipeline is AssignmentStatementAst assignment)
{
if (assignment.Left is VariableExpressionAst)
{
return assignment.Right.Accept(this);
}

return assignment.Left.Accept(this);
}
return parenExpressionAst.Pipeline.Accept(this);
}

Expand Down Expand Up @@ -2468,7 +2479,8 @@ public static bool AstAssignsToSameVariable(this VariableExpressionAst variableA
if (parameterAst != null)
{
return variableAstVariablePath.IsUnscopedVariable &&
parameterAst.Name.VariablePath.UnqualifiedPath.Equals(variableAstVariablePath.UnqualifiedPath, StringComparison.OrdinalIgnoreCase);
parameterAst.Name.VariablePath.UnqualifiedPath.Equals(variableAstVariablePath.UnqualifiedPath, StringComparison.OrdinalIgnoreCase) &&
parameterAst.Parent.Parent.Extent.EndOffset > variableAst.Extent.StartOffset;
}

if (ast is ForEachStatementAst foreachAst)
Expand Down
30 changes: 30 additions & 0 deletions test/powershell/engine/Api/TypeInference.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ Describe "Type inference Tests" -tags "CI" {
return $script:inferTypeOf4.Invoke($null, @($ast, $powerShell, $runtimePermissions))
}
}

class TypeConstrainedTestClass
{
[string] $Property1
}
}

It "Infers type from integer" {
Expand Down Expand Up @@ -1359,6 +1364,31 @@ Describe "Type inference Tests" -tags "CI" {
$res = [AstTypeInference]::InferTypeOf( { [string]$TestVar = "";[hashtable]$TestVar = @{};$TestVar }.Ast)
$res.Name | Should -Be "System.Collections.Hashtable"
}

It 'Infers closest variable type and ignores unrelated param blocks' {
$res = [AstTypeInference]::InferTypeOf( {
[hashtable]$ParameterName=@{}
function Verb-Noun {
param
(
[string]$ParameterName
)
}
$ParameterName }.Ast)
$res.Name | Should -Be "System.Collections.Hashtable"
}

It 'Infers output from AssignmentStatement inside ParenExpression' {
$res = [AstTypeInference]::InferTypeOf( { ($TestVar = "Hello") }.Ast)
$res.Name | Should -Be "System.String"
}

It 'Infers output from left side of AssignmentStatement inside ParenExpression when assigning to property' {
$res = [AstTypeInference]::InferTypeOf( {
$Object = [TypeConstrainedTestClass]@{Property1="Test"}
($Object.Property1 = 2) }.Ast)
$res.Name | Should -Be "System.String"
}
}

Describe "AstTypeInference tests" -Tags CI {
Expand Down

0 comments on commit c91e29f

Please sign in to comment.