9
9
using Microsoft . PowerShell . EditorServices . Services . TextDocument ;
10
10
using Microsoft . PowerShell . EditorServices . Services . PowerShell . Utility ;
11
11
using Microsoft . PowerShell . EditorServices . Services . Symbols ;
12
+ using System . Collections . Generic ;
13
+ using Microsoft . PowerShell . EditorServices . Utility ;
12
14
13
15
namespace Microsoft . PowerShell . EditorServices . Services ;
14
16
@@ -19,7 +21,7 @@ internal sealed class ReferenceTable
19
21
{
20
22
private readonly ScriptFile _parent ;
21
23
22
- private readonly ConcurrentDictionary < string , ConcurrentBag < IScriptExtent > > _symbolReferences = new ( StringComparer . OrdinalIgnoreCase ) ;
24
+ private readonly ConcurrentDictionary < string , ConcurrentBag < SymbolReference > > _symbolReferences = new ( StringComparer . OrdinalIgnoreCase ) ;
23
25
24
26
private bool _isInited ;
25
27
@@ -41,12 +43,24 @@ public void TagAsChanged()
41
43
/// </summary>
42
44
private bool IsInitialized => ! _symbolReferences . IsEmpty || _isInited ;
43
45
44
- internal bool TryGetReferences ( string command , out ConcurrentBag < IScriptExtent > ? references )
46
+ internal bool TryGetReferences ( string command , out ConcurrentBag < SymbolReference > ? references )
45
47
{
46
48
EnsureInitialized ( ) ;
47
49
return _symbolReferences . TryGetValue ( command , out references ) ;
48
50
}
49
51
52
+ // TODO: Should this be improved, or pre-sorted?
53
+ internal IReadOnlyList < SymbolReference > GetAllReferences ( )
54
+ {
55
+ EnsureInitialized ( ) ;
56
+ List < SymbolReference > allReferences = new ( ) ;
57
+ foreach ( ConcurrentBag < SymbolReference > bag in _symbolReferences . Values )
58
+ {
59
+ allReferences . AddRange ( bag ) ;
60
+ }
61
+ return allReferences ;
62
+ }
63
+
50
64
internal void EnsureInitialized ( )
51
65
{
52
66
if ( IsInitialized )
@@ -57,51 +71,73 @@ internal void EnsureInitialized()
57
71
_parent . ScriptAst . Visit ( new ReferenceVisitor ( this ) ) ;
58
72
}
59
73
60
- private void AddReference ( string symbol , IScriptExtent extent )
74
+ private void AddReference ( SymbolType type , string name , IScriptExtent extent )
61
75
{
76
+ SymbolReference symbol = new ( type , name , extent , _parent ) ;
62
77
_symbolReferences . AddOrUpdate (
63
- symbol ,
64
- _ => new ConcurrentBag < IScriptExtent > { extent } ,
78
+ name ,
79
+ _ => new ConcurrentBag < SymbolReference > { symbol } ,
65
80
( _ , existing ) =>
66
81
{
67
- existing . Add ( extent ) ;
82
+ existing . Add ( symbol ) ;
68
83
return existing ;
69
84
} ) ;
70
85
}
71
86
72
- private sealed class ReferenceVisitor : AstVisitor
87
+ // TODO: Should we move this to AstOperations.cs? It is highly coupled to `ReferenceTable`,
88
+ // perhaps it doesn't have to be.
89
+ private sealed class ReferenceVisitor : AstVisitor2
73
90
{
74
91
private readonly ReferenceTable _references ;
75
92
76
93
public ReferenceVisitor ( ReferenceTable references ) => _references = references ;
77
94
78
- private static string ? GetCommandName ( CommandAst commandAst )
95
+ public override AstVisitAction VisitCommand ( CommandAst commandAst )
79
96
{
80
- string commandName = commandAst . GetCommandName ( ) ;
81
- if ( ! string . IsNullOrEmpty ( commandName ) )
97
+ string ? commandName = VisitorUtils . GetCommandName ( commandAst ) ;
98
+ if ( string . IsNullOrEmpty ( commandName ) )
82
99
{
83
- return commandName ;
100
+ return AstVisitAction . Continue ;
84
101
}
85
102
86
- if ( commandAst . CommandElements [ 0 ] is not ExpandableStringExpressionAst expandableStringExpressionAst )
87
- {
88
- return null ;
89
- }
103
+ _references . AddReference (
104
+ SymbolType . Function ,
105
+ CommandHelpers . StripModuleQualification ( commandName , out _ ) ,
106
+ commandAst . CommandElements [ 0 ] . Extent
107
+ ) ;
90
108
91
- return AstOperations . TryGetInferredValue ( expandableStringExpressionAst , out string value ) ? value : null ;
109
+ return AstVisitAction . Continue ;
92
110
}
93
111
94
- public override AstVisitAction VisitCommand ( CommandAst commandAst )
112
+ // TODO: We should examine if we really want to constrain the extents to the name only. This
113
+ // means that highlighting only highlights the symbol name, but providing the whole extend
114
+ // means the whole function (or class etc.) gets highlighted, which seems to be a personal
115
+ // preference.
116
+ public override AstVisitAction VisitFunctionDefinition ( FunctionDefinitionAst functionDefinitionAst )
95
117
{
96
- string ? commandName = GetCommandName ( commandAst ) ;
97
- if ( string . IsNullOrEmpty ( commandName ) )
118
+ // Extent for constructors and method trigger both this and VisitFunctionMember(). Covered in the latter.
119
+ // This will not exclude nested functions as they have ScriptBlockAst as parent
120
+ if ( functionDefinitionAst . Parent is FunctionMemberAst )
98
121
{
99
122
return AstVisitAction . Continue ;
100
123
}
101
124
125
+ // We only want the function name
126
+ IScriptExtent nameExtent = VisitorUtils . GetNameExtent ( functionDefinitionAst ) ;
102
127
_references . AddReference (
103
- CommandHelpers . StripModuleQualification ( commandName , out _ ) ,
104
- commandAst . CommandElements [ 0 ] . Extent ) ;
128
+ SymbolType . Function ,
129
+ functionDefinitionAst . Name ,
130
+ nameExtent ) ;
131
+
132
+ return AstVisitAction . Continue ;
133
+ }
134
+
135
+ public override AstVisitAction VisitCommandParameter ( CommandParameterAst commandParameterAst )
136
+ {
137
+ _references . AddReference (
138
+ SymbolType . Parameter ,
139
+ commandParameterAst . Extent . Text ,
140
+ commandParameterAst . Extent ) ;
105
141
106
142
return AstVisitAction . Continue ;
107
143
}
@@ -111,10 +147,70 @@ public override AstVisitAction VisitVariableExpression(VariableExpressionAst var
111
147
// TODO: Consider tracking unscoped variable references only when they declared within
112
148
// the same function definition.
113
149
_references . AddReference (
150
+ SymbolType . Variable ,
114
151
$ "${ variableExpressionAst . VariablePath . UserPath } ",
115
- variableExpressionAst . Extent ) ;
152
+ variableExpressionAst . Extent
153
+ ) ;
154
+
155
+ return AstVisitAction . Continue ;
156
+ }
157
+
158
+ public override AstVisitAction VisitTypeDefinition ( TypeDefinitionAst typeDefinitionAst )
159
+ {
160
+ SymbolType symbolType = typeDefinitionAst . IsEnum ? SymbolType . Enum : SymbolType . Class ;
161
+
162
+ // We only want the type name. Get start-location for name
163
+ IScriptExtent nameExtent = VisitorUtils . GetNameExtent ( typeDefinitionAst ) ;
164
+ _references . AddReference ( symbolType , typeDefinitionAst . Name , nameExtent ) ;
165
+
166
+ return AstVisitAction . Continue ;
167
+ }
168
+
169
+ public override AstVisitAction VisitTypeExpression ( TypeExpressionAst typeExpressionAst )
170
+ {
171
+ _references . AddReference (
172
+ SymbolType . Type ,
173
+ typeExpressionAst . TypeName . Name ,
174
+ typeExpressionAst . Extent ) ;
116
175
117
176
return AstVisitAction . Continue ;
118
177
}
178
+
179
+ public override AstVisitAction VisitTypeConstraint ( TypeConstraintAst typeConstraintAst )
180
+ {
181
+ _references . AddReference ( SymbolType . Type , typeConstraintAst . TypeName . Name , typeConstraintAst . Extent ) ;
182
+
183
+ return AstVisitAction . Continue ;
184
+ }
185
+
186
+ public override AstVisitAction VisitFunctionMember ( FunctionMemberAst functionMemberAst )
187
+ {
188
+ SymbolType symbolType = functionMemberAst . IsConstructor
189
+ ? SymbolType . Constructor
190
+ : SymbolType . Method ;
191
+
192
+ // We only want the method/ctor name. Get start-location for name
193
+ IScriptExtent nameExtent = VisitorUtils . GetNameExtent ( functionMemberAst , true , false ) ;
194
+ _references . AddReference (
195
+ symbolType ,
196
+ VisitorUtils . GetMemberOverloadName ( functionMemberAst , true , false ) ,
197
+ nameExtent ) ;
198
+
199
+ return AstVisitAction . Continue ;
200
+ }
201
+
202
+ public override AstVisitAction VisitPropertyMember ( PropertyMemberAst propertyMemberAst )
203
+ {
204
+ // We only want the property name. Get start-location for name
205
+ IScriptExtent nameExtent = VisitorUtils . GetNameExtent ( propertyMemberAst , false ) ;
206
+ _references . AddReference (
207
+ SymbolType . Property ,
208
+ VisitorUtils . GetMemberOverloadName ( propertyMemberAst , false ) ,
209
+ nameExtent ) ;
210
+
211
+ return AstVisitAction . Continue ;
212
+ }
213
+
214
+ // TODO: What else can we implement?
119
215
}
120
216
}
0 commit comments