Skip to content

Commit c64a636

Browse files
authored
Fix completion of variables assigned inside Do loops (PowerShell#25076)
1 parent 33d4bf5 commit c64a636

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs

+9-3
Original file line numberDiff line numberDiff line change
@@ -5546,7 +5546,7 @@ private sealed class VariableInfo
55465546
internal Type LastAssignedType;
55475547
}
55485548

5549-
private sealed class FindVariablesVisitor : AstVisitor
5549+
private sealed class FindVariablesVisitor : AstVisitor2
55505550
{
55515551
internal Ast Top;
55525552
internal Ast CompletionVariableAst;
@@ -5621,7 +5621,11 @@ public override AstVisitAction DefaultVisit(Ast ast)
56215621
{
56225622
if (ast.Extent.StartOffset > StopSearchOffset)
56235623
{
5624-
return AstVisitAction.StopVisit;
5624+
// When visiting do while/until statements, the condition will be visited before the statement block.
5625+
// The condition itself may not be interesting if it's after the cursor, but the statement block could be.
5626+
return ast is PipelineBaseAst && ast.Parent is DoUntilStatementAst or DoWhileStatementAst
5627+
? AstVisitAction.SkipChildren
5628+
: AstVisitAction.StopVisit;
56255629
}
56265630

56275631
return AstVisitAction.Continue;
@@ -5631,7 +5635,9 @@ public override AstVisitAction VisitAssignmentStatement(AssignmentStatementAst a
56315635
{
56325636
if (assignmentStatementAst.Extent.StartOffset > StopSearchOffset)
56335637
{
5634-
return AstVisitAction.StopVisit;
5638+
return assignmentStatementAst.Parent is DoUntilStatementAst or DoWhileStatementAst ?
5639+
AstVisitAction.SkipChildren
5640+
: AstVisitAction.StopVisit;
56355641
}
56365642

56375643
if (assignmentStatementAst.Left is AttributedExpressionAst attributedExpression)

test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1

+14
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,20 @@ using `
760760
$completionText -join ' ' | Should -BeExactly 'Equals( new( ReferenceEquals('
761761
}
762762

763+
It 'Should complete variables assigned inside do while loop' {
764+
$TestString = 'do{$Var1 = 1; $Var^ }while ($true)'
765+
$CursorIndex = $TestString.IndexOf('^')
766+
$res = TabExpansion2 -cursorColumn $CursorIndex -inputScript $TestString.Remove($CursorIndex, 1)
767+
$res.CompletionMatches[0].CompletionText | Should -BeExactly '$Var1'
768+
}
769+
770+
It 'Should complete variables assigned inside do until loop' {
771+
$TestString = 'do{$Var1 = 1; $Var^ }until ($null = Get-ChildItem)'
772+
$CursorIndex = $TestString.IndexOf('^')
773+
$res = TabExpansion2 -cursorColumn $CursorIndex -inputScript $TestString.Remove($CursorIndex, 1)
774+
$res.CompletionMatches[0].CompletionText | Should -BeExactly '$Var1'
775+
}
776+
763777
It 'Should show multiple constructors in the tooltip' {
764778
$res = TabExpansion2 -inputScript 'class ConstructorTestClass{ConstructorTestClass ([string] $s){}ConstructorTestClass ([int] $i){}ConstructorTestClass ([int] $i, [bool]$b){}};[ConstructorTestClass]::new'
765779
$res.CompletionMatches | Should -HaveCount 1

0 commit comments

Comments
 (0)