@@ -7,23 +7,25 @@ import 'package:analysis_server/src/services/search/search_engine.dart';
7
7
import 'package:analyzer/dart/analysis/results.dart' ;
8
8
import 'package:analyzer/dart/ast/ast.dart' ;
9
9
import 'package:analyzer/dart/ast/visitor.dart' ;
10
- import 'package:analyzer/dart/element/element .dart' ;
10
+ import 'package:analyzer/dart/element/element2 .dart' ;
11
11
import 'package:analyzer/source/source_range.dart' ;
12
12
import 'package:analyzer/src/dart/ast/element_locator.dart' ;
13
13
import 'package:analyzer/src/dart/ast/utilities.dart' ;
14
14
import 'package:analyzer/src/dart/element/element.dart' ;
15
- import 'package:analyzer/src/utilities/extensions/element.dart' ;
16
15
17
16
/// Returns the container for [element] that should be used in Call Hierarchy.
18
17
///
19
18
/// Returns `null` if none of [elements] are valid containers.
20
19
///
21
20
/// This is used to construct (and group calls by) a [CallHierarchyItem] that
22
21
/// contains calls and also locate their containers for additional labelling.
23
- Element ? _getContainer (Element element) {
22
+ Element2 ? _getContainer (Element2 element) {
23
+ // TODO(brianwilkerson): This used to use the compilation unit as a container
24
+ // which allowed users to see the path to the containing file, but that's
25
+ // been lost. Consider trying to restore that behavior.
24
26
const containerKinds = {
25
27
ElementKind .CLASS ,
26
- ElementKind .COMPILATION_UNIT ,
28
+ ElementKind .LIBRARY ,
27
29
ElementKind .CONSTRUCTOR ,
28
30
ElementKind .ENUM ,
29
31
ElementKind .EXTENSION ,
@@ -34,29 +36,27 @@ Element? _getContainer(Element element) {
34
36
ElementKind .MIXIN ,
35
37
ElementKind .SETTER ,
36
38
};
37
- return element.thisOrAncestorMatching (
39
+ return element.thisOrAncestorMatching2 (
38
40
(ancestor) => containerKinds.contains (ancestor.kind),
39
41
);
40
42
}
41
43
42
44
/// Gets a user-friendly display name for [element] .
43
- String _getDisplayName (Element element) {
44
- return element is CompilationUnitElement
45
- ? element.source.shortName
46
- : element is PropertyAccessorElement
47
- ? element.isGetter
48
- ? 'get ${element .displayName }'
49
- : 'set ${element .displayName }'
50
- : element.displayName;
45
+ String _getDisplayName (Element2 element) {
46
+ return switch (element) {
47
+ LibraryElement2 () => element.firstFragment.source.shortName,
48
+ GetterElement () => 'get ${element .displayName }' ,
49
+ SetterElement () => 'set ${element .displayName }' ,
50
+ _ => element.displayName,
51
+ };
51
52
}
52
53
53
54
/// A [CallHierarchyItem] and a set of ranges that call to or from it.
54
55
class CallHierarchyCalls {
55
56
final CallHierarchyItem item;
56
- final List <SourceRange > ranges;
57
+ final List <SourceRange > ranges = [] ;
57
58
58
- CallHierarchyCalls (this .item, [List <SourceRange >? ranges])
59
- : ranges = ranges ?? [];
59
+ CallHierarchyCalls (this .item);
60
60
}
61
61
62
62
/// An item that can appear in a Call Hierarchy.
@@ -102,39 +102,53 @@ class CallHierarchyItem {
102
102
required this .codeRange,
103
103
});
104
104
105
- CallHierarchyItem .forElement (Element element)
105
+ CallHierarchyItem .forElement (Element2 element)
106
106
: displayName = _getDisplayName (element),
107
107
nameRange = _nameRangeForElement (element),
108
108
codeRange = _codeRangeForElement (element),
109
- file = element.source ! .fullName,
109
+ file = element.firstFragment.libraryFragment ! .source .fullName,
110
110
kind = CallHierarchyKind .forElement (element) {
111
- var enclosingElement = element.enclosingElement3;
111
+ var enclosingElement =
112
+ element.enclosingElement2 ??
113
+ element.firstFragment.enclosingFragment? .element;
112
114
var container =
113
115
enclosingElement != null ? _getContainer (enclosingElement) : null ;
114
116
containerName = container != null ? _getDisplayName (container) : null ;
115
117
}
116
118
117
119
/// Returns the [SourceRange] of the code for [element] .
118
- static SourceRange _codeRangeForElement (Element element) {
120
+ static SourceRange _codeRangeForElement (Element2 element) {
119
121
// For synthetic items (like implicit constructors), use the nonSynthetic
120
122
// element for the location.
121
- var elementImpl = element.nonSynthetic as ElementImpl ;
123
+ element = _nonSynthetic (element);
124
+ var fragment = element.firstFragment as ElementImpl ;
122
125
123
126
// Non-synthetic elements should always have code locations.
124
- return SourceRange (elementImpl.codeOffset! , elementImpl.codeLength! );
127
+ // TODO(brianwilkerson): Figure out why that's no longer true and possibly
128
+ // remove the conditionals below.
129
+ return SourceRange (fragment.codeOffset ?? 0 , fragment.codeLength ?? 0 );
125
130
}
126
131
127
132
/// Returns the [SourceRange] of the name for [element] .
128
- static SourceRange _nameRangeForElement (Element element) {
133
+ static SourceRange _nameRangeForElement (Element2 element) {
129
134
// For synthetic items (like implicit constructors), use the nonSynthetic
130
135
// element for the location.
131
- element = element.nonSynthetic;
136
+ element = _nonSynthetic (element);
137
+ var fragment = element.firstFragment as ElementImpl ;
132
138
133
139
// Compilation units will return -1 for nameOffset which is not valid, so
134
- //use 0:0.
135
- return element .nameOffset == - 1
140
+ // use 0:0.
141
+ return fragment .nameOffset == - 1
136
142
? SourceRange (0 , 0 )
137
- : SourceRange (element.nameOffset, element.nameLength);
143
+ : SourceRange (fragment.nameOffset, fragment.nameLength);
144
+ }
145
+
146
+ static Element2 _nonSynthetic (Element2 element) {
147
+ element = element.nonSynthetic2;
148
+ if (element.isSynthetic) {
149
+ element = element.enclosingElement2 ?? element;
150
+ }
151
+ return element;
138
152
}
139
153
}
140
154
@@ -153,7 +167,7 @@ enum CallHierarchyKind {
153
167
154
168
static const _elementMapping = {
155
169
ElementKind .CLASS : class_,
156
- ElementKind .COMPILATION_UNIT : file,
170
+ ElementKind .LIBRARY : file,
157
171
ElementKind .CONSTRUCTOR : constructor,
158
172
ElementKind .EXTENSION : extension ,
159
173
ElementKind .FUNCTION : function,
@@ -163,7 +177,7 @@ enum CallHierarchyKind {
163
177
ElementKind .SETTER : property,
164
178
};
165
179
166
- static CallHierarchyKind forElement (Element element) =>
180
+ static CallHierarchyKind forElement (Element2 element) =>
167
181
_elementMapping[element.kind] ?? unknown;
168
182
}
169
183
@@ -210,28 +224,28 @@ class DartCallHierarchyComputer {
210
224
// implicit constructors do not have.
211
225
// Here, we map them back to the synthetic constructor element.
212
226
var isImplicitConstructor =
213
- element is InterfaceElement &&
227
+ element is InterfaceElement2 &&
214
228
target.kind == CallHierarchyKind .constructor;
215
229
if (isImplicitConstructor) {
216
- element = element.unnamedConstructor ;
230
+ element = element.unnamedConstructor2 ;
217
231
}
218
232
219
233
// We only find incoming calls to executable elements.
220
- if (element is ! ExecutableElement ) {
234
+ if (element is ! ExecutableElement2 ) {
221
235
return [];
222
236
}
223
237
224
238
var computer = ElementReferencesComputer (searchEngine);
225
- var references = await computer.compute (element.asElement2 , false );
239
+ var references = await computer.compute (element, false );
226
240
227
241
// Group results by their container, since we only want to return a single
228
242
// entry for a body, with a set of ranges within.
229
- var resultsByContainer = < Element , CallHierarchyCalls > {};
243
+ var resultsByContainer = < Element2 , CallHierarchyCalls > {};
230
244
// We may need to fetch parsed results for the other files, reuse them
231
245
// across calls.
232
246
var parsedUnits = < String , SomeParsedUnitResult ? > {};
233
247
for (var reference in references) {
234
- var container = _getContainer (reference.element );
248
+ var container = _getContainer (reference.element2 );
235
249
if (container == null ) {
236
250
continue ;
237
251
}
@@ -279,7 +293,7 @@ class DartCallHierarchyComputer {
279
293
280
294
// Group results by their target, since we only want to return a single
281
295
// entry for each target, with a set of ranges that call it.
282
- var resultsByTarget = < Element , CallHierarchyCalls > {};
296
+ var resultsByTarget = < Element2 , CallHierarchyCalls > {};
283
297
for (var referenceNode in referenceNodes) {
284
298
var target = _getElementOfNode (referenceNode);
285
299
if (target == null ) {
@@ -309,7 +323,7 @@ class DartCallHierarchyComputer {
309
323
var element = _getElementOfNode (node);
310
324
311
325
// We only return targets that are executable elements.
312
- return element is ExecutableElement
326
+ return element is ExecutableElement2
313
327
? CallHierarchyItem .forElement (element)
314
328
: null ;
315
329
}
@@ -348,7 +362,7 @@ class DartCallHierarchyComputer {
348
362
/// Return the [Element] of the given [node] , or `null` if [node] is `null` ,
349
363
/// does not have an element, or the element is not a valid target for call
350
364
/// hierarchy.
351
- Element ? _getElementOfNode (AstNode ? node) {
365
+ Element2 ? _getElementOfNode (AstNode ? node) {
352
366
if (node == null ) {
353
367
return null ;
354
368
}
@@ -357,18 +371,18 @@ class DartCallHierarchyComputer {
357
371
// ElementLocator returns the class for default constructor calls and null
358
372
// for constructor names.
359
373
if (node is NamedType && parent is ConstructorName ) {
360
- return parent.staticElement ;
374
+ return parent.element ;
361
375
} else if (node is ConstructorName ) {
362
- return node.staticElement ;
376
+ return node.element ;
363
377
} else if (node is PropertyAccess ) {
364
378
node = node.propertyName;
365
379
}
366
380
367
- var element = ElementLocator .locate (node);
381
+ var element = ElementLocator .locate2 (node);
368
382
369
383
// Don't consider synthetic getter/setter for a field to be executable
370
384
// since they don't contain any executable code.
371
- if (element is PropertyAccessorElement && element.isSynthetic) {
385
+ if (element is PropertyAccessorElement2 && element.isSynthetic) {
372
386
return null ;
373
387
}
374
388
@@ -380,7 +394,7 @@ class DartCallHierarchyComputer {
380
394
/// This is used to ensure calls are only returned for the expected target
381
395
/// if source code has changed since the earlier request that provided
382
396
/// [target] to the client.
383
- bool _isMatchingElement (Element element, CallHierarchyItem target) {
397
+ bool _isMatchingElement (Element2 element, CallHierarchyItem target) {
384
398
return _getDisplayName (element) == target.displayName;
385
399
}
386
400
@@ -494,7 +508,10 @@ class _OutboundCallVisitor extends RecursiveAstVisitor<void> {
494
508
495
509
@override
496
510
void visitSimpleIdentifier (SimpleIdentifier node) {
497
- if (node.staticElement is FunctionElement && ! node.inDeclarationContext ()) {
511
+ var element = node.element;
512
+ if ((element is LocalFunctionElement ||
513
+ element is TopLevelFunctionElement ) &&
514
+ ! node.inDeclarationContext ()) {
498
515
collect (node);
499
516
}
500
517
super .visitSimpleIdentifier (node);
0 commit comments