Skip to content

Commit

Permalink
Fix variable type inference precedence (#18691)
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinGC94 authored Jun 12, 2023
1 parent 1822ad7 commit f093f53
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2121,11 +2121,6 @@ private void InferTypeFrom(VariableExpressionAst variableExpressionAst, List<PST
parent = parent.Parent;
}

if (parent.Parent is FunctionDefinitionAst)
{
parent = parent.Parent;
}

int startOffset = variableExpressionAst.Extent.StartOffset;
var targetAsts = (List<Ast>)AstSearcher.FindAll(
parent,
Expand Down Expand Up @@ -2165,9 +2160,9 @@ private void InferTypeFrom(VariableExpressionAst variableExpressionAst, List<PST

// If any of the assignments lhs use a type constraint, then we use that.
// Otherwise, we use the rhs of the "nearest" assignment
foreach (var assignAst in assignAsts)
for (int i = assignAsts.Length - 1; i >= 0; i--)
{
if (assignAst.Left is ConvertExpressionAst lhsConvert)
if (assignAsts[i].Left is ConvertExpressionAst lhsConvert)
{
inferredTypes.Add(new PSTypeName(lhsConvert.Type.TypeName));
return;
Expand Down Expand Up @@ -2592,7 +2587,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
18 changes: 18 additions & 0 deletions test/powershell/engine/Api/TypeInference.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1385,6 +1385,24 @@ Describe "Type inference Tests" -tags "CI" {
$res.Name -join ' ' | Should -Be "System.IO.FileInfo System.IO.DirectoryInfo"
}

It 'Infers closest variable type' {
$res = [AstTypeInference]::InferTypeOf( { [string]$TestVar = "";[hashtable]$TestVar = @{};$TestVar }.Ast)
$res.Name | Select-Object -Last 1 | 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 type of $null after variable assignment' {
$res = [AstTypeInference]::InferTypeOf( { $null = "Hello";$null }.Ast)
$res.Count | Should -Be 0
Expand Down

0 comments on commit f093f53

Please sign in to comment.