Skip to content

Commit 9ecc372

Browse files
committed
added functionality to reverse lookup the top variable from a splat
1 parent 0ca7824 commit 9ecc372

File tree

1 file changed

+55
-8
lines changed

1 file changed

+55
-8
lines changed

src/PowerShellEditorServices/Services/PowerShell/Refactoring/IterativeVariableVisitor.cs

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public IterativeVariableRename(string NewName, int StartLineNumber, int StartCol
3535
this.StartColumnNumber = StartColumnNumber;
3636
this.ScriptAst = ScriptAst;
3737

38-
VariableExpressionAst Node = (VariableExpressionAst)VariableRename.GetVariableTopAssignment(StartLineNumber, StartColumnNumber, ScriptAst);
38+
VariableExpressionAst Node = (VariableExpressionAst)GetVariableTopAssignment(StartLineNumber, StartColumnNumber, ScriptAst);
3939
if (Node != null)
4040
{
4141
if (Node.Parent is ParameterAst)
@@ -70,7 +70,7 @@ public static Ast GetAstNodeByLineAndColumn(int StartLineNumber, int StartColumn
7070
{
7171
return ast.Extent.StartLineNumber == StartLineNumber &&
7272
ast.Extent.StartColumnNumber == StartColumnNumber &&
73-
ast is VariableExpressionAst or CommandParameterAst;
73+
ast is VariableExpressionAst or CommandParameterAst or StringConstantExpressionAst;
7474
}, true);
7575
if (result == null)
7676
{
@@ -85,17 +85,40 @@ public static Ast GetVariableTopAssignment(int StartLineNumber, int StartColumnN
8585
// Look up the target object
8686
Ast node = GetAstNodeByLineAndColumn(StartLineNumber, StartColumnNumber, ScriptAst);
8787

88-
string name = node is CommandParameterAst commdef
89-
? commdef.ParameterName
90-
: node is VariableExpressionAst varDef ? varDef.VariablePath.UserPath : throw new TargetSymbolNotFoundException();
88+
string name = node switch
89+
{
90+
CommandParameterAst commdef => commdef.ParameterName,
91+
VariableExpressionAst varDef => varDef.VariablePath.UserPath,
92+
// Key within a Hashtable
93+
StringConstantExpressionAst strExp => strExp.Value,
94+
_ => throw new TargetSymbolNotFoundException()
95+
};
96+
97+
VariableExpressionAst splatAssignment = null;
98+
if (node is StringConstantExpressionAst)
99+
{
100+
Ast parent = node;
101+
while (parent != null)
102+
{
103+
if (parent is AssignmentStatementAst assignmentStatementAst)
104+
{
105+
splatAssignment = (VariableExpressionAst)assignmentStatementAst.Left.Find(ast => ast is VariableExpressionAst, false);
91106

92-
Ast TargetParent = GetAstParentScope(node);
107+
break;
108+
}
109+
parent = parent.Parent;
110+
}
111+
}
93112

113+
Ast TargetParent = GetAstParentScope(node);
114+
// Find All Variables and Parameter Assignments with the same name before
115+
// The node found above
94116
List<VariableExpressionAst> VariableAssignments = ScriptAst.FindAll(ast =>
95117
{
96118
return ast is VariableExpressionAst VarDef &&
97119
VarDef.Parent is AssignmentStatementAst or ParameterAst &&
98120
VarDef.VariablePath.UserPath.ToLower() == name.ToLower() &&
121+
// Look Backwards from the node above
99122
(VarDef.Extent.EndLineNumber < node.Extent.StartLineNumber ||
100123
(VarDef.Extent.EndColumnNumber <= node.Extent.StartColumnNumber &&
101124
VarDef.Extent.EndLineNumber <= node.Extent.StartLineNumber));
@@ -123,7 +146,7 @@ VarDef.Parent is AssignmentStatementAst or ParameterAst &&
123146
CorrectDefinition = node;
124147
break;
125148
}
126-
// node is proably just a reference of an assignment statement within the global scope or higher
149+
// node is proably just a reference to an assignment statement or Parameter within the global scope or higher
127150
if (node.Parent is not AssignmentStatementAst)
128151
{
129152
if (null == parent || null == parent.Parent)
@@ -132,8 +155,32 @@ VarDef.Parent is AssignmentStatementAst or ParameterAst &&
132155
CorrectDefinition = element;
133156
break;
134157
}
135-
if (parent is FunctionDefinitionAst funcDef && node is CommandParameterAst)
158+
159+
if (parent is FunctionDefinitionAst funcDef && node is CommandParameterAst or StringConstantExpressionAst)
136160
{
161+
if (node is StringConstantExpressionAst)
162+
{
163+
List<VariableExpressionAst> SplatReferences = ScriptAst.FindAll(ast =>
164+
{
165+
return ast is VariableExpressionAst varDef &&
166+
varDef.Splatted &&
167+
varDef.Parent is CommandAst &&
168+
varDef.VariablePath.UserPath.ToLower() == splatAssignment.VariablePath.UserPath.ToLower();
169+
}, true).Cast<VariableExpressionAst>().ToList();
170+
171+
if (SplatReferences.Count >= 1)
172+
{
173+
CommandAst splatFirstRefComm = (CommandAst)SplatReferences.First().Parent;
174+
if (funcDef.Name == splatFirstRefComm.GetCommandName()
175+
&& funcDef.Parent.Parent == TargetParent)
176+
{
177+
CorrectDefinition = element;
178+
break;
179+
}
180+
}
181+
}
182+
183+
137184
if (node.Parent is CommandAst commDef)
138185
{
139186
if (funcDef.Name == commDef.GetCommandName()

0 commit comments

Comments
 (0)