diff --git a/src/PowerShellEditorServices/Language/FindDeclarationVisitor.cs b/src/PowerShellEditorServices/Language/FindDeclarationVisitor.cs
index e706e1199..1f7e8a649 100644
--- a/src/PowerShellEditorServices/Language/FindDeclarationVisitor.cs
+++ b/src/PowerShellEditorServices/Language/FindDeclarationVisitor.cs
@@ -4,6 +4,8 @@
//
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Management.Automation.Language;
namespace Microsoft.PowerShell.EditorServices
@@ -54,7 +56,7 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
};
if (symbolRef.SymbolType.Equals(SymbolType.Function) &&
- nameExtent.Text.Equals(symbolRef.ScriptRegion.Text, StringComparison.CurrentCultureIgnoreCase))
+ nameExtent.Text.Equals(symbolRef.ScriptRegion.Text, StringComparison.CurrentCultureIgnoreCase))
{
this.FoundDeclaration =
new SymbolReference(
@@ -76,19 +78,71 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
/// or a decision to continue if it wasn't found
public override AstVisitAction VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst)
{
- var variableExprAst = assignmentStatementAst.Left as VariableExpressionAst;
- if (variableExprAst == null ||
- variableName == null ||
- !variableExprAst.VariablePath.UserPath.Equals(
- variableName,
- StringComparison.OrdinalIgnoreCase))
+ if (variableName == null)
{
return AstVisitAction.Continue;
}
- // TODO also find instances of set-variable
- FoundDeclaration = new SymbolReference(SymbolType.Variable, variableExprAst.Extent);
- return AstVisitAction.StopVisit;
+ // We want to check VariableExpressionAsts from within this AssignmentStatementAst so we visit it.
+ FindDeclarationVariableExpressionVisitor visitor = new FindDeclarationVariableExpressionVisitor(symbolRef);
+ assignmentStatementAst.Left.Visit(visitor);
+
+ if (visitor.FoundDeclaration != null)
+ {
+ FoundDeclaration = visitor.FoundDeclaration;
+ return AstVisitAction.StopVisit;
+ }
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// The private visitor used to find the variable expression that matches a symbol
+ ///
+ private class FindDeclarationVariableExpressionVisitor : AstVisitor
+ {
+ private SymbolReference symbolRef;
+ private string variableName;
+
+ public SymbolReference FoundDeclaration{ get; private set; }
+
+ public FindDeclarationVariableExpressionVisitor(SymbolReference symbolRef)
+ {
+ this.symbolRef = symbolRef;
+ if (this.symbolRef.SymbolType == SymbolType.Variable)
+ {
+ // converts `$varName` to `varName` or of the form ${varName} to varName
+ variableName = symbolRef.SymbolName.TrimStart('$').Trim('{', '}');
+ }
+ }
+
+ ///
+ /// Check if the VariableExpressionAst has the same name as that of symbolRef.
+ ///
+ /// A VariableExpressionAst
+ /// A decision to stop searching if the right VariableExpressionAst was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst)
+ {
+ if (variableExpressionAst.VariablePath.UserPath.Equals(variableName, StringComparison.OrdinalIgnoreCase))
+ {
+ // TODO also find instances of set-variable
+ FoundDeclaration = new SymbolReference(SymbolType.Variable, variableExpressionAst.Extent);
+ return AstVisitAction.StopVisit;
+ }
+ return AstVisitAction.Continue;
+ }
+
+ public override AstVisitAction VisitMemberExpression(MemberExpressionAst functionDefinitionAst)
+ {
+ // We don't want to discover any variables in member expressisons (`$something.Foo`)
+ return AstVisitAction.SkipChildren;
+ }
+
+ public override AstVisitAction VisitIndexExpression(IndexExpressionAst functionDefinitionAst)
+ {
+ // We don't want to discover any variables in index expressions (`$something[0]`)
+ return AstVisitAction.SkipChildren;
+ }
}
}
}