Skip to content

Commit 98a97c2

Browse files
Fix declaration detection for variables with type constraints (#2006)
1 parent 824fd4f commit 98a97c2

File tree

4 files changed

+57
-1
lines changed

4 files changed

+57
-1
lines changed

src/PowerShellEditorServices/Services/Symbols/Visitors/SymbolVisitor.cs

+22-1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,27 @@ public override AstVisitAction VisitVariableExpression(VariableExpressionAst var
110110
));
111111
}
112112

113+
// Traverse the parents to determine if this is a declaration.
114+
static bool isDeclaration(Ast current)
115+
{
116+
Ast next = current.Parent;
117+
while (true)
118+
{
119+
// Should come from an assignment statement.
120+
if (next is AssignmentStatementAst assignment)
121+
{
122+
return assignment.Left == current;
123+
}
124+
// Or we might have type constraints or attributes to traverse first.
125+
if (next is not ConvertExpressionAst or not AttributedExpressionAst)
126+
{
127+
return false;
128+
}
129+
current = next;
130+
next = next.Parent;
131+
}
132+
}
133+
113134
// TODO: Consider tracking unscoped variable references only when they're declared within
114135
// the same function definition.
115136
return _action(new SymbolReference(
@@ -119,7 +140,7 @@ public override AstVisitAction VisitVariableExpression(VariableExpressionAst var
119140
variableExpressionAst.Extent,
120141
variableExpressionAst.Extent, // TODO: Maybe parent?
121142
_file,
122-
isDeclaration: variableExpressionAst.Parent is AssignmentStatementAst or ParameterAst));
143+
isDeclaration(variableExpressionAst)));
123144
}
124145

125146
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
5+
6+
namespace Microsoft.PowerShell.EditorServices.Test.Shared.Definition
7+
{
8+
public static class FindsTypedVariableDefinitionData
9+
{
10+
public static readonly ScriptRegion SourceDetails = new(
11+
file: TestUtilities.NormalizePath("References/SimpleFile.ps1"),
12+
text: string.Empty,
13+
startLineNumber: 25,
14+
startColumnNumber: 13,
15+
startOffset: 0,
16+
endLineNumber: 0,
17+
endColumnNumber: 0,
18+
endOffset: 0);
19+
}
20+
}

test/PowerShellEditorServices.Test.Shared/References/SimpleFile.ps1

+3
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ Get-ChildItem
2020
My-Alias
2121

2222
Invoke-Command -ScriptBlock ${Function:My-Function}
23+
24+
[string]$hello = "test"
25+
Write-Host $hello

test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs

+12
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,18 @@ public async Task FindsVariableDefinition()
300300
AssertIsRegion(symbol.NameRegion, 6, 1, 6, 8);
301301
}
302302

303+
[Fact]
304+
public async Task FindsTypedVariableDefinition()
305+
{
306+
IEnumerable<SymbolReference> definitions = await GetDefinitions(FindsTypedVariableDefinitionData.SourceDetails).ConfigureAwait(true);
307+
SymbolReference symbol = Assert.Single(definitions);
308+
Assert.Equal("var hello", symbol.Id);
309+
Assert.Equal("$hello", symbol.Name);
310+
Assert.Equal(SymbolType.Variable, symbol.Type);
311+
Assert.True(symbol.IsDeclaration);
312+
AssertIsRegion(symbol.NameRegion, 24, 9, 24, 15);
313+
}
314+
303315
[Fact]
304316
public async Task FindsReferencesOnVariable()
305317
{

0 commit comments

Comments
 (0)