Skip to content

Commit 5717ad0

Browse files
Go To Definition works with different Ast types (#706)
* better go to definition * switched to an astvisitor * add a few more overrides * only look at LHS * fix indent
1 parent adc0650 commit 5717ad0

File tree

1 file changed

+64
-10
lines changed

1 file changed

+64
-10
lines changed

src/PowerShellEditorServices/Language/FindDeclarationVisitor.cs

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
//
55

66
using System;
7+
using System.Collections.Generic;
8+
using System.Linq;
79
using System.Management.Automation.Language;
810

911
namespace Microsoft.PowerShell.EditorServices
@@ -54,7 +56,7 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
5456
};
5557

5658
if (symbolRef.SymbolType.Equals(SymbolType.Function) &&
57-
nameExtent.Text.Equals(symbolRef.ScriptRegion.Text, StringComparison.CurrentCultureIgnoreCase))
59+
nameExtent.Text.Equals(symbolRef.ScriptRegion.Text, StringComparison.CurrentCultureIgnoreCase))
5860
{
5961
this.FoundDeclaration =
6062
new SymbolReference(
@@ -76,19 +78,71 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
7678
/// or a decision to continue if it wasn't found</returns>
7779
public override AstVisitAction VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst)
7880
{
79-
var variableExprAst = assignmentStatementAst.Left as VariableExpressionAst;
80-
if (variableExprAst == null ||
81-
variableName == null ||
82-
!variableExprAst.VariablePath.UserPath.Equals(
83-
variableName,
84-
StringComparison.OrdinalIgnoreCase))
81+
if (variableName == null)
8582
{
8683
return AstVisitAction.Continue;
8784
}
8885

89-
// TODO also find instances of set-variable
90-
FoundDeclaration = new SymbolReference(SymbolType.Variable, variableExprAst.Extent);
91-
return AstVisitAction.StopVisit;
86+
// We want to check VariableExpressionAsts from within this AssignmentStatementAst so we visit it.
87+
FindDeclarationVariableExpressionVisitor visitor = new FindDeclarationVariableExpressionVisitor(symbolRef);
88+
assignmentStatementAst.Left.Visit(visitor);
89+
90+
if (visitor.FoundDeclaration != null)
91+
{
92+
FoundDeclaration = visitor.FoundDeclaration;
93+
return AstVisitAction.StopVisit;
94+
}
95+
return AstVisitAction.Continue;
96+
}
97+
98+
/// <summary>
99+
/// The private visitor used to find the variable expression that matches a symbol
100+
/// </summary>
101+
private class FindDeclarationVariableExpressionVisitor : AstVisitor
102+
{
103+
private SymbolReference symbolRef;
104+
private string variableName;
105+
106+
public SymbolReference FoundDeclaration{ get; private set; }
107+
108+
public FindDeclarationVariableExpressionVisitor(SymbolReference symbolRef)
109+
{
110+
this.symbolRef = symbolRef;
111+
if (this.symbolRef.SymbolType == SymbolType.Variable)
112+
{
113+
// converts `$varName` to `varName` or of the form ${varName} to varName
114+
variableName = symbolRef.SymbolName.TrimStart('$').Trim('{', '}');
115+
}
116+
}
117+
118+
/// <summary>
119+
/// Check if the VariableExpressionAst has the same name as that of symbolRef.
120+
/// </summary>
121+
/// <param name="variableExpressionAst">A VariableExpressionAst</param>
122+
/// <returns>A decision to stop searching if the right VariableExpressionAst was found,
123+
/// or a decision to continue if it wasn't found</returns>
124+
public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst)
125+
{
126+
if (variableExpressionAst.VariablePath.UserPath.Equals(variableName, StringComparison.OrdinalIgnoreCase))
127+
{
128+
// TODO also find instances of set-variable
129+
FoundDeclaration = new SymbolReference(SymbolType.Variable, variableExpressionAst.Extent);
130+
return AstVisitAction.StopVisit;
131+
}
132+
return AstVisitAction.Continue;
133+
}
134+
135+
public override AstVisitAction VisitMemberExpression(MemberExpressionAst functionDefinitionAst)
136+
{
137+
// We don't want to discover any variables in member expressisons (`$something.Foo`)
138+
return AstVisitAction.SkipChildren;
139+
}
140+
141+
public override AstVisitAction VisitIndexExpression(IndexExpressionAst functionDefinitionAst)
142+
{
143+
// We don't want to discover any variables in index expressions (`$something[0]`)
144+
return AstVisitAction.SkipChildren;
145+
}
92146
}
93147
}
94148
}

0 commit comments

Comments
 (0)