Update Named and Statement block type inference to not consider AssignmentStatements and Increment/decrement operators as part of their output (#21137)

This commit is contained in:
MartinGC94
2024-12-29 17:29:03 +05:00
committed by GitHub
parent 10d1785030
commit 57dbde625f
2 changed files with 91 additions and 20 deletions
@@ -850,9 +850,20 @@ namespace System.Management.Automation
object ICustomAstVisitor.VisitNamedBlock(NamedBlockAst namedBlockAst)
{
var inferredTypes = new List<PSTypeName>();
for (var index = 0; index < namedBlockAst.Statements.Count; index++)
for (int index = 0; index < namedBlockAst.Statements.Count; index++)
{
var ast = namedBlockAst.Statements[index];
StatementAst ast = namedBlockAst.Statements[index];
if (ast is AssignmentStatementAst
|| (ast is PipelineAst pipe && pipe.PipelineElements.Count == 1 && pipe.PipelineElements[0] is CommandExpressionAst cmd
&& cmd.Redirections.Count == 0 && cmd.Expression is UnaryExpressionAst unary
&& unary.TokenKind is TokenKind.PostfixPlusPlus or TokenKind.PlusPlus or TokenKind.PostfixMinusMinus or TokenKind.MinusMinus))
{
// Assignments don't output anything to the named block unless they are wrapped in parentheses.
// When they are wrapped in parentheses, they are seen as PipelineAst.
// Increment/decrement operators like $i++ also don't output anything unless there's a redirection, or they are wrapped in parentheses.
continue;
}
inferredTypes.AddRange(InferTypes(ast));
}
@@ -921,8 +932,19 @@ namespace System.Management.Automation
object ICustomAstVisitor.VisitStatementBlock(StatementBlockAst statementBlockAst)
{
var inferredTypes = new List<PSTypeName>();
foreach (var ast in statementBlockAst.Statements)
foreach (StatementAst ast in statementBlockAst.Statements)
{
if (ast is AssignmentStatementAst
|| (ast is PipelineAst pipe && pipe.PipelineElements.Count == 1 && pipe.PipelineElements[0] is CommandExpressionAst cmd
&& cmd.Redirections.Count == 0 && cmd.Expression is UnaryExpressionAst unary
&& unary.TokenKind is TokenKind.PostfixPlusPlus or TokenKind.PlusPlus or TokenKind.PostfixMinusMinus or TokenKind.MinusMinus))
{
// Assignments don't output anything to the statement block unless they are wrapped in parentheses.
// When they are wrapped in parentheses, they are seen as PipelineAst.
// Increment operators like $i++ also don't output anything unless there's a redirection, or they are wrapped in parentheses.
continue;
}
inferredTypes.AddRange(InferTypes(ast));
}
@@ -361,10 +361,8 @@ Describe "Type inference Tests" -tags "CI" {
It "Infers type from foreach-object of integer" {
$res = [AstTypeInference]::InferTypeOf( { [int[]] $i = 1..20; $i | ForEach-Object {$_ * 10} }.Ast)
$res.Count | Should -Be 2
foreach ($r in $res) {
$r.Name -In 'System.Int32', 'System.Int32[]' | Should -BeTrue
}
$res.Count | Should -Be 1
$res.Name | Should -Be 'System.Int32'
}
It "Infers type from generic new" {
@@ -386,9 +384,9 @@ Describe "Type inference Tests" -tags "CI" {
It "Infers type from foreach-object with begin/end" {
$res = [AstTypeInference]::InferTypeOf( { [int[]] $i = 1..20; $i | ForEach-Object -Begin {"Hi"} {$_ * 10} -End {[int]} }.Ast)
$res.Count | Should -Be 4
$res.Count | Should -Be 3
foreach ($r in $res) {
$r.Name -In 'System.Int32', 'System.Int32[]', 'System.String', 'System.Type' | Should -BeTrue
$r.Name -In 'System.Int32', 'System.String', 'System.Type' | Should -BeTrue
}
}
@@ -618,16 +616,6 @@ Describe "Type inference Tests" -tags "CI" {
$res.Name | Should -Be 'System.Int32'
}
It 'Infers type from attributed expession' {
$res = [AstTypeInference]::InferTypeOf( {
[ValidateRange(1, 2)]
[int]$i = 1
}.Ast)
$res.Count | Should -Be 1
$res.Name | Should -Be System.Int32
}
It 'Infers type from if statement' {
$res = [AstTypeInference]::InferTypeOf( {
if ($true) { return 1}
@@ -1399,7 +1387,8 @@ Describe "Type inference Tests" -tags "CI" {
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"
$res.Count | Should -Be 1
$res.Name | Should -Be "System.Collections.Hashtable"
}
It 'Infers closest variable type and ignores unrelated param blocks' {
@@ -1444,6 +1433,66 @@ Describe "Type inference Tests" -tags "CI" {
)
$null = [AstTypeInference]::InferTypeOf($FoundAst)
}
It 'Should only consider assignments wrapped in parentheses to be a part of the output in a Named block' {
$res = [AstTypeInference]::InferTypeOf( { [string]$Assignment1 = "Hello"; ([int]$Assignment2 = 42) }.Ast)
$res.Count | Should -Be 1
$res.Name | Should -Be 'System.Int32'
}
It 'Should only consider assignments wrapped in parentheses to be a part of the output in a Statement block' {
$res = [AstTypeInference]::InferTypeOf( { if ($true){ [string]$Assignment1 = "Hello"; ([int]$Assignment2 = 42) }}.Ast)
$res.Count | Should -Be 1
$res.Name | Should -Be 'System.Int32'
}
It 'Should only consider increments/decrements wrapped in parentheses to be a part of the output in a Named block' {
$res = [AstTypeInference]::InferTypeOf( {
[Int16]$Int16 = 1; [Int32]$Int32 = 1; [Int64]$Int64 = 1; [System.Int128]$Int128 = 1;
$Int16++; $Int32--; ++$Int64; --$Int128}.Ast)
$res.Count | Should -Be 0
$res = [AstTypeInference]::InferTypeOf( {
[UInt16]$Uint16 = 1; [UInt32]$Uint32 = 1; [UInt64]$Uint64 = 1; [System.UInt128]$Uint128 = 1
($Uint16++); ($Uint32--); (++$Uint64); (--$Uint128) }.Ast)
$res.Count | Should -Be 4
$res.Name -join ',' | Should -Be ('System.UInt16', 'System.UInt32', 'System.UInt64', 'System.UInt128' -join ',')
}
It 'Should only consider increments/decrements wrapped in parentheses to be a part of the output in a Statement block' {
$res = [AstTypeInference]::InferTypeOf( {if ($true){
[Int16]$Int16 = 1; [Int32]$Int32 = 1; [Int64]$Int64 = 1; [System.Int128]$Int128 = 1;
$Int16++; $Int32--; ++$Int64; --$Int128}}.Ast)
$res.Count | Should -Be 0
$res = [AstTypeInference]::InferTypeOf( {if ($true){
[UInt16]$Uint16 = 1; [UInt32]$Uint32 = 1; [UInt64]$Uint64 = 1; [System.UInt128]$Uint128 = 1
($Uint16++); ($Uint32--); (++$Uint64); (--$Uint128) }}.Ast)
$res.Count | Should -Be 4
$res.Name -join ',' | Should -Be ('System.UInt16', 'System.UInt32', 'System.UInt64', 'System.UInt128' -join ',')
}
It 'Redirected increments/decrements should be considered part of the output in a Named block' {
$res = [AstTypeInference]::InferTypeOf( {
[Int16]$Int16 = 1; [Int32]$Int32 = 1; [Int64]$Int64 = 1; [System.Int128]$Int128 = 1;
$Int16++ *>&1; $Int32-- *>&1; ++$Int64 *>&1; --$Int128 *>&1}.Ast)
$res.Count | Should -Be 4
$res.Name -join ',' | Should -Be ('System.Int16', 'System.Int32', 'System.Int64', 'System.Int128' -join ',')
}
It 'Redirected increments/decrements should be considered part of the output in a Statement block' {
$res = [AstTypeInference]::InferTypeOf( {if ($true){
[Int16]$Int16 = 1; [Int32]$Int32 = 1; [Int64]$Int64 = 1; [System.Int128]$Int128 = 1;
$Int16++ *>&1; $Int32-- *>&1; ++$Int64 *>&1; --$Int128 *>&1}}.Ast)
$res.Count | Should -Be 4
$res.Name -join ',' | Should -Be ('System.Int16', 'System.Int32', 'System.Int64', 'System.Int128' -join ',')
}
}
Describe "AstTypeInference tests" -Tags CI {