Skip to content

Commit a137874

Browse files
committed
support references and definitions
1 parent 060c28f commit a137874

File tree

3 files changed

+381
-3
lines changed

3 files changed

+381
-3
lines changed

src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs

Lines changed: 152 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Microsoft.PowerShell.EditorServices.Services.Symbols
99
/// <summary>
1010
/// The visitor used to find the definition of a symbol
1111
/// </summary>
12-
internal class FindDeclarationVisitor : AstVisitor
12+
internal class FindDeclarationVisitor : AstVisitor2
1313
{
1414
private readonly SymbolReference symbolRef;
1515
private readonly string variableName;
@@ -68,6 +68,157 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
6868
return base.VisitFunctionDefinition(functionDefinitionAst);
6969
}
7070

71+
/// <summary>
72+
/// Decides if the current type definition is the right definition
73+
/// for the symbol being searched for. The definition of the symbol will be a of type
74+
/// SymbolType.Enum or SymbolType.Class and have the same name as the symbol
75+
/// </summary>
76+
/// <param name="typeDefinitionAst">A TypeDefinitionAst in the script's AST</param>
77+
/// <returns>A decision to stop searching if the right TypeDefinitionAst was found,
78+
/// or a decision to continue if it wasn't found</returns>
79+
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst)
80+
{
81+
SymbolType symbolType =
82+
typeDefinitionAst.IsEnum ?
83+
SymbolType.Enum : SymbolType.Class;
84+
85+
if ((symbolRef.SymbolType is SymbolType.Type || symbolRef.SymbolType.Equals(symbolType)) &&
86+
typeDefinitionAst.Name.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
87+
{
88+
// Show only type name. Offset by StartColumn to include indentation etc.
89+
int startColumnNumber =
90+
typeDefinitionAst.Extent.StartColumnNumber +
91+
typeDefinitionAst.Extent.Text.IndexOf(typeDefinitionAst.Name);
92+
93+
IScriptExtent nameExtent = new ScriptExtent()
94+
{
95+
Text = typeDefinitionAst.Name,
96+
StartLineNumber = typeDefinitionAst.Extent.StartLineNumber,
97+
EndLineNumber = typeDefinitionAst.Extent.StartLineNumber,
98+
StartColumnNumber = startColumnNumber,
99+
EndColumnNumber = startColumnNumber + typeDefinitionAst.Name.Length,
100+
File = typeDefinitionAst.Extent.File
101+
};
102+
103+
FoundDeclaration =
104+
new SymbolReference(
105+
symbolType,
106+
nameExtent);
107+
108+
return AstVisitAction.StopVisit;
109+
}
110+
111+
return AstVisitAction.Continue;
112+
}
113+
114+
/// <summary>
115+
/// Decides if the current function member is the right definition
116+
/// for the symbol being searched for. The definition of the symbol will be a of type
117+
/// SymbolType.Constructor or SymbolType.Method and have the same name as the symbol
118+
/// </summary>
119+
/// <param name="functionMemberAst">A FunctionMemberAst in the script's AST</param>
120+
/// <returns>A decision to stop searching if the right FunctionMemberAst was found,
121+
/// or a decision to continue if it wasn't found</returns>
122+
public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)
123+
{
124+
SymbolType symbolType =
125+
functionMemberAst.IsConstructor ?
126+
SymbolType.Constructor : SymbolType.Method;
127+
128+
if (symbolRef.SymbolType.Equals(symbolType) &&
129+
functionMemberAst.Name.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
130+
{
131+
// Show only method/ctor name. Offset by StartColumn to include indentation etc.
132+
int startColumnNumber =
133+
functionMemberAst.Extent.StartColumnNumber +
134+
functionMemberAst.Extent.Text.IndexOf(functionMemberAst.Name);
135+
136+
IScriptExtent nameExtent = new ScriptExtent()
137+
{
138+
Text = functionMemberAst.Name,
139+
StartLineNumber = functionMemberAst.Extent.StartLineNumber,
140+
EndLineNumber = functionMemberAst.Extent.StartLineNumber,
141+
StartColumnNumber = startColumnNumber,
142+
EndColumnNumber = startColumnNumber + functionMemberAst.Name.Length,
143+
File = functionMemberAst.Extent.File
144+
};
145+
146+
FoundDeclaration =
147+
new SymbolReference(
148+
symbolType,
149+
nameExtent);
150+
151+
return AstVisitAction.StopVisit;
152+
}
153+
154+
return AstVisitAction.Continue;
155+
}
156+
157+
/// <summary>
158+
/// Decides if the current property member is the right definition
159+
/// for the symbol being searched for. The definition of the symbol will be a of type
160+
/// SymbolType.Property and have the same name as the symbol
161+
/// </summary>
162+
/// <param name="propertyMemberAst">A PropertyMemberAst in the script's AST</param>
163+
/// <returns>A decision to stop searching if the right PropertyMemberAst was found,
164+
/// or a decision to continue if it wasn't found</returns>
165+
public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
166+
{
167+
if (symbolRef.SymbolType.Equals(SymbolType.Property) &&
168+
propertyMemberAst.Name.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
169+
{
170+
FoundDeclaration =
171+
new SymbolReference(
172+
SymbolType.Property,
173+
propertyMemberAst.Extent);
174+
175+
return AstVisitAction.StopVisit;
176+
}
177+
178+
return AstVisitAction.Continue;
179+
}
180+
181+
/// <summary>
182+
/// Decides if the current configuration definition is the right definition
183+
/// for the symbol being searched for. The definition of the symbol will be a of type
184+
/// SymbolType.Configuration and have the same name as the symbol
185+
/// </summary>
186+
/// <param name="configurationDefinitionAst">A ConfigurationDefinitionAst in the script's AST</param>
187+
/// <returns>A decision to stop searching if the right ConfigurationDefinitionAst was found,
188+
/// or a decision to continue if it wasn't found</returns>
189+
public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
190+
{
191+
string configurationName = configurationDefinitionAst.InstanceName.Extent.Text;
192+
193+
if (symbolRef.SymbolType.Equals(SymbolType.Configuration) &&
194+
configurationName.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
195+
{
196+
// Show only configuration name. Offset by StartColumn to include indentation etc.
197+
int startColumnNumber =
198+
configurationDefinitionAst.Extent.StartColumnNumber +
199+
configurationDefinitionAst.Extent.Text.IndexOf(configurationName);
200+
201+
IScriptExtent nameExtent = new ScriptExtent()
202+
{
203+
Text = configurationName,
204+
StartLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
205+
EndLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
206+
StartColumnNumber = startColumnNumber,
207+
EndColumnNumber = startColumnNumber + configurationName.Length,
208+
File = configurationDefinitionAst.Extent.File
209+
};
210+
211+
FoundDeclaration =
212+
new SymbolReference(
213+
SymbolType.Configuration,
214+
nameExtent);
215+
216+
return AstVisitAction.StopVisit;
217+
}
218+
219+
return AstVisitAction.Continue;
220+
}
221+
71222
/// <summary>
72223
/// Check if the left hand side of an assignmentStatementAst is a VariableExpressionAst
73224
/// with the same name as that of symbolRef.

src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs

Lines changed: 161 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation.
1+
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

44
using System;
@@ -11,7 +11,7 @@ namespace Microsoft.PowerShell.EditorServices.Services.Symbols
1111
/// <summary>
1212
/// The visitor used to find the references of a symbol in a script's AST
1313
/// </summary>
14-
internal class FindReferencesVisitor : AstVisitor
14+
internal class FindReferencesVisitor : AstVisitor2
1515
{
1616
private readonly SymbolReference _symbolRef;
1717
private readonly IDictionary<string, List<string>> _cmdletToAliasDictionary;
@@ -168,5 +168,164 @@ public override AstVisitAction VisitVariableExpression(VariableExpressionAst var
168168
}
169169
return AstVisitAction.Continue;
170170
}
171+
172+
/// <summary>
173+
/// Decides if the current type definition is a reference of the symbol being searched for.
174+
/// A reference of the symbol will be a of type SymbolType.Class or SymbolType.Enum and have the same name as the symbol
175+
/// </summary>
176+
/// <param name="typeDefinitionAst">A TypeDefinitionAst in the script's AST</param>
177+
/// <returns>A visit action that continues the search for references</returns>
178+
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst)
179+
{
180+
SymbolType symbolType =
181+
typeDefinitionAst.IsEnum ?
182+
SymbolType.Enum : SymbolType.Class;
183+
184+
if ((_symbolRef.SymbolType is SymbolType.Type || _symbolRef.SymbolType.Equals(symbolType)) &&
185+
typeDefinitionAst.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
186+
{
187+
// Show only type name. Offset by StartColumn to include indentation etc.
188+
int startColumnNumber =
189+
typeDefinitionAst.Extent.StartColumnNumber +
190+
typeDefinitionAst.Extent.Text.IndexOf(typeDefinitionAst.Name);
191+
192+
IScriptExtent nameExtent = new ScriptExtent()
193+
{
194+
Text = typeDefinitionAst.Name,
195+
StartLineNumber = typeDefinitionAst.Extent.StartLineNumber,
196+
EndLineNumber = typeDefinitionAst.Extent.StartLineNumber,
197+
StartColumnNumber = startColumnNumber,
198+
EndColumnNumber = startColumnNumber + typeDefinitionAst.Name.Length,
199+
File = typeDefinitionAst.Extent.File
200+
};
201+
202+
FoundReferences.Add(new SymbolReference(symbolType, nameExtent));
203+
}
204+
return AstVisitAction.Continue;
205+
}
206+
207+
/// <summary>
208+
/// Decides if the current type expression is a reference of the symbol being searched for.
209+
/// A reference of the symbol will be a of type SymbolType.Type and have the same name as the symbol
210+
/// </summary>
211+
/// <param name="typeExpressionAst">A TypeExpressionAst in the script's AST</param>
212+
/// <returns>A visit action that continues the search for references</returns>
213+
public override AstVisitAction VisitTypeExpression(TypeExpressionAst typeExpressionAst)
214+
{
215+
// We don't know if we're looking at a class or enum, but name is likely unique
216+
if (IsTypeSymbol(_symbolRef.SymbolType) &&
217+
typeExpressionAst.TypeName.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
218+
{
219+
FoundReferences.Add(new SymbolReference(SymbolType.Type, typeExpressionAst.Extent));
220+
}
221+
return AstVisitAction.Continue;
222+
}
223+
224+
/// <summary>
225+
/// Decides if the current type constraint is a reference of the symbol being searched for.
226+
/// A reference of the symbol will be a of type SymbolType.Type and have the same name as the symbol
227+
/// </summary>
228+
/// <param name="typeConstraintAst">A TypeConstraintAst in the script's AST</param>
229+
/// <returns>A visit action that continues the search for references</returns>
230+
public override AstVisitAction VisitTypeConstraint(TypeConstraintAst typeConstraintAst)
231+
{
232+
// We don't know if we're looking at a class or enum, but name is likely unique
233+
if (IsTypeSymbol(_symbolRef.SymbolType) &&
234+
typeConstraintAst.TypeName.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
235+
{
236+
FoundReferences.Add(new SymbolReference(SymbolType.Type, typeConstraintAst.Extent));
237+
}
238+
return AstVisitAction.Continue;
239+
}
240+
241+
/// <summary>
242+
/// Decides if the current function member is a reference of the symbol being searched for.
243+
/// A reference of the symbol will be a of type SymbolType.Constructor or SymbolType.Method and have the same name as the symbol
244+
/// </summary>
245+
/// <param name="functionMemberAst">A FunctionMemberAst in the script's AST</param>
246+
/// <returns>A visit action that continues the search for references</returns>
247+
public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)
248+
{
249+
SymbolType symbolType =
250+
functionMemberAst.IsConstructor ?
251+
SymbolType.Constructor : SymbolType.Method;
252+
253+
if (_symbolRef.SymbolType.Equals(symbolType) &&
254+
functionMemberAst.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
255+
{
256+
// Show only method/ctor name. Offset by StartColumn to include indentation etc.
257+
int startColumnNumber =
258+
functionMemberAst.Extent.StartColumnNumber +
259+
functionMemberAst.Extent.Text.IndexOf(functionMemberAst.Name);
260+
261+
IScriptExtent nameExtent = new ScriptExtent()
262+
{
263+
Text = functionMemberAst.Name,
264+
StartLineNumber = functionMemberAst.Extent.StartLineNumber,
265+
EndLineNumber = functionMemberAst.Extent.StartLineNumber,
266+
StartColumnNumber = startColumnNumber,
267+
EndColumnNumber = startColumnNumber + functionMemberAst.Name.Length,
268+
File = functionMemberAst.Extent.File
269+
};
270+
271+
FoundReferences.Add(new SymbolReference(symbolType, nameExtent));
272+
}
273+
return AstVisitAction.Continue;
274+
}
275+
276+
/// <summary>
277+
/// Decides if the current property member is a reference of the symbol being searched for.
278+
/// A reference of the symbol will be a of type SymbolType.Property and have the same name as the symbol
279+
/// </summary>
280+
/// <param name="propertyMemberAst">A PropertyMemberAst in the script's AST</param>
281+
/// <returns>A visit action that continues the search for references</returns>
282+
public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
283+
{
284+
if (_symbolRef.SymbolType.Equals(SymbolType.Property) &&
285+
propertyMemberAst.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
286+
{
287+
FoundReferences.Add(new SymbolReference(SymbolType.Property, propertyMemberAst.Extent));
288+
}
289+
return AstVisitAction.Continue;
290+
}
291+
292+
/// <summary>
293+
/// Decides if the current configuration definition is a reference of the symbol being searched for.
294+
/// A reference of the symbol will be a of type SymbolType.Configuration and have the same name as the symbol
295+
/// </summary>
296+
/// <param name="configurationDefinitionAst">A ConfigurationDefinitionAst in the script's AST</param>
297+
/// <returns>A visit action that continues the search for references</returns>
298+
public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
299+
{
300+
string configurationName = configurationDefinitionAst.InstanceName.Extent.Text;
301+
302+
if (_symbolRef.SymbolType.Equals(SymbolType.Configuration) &&
303+
configurationName.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
304+
{
305+
// Show only configuration name. Offset by StartColumn to include indentation etc.
306+
int startColumnNumber =
307+
configurationDefinitionAst.Extent.StartColumnNumber +
308+
configurationDefinitionAst.Extent.Text.IndexOf(configurationName);
309+
310+
IScriptExtent nameExtent = new ScriptExtent()
311+
{
312+
Text = configurationName,
313+
StartLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
314+
EndLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
315+
StartColumnNumber = startColumnNumber,
316+
EndColumnNumber = startColumnNumber + configurationName.Length,
317+
File = configurationDefinitionAst.Extent.File
318+
};
319+
320+
FoundReferences.Add(new SymbolReference(SymbolType.Configuration, nameExtent));
321+
}
322+
return AstVisitAction.Continue;
323+
}
324+
325+
/// <summary>
326+
/// Tests if symbol type is a type (class/enum) definition or type reference.
327+
/// </summary>
328+
private static bool IsTypeSymbol(SymbolType symbolType)
329+
=> symbolType is SymbolType.Class or SymbolType.Enum or SymbolType.Type;
171330
}
172331
}

0 commit comments

Comments
 (0)