Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(271)

Side by Side Diff: pkg/analysis_server/lib/src/services/search/search_engine_internal.dart

Issue 2949823002: Remove unused implementation of SearchEngine and rename the driver-based implementation (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:async'; 5 import 'dart:async';
6 6
7 import 'package:analysis_server/src/services/index/index.dart';
8 import 'package:analysis_server/src/services/search/search_engine.dart'; 7 import 'package:analysis_server/src/services/search/search_engine.dart';
9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/visitor.dart';
11 import 'package:analyzer/dart/element/element.dart'; 8 import 'package:analyzer/dart/element/element.dart';
12 import 'package:analyzer/dart/element/visitor.dart'; 9 import 'package:analyzer/src/dart/analysis/driver.dart';
13 import 'package:analyzer/src/dart/element/ast_provider.dart'; 10 import 'package:analyzer/src/dart/analysis/search.dart';
14 import 'package:analyzer/src/dart/element/element.dart';
15 import 'package:analyzer/src/dart/element/member.dart';
16 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
17 import 'package:analyzer/src/generated/resolver.dart' show NamespaceBuilder;
18 import 'package:analyzer/src/generated/source.dart' show Source, SourceRange; 11 import 'package:analyzer/src/generated/source.dart' show Source, SourceRange;
19 import 'package:analyzer/src/generated/utilities_general.dart'; 12 import 'package:meta/meta.dart';
20 import 'package:analyzer/src/summary/idl.dart';
21 import 'package:analyzer_plugin/utilities/range_factory.dart';
22
23 /**
24 * The type of a function that returns the [AstProvider] managing the [file].
25 */
26 typedef AstProvider GetAstProvider(String file);
27 13
28 /** 14 /**
29 * A [SearchEngine] implementation. 15 * A [SearchEngine] implementation.
30 */ 16 */
31 class SearchEngineImpl implements SearchEngine { 17 class SearchEngineImpl implements SearchEngine {
32 final Index _index; 18 final Iterable<AnalysisDriver> _drivers;
33 final GetAstProvider _getAstProvider;
34 19
35 SearchEngineImpl(this._index, this._getAstProvider); 20 SearchEngineImpl(this._drivers);
36 21
37 @override 22 @override
38 Future<Set<ClassElement>> searchAllSubtypes(ClassElement type) async { 23 Future<Set<ClassElement>> searchAllSubtypes(ClassElement type) async {
39 List<SearchMatch> matches = <SearchMatch>[]; 24 Set<ClassElement> allSubtypes = new Set<ClassElement>();
40 await _addMatches( 25
41 matches, type, IndexRelationKind.IS_ANCESTOR_OF, MatchKind.DECLARATION); 26 Future<Null> addSubtypes(ClassElement type) async {
42 return matches.map((match) => match.element as ClassElement).toSet(); 27 List<SearchResult> directResults = await _searchDirectSubtypes(type);
28 for (SearchResult directResult in directResults) {
29 var directSubtype = directResult.enclosingElement as ClassElement;
30 if (allSubtypes.add(directSubtype)) {
31 await addSubtypes(directSubtype);
32 }
33 }
34 }
35
36 await addSubtypes(type);
37 return allSubtypes;
43 } 38 }
44 39
45 @override 40 @override
46 Future<List<SearchMatch>> searchMemberDeclarations(String name) { 41 Future<List<SearchMatch>> searchMemberDeclarations(String name) async {
47 String pattern = '^$name\$'; 42 List<SearchMatch> allDeclarations = [];
48 return _searchDefinedNames(pattern, IndexNameKind.classMember); 43 List<AnalysisDriver> drivers = _drivers.toList();
44 for (AnalysisDriver driver in drivers) {
45 List<Element> elements = await driver.search.classMembers(name);
46 allDeclarations.addAll(elements.map(SearchMatchImpl.forElement));
47 }
48 return allDeclarations;
49 } 49 }
50 50
51 @override 51 @override
52 Future<List<SearchMatch>> searchMemberReferences(String name) async { 52 Future<List<SearchMatch>> searchMemberReferences(String name) async {
53 List<Location> locations = await _index.getUnresolvedMemberReferences(name); 53 List<SearchResult> allResults = [];
54 return locations.map((location) { 54 List<AnalysisDriver> drivers = _drivers.toList();
55 return _newMatchForLocation(location, null); 55 for (AnalysisDriver driver in drivers) {
56 }).toList(); 56 List<SearchResult> results =
57 await driver.search.unresolvedMemberReferences(name);
58 allResults.addAll(results);
59 }
60 return allResults.map(SearchMatchImpl.forSearchResult).toList();
57 } 61 }
58 62
59 @override 63 @override
60 Future<List<SearchMatch>> searchReferences(Element element) { 64 Future<List<SearchMatch>> searchReferences(Element element) async {
61 ElementKind kind = element.kind; 65 List<SearchResult> allResults = [];
62 if (kind == ElementKind.CLASS || 66 List<AnalysisDriver> drivers = _drivers.toList();
63 kind == ElementKind.COMPILATION_UNIT || 67 for (AnalysisDriver driver in drivers) {
64 kind == ElementKind.CONSTRUCTOR || 68 List<SearchResult> results = await driver.search.references(element);
65 kind == ElementKind.FUNCTION_TYPE_ALIAS || 69 allResults.addAll(results);
66 kind == ElementKind.SETTER) {
67 return _searchReferences(element);
68 } else if (kind == ElementKind.GETTER) {
69 return _searchReferences_Getter(element);
70 } else if (kind == ElementKind.FIELD ||
71 kind == ElementKind.TOP_LEVEL_VARIABLE) {
72 return _searchReferences_Field(element);
73 } else if (kind == ElementKind.FUNCTION || kind == ElementKind.METHOD) {
74 if (element.enclosingElement is ExecutableElement) {
75 return _searchReferences_Local(element, (n) => n is Block);
76 }
77 return _searchReferences_Function(element);
78 } else if (kind == ElementKind.IMPORT) {
79 return _searchReferences_Import(element);
80 } else if (kind == ElementKind.LABEL ||
81 kind == ElementKind.LOCAL_VARIABLE) {
82 return _searchReferences_Local(element, (n) => n is Block);
83 } else if (kind == ElementKind.LIBRARY) {
84 return _searchReferences_Library(element);
85 } else if (kind == ElementKind.PARAMETER) {
86 return _searchReferences_Parameter(element);
87 } else if (kind == ElementKind.PREFIX) {
88 return _searchReferences_Prefix(element);
89 } else if (kind == ElementKind.TYPE_PARAMETER) {
90 return _searchReferences_Local(element, (n) => n is ClassDeclaration);
91 } 70 }
92 return new Future.value(<SearchMatch>[]); 71 return allResults.map(SearchMatchImpl.forSearchResult).toList();
93 } 72 }
94 73
95 @override 74 @override
96 Future<List<SearchMatch>> searchSubtypes(ClassElement type) async { 75 Future<List<SearchMatch>> searchSubtypes(ClassElement type) async {
97 List<SearchMatch> matches = <SearchMatch>[]; 76 List<SearchResult> results = await _searchDirectSubtypes(type);
98 await _addMatches( 77 return results.map(SearchMatchImpl.forSearchResult).toList();
99 matches, type, IndexRelationKind.IS_EXTENDED_BY, MatchKind.REFERENCE);
100 await _addMatches(
101 matches, type, IndexRelationKind.IS_MIXED_IN_BY, MatchKind.REFERENCE);
102 await _addMatches(matches, type, IndexRelationKind.IS_IMPLEMENTED_BY,
103 MatchKind.REFERENCE);
104 return matches;
105 } 78 }
106 79
107 @override 80 @override
108 Future<List<SearchMatch>> searchTopLevelDeclarations(String pattern) { 81 Future<List<SearchMatch>> searchTopLevelDeclarations(String pattern) async {
109 return _searchDefinedNames(pattern, IndexNameKind.topLevel); 82 List<SearchMatch> allDeclarations = [];
83 RegExp regExp = new RegExp(pattern);
84 List<AnalysisDriver> drivers = _drivers.toList();
85 for (AnalysisDriver driver in drivers) {
86 List<Element> elements = await driver.search.topLevelElements(regExp);
87 allDeclarations.addAll(elements.map(SearchMatchImpl.forElement));
88 }
89 return allDeclarations;
110 } 90 }
111 91
112 _addMatches(List<SearchMatch> matches, Element element, 92 Future<List<SearchResult>> _searchDirectSubtypes(ClassElement type) async {
113 IndexRelationKind relationKind, MatchKind kind) async { 93 List<SearchResult> allResults = [];
114 List<Location> locations = await _index.getRelations(element, relationKind); 94 List<AnalysisDriver> drivers = _drivers.toList();
115 for (Location location in locations) { 95 for (AnalysisDriver driver in drivers) {
116 SearchMatch match = _newMatchForLocation(location, kind); 96 List<SearchResult> results = await driver.search.subTypes(type);
117 matches.add(match); 97 allResults.addAll(results);
118 } 98 }
119 } 99 return allResults;
120
121 SearchMatch _newMatchForLocation(Location location, MatchKind kind) {
122 if (kind == null) {
123 IndexRelationKind relationKind = location.kind;
124 if (relationKind == IndexRelationKind.IS_INVOKED_BY) {
125 kind = MatchKind.INVOCATION;
126 } else if (relationKind == IndexRelationKind.IS_REFERENCED_BY) {
127 kind = MatchKind.REFERENCE;
128 } else if (relationKind == IndexRelationKind.IS_READ_BY) {
129 kind = MatchKind.READ;
130 } else if (relationKind == IndexRelationKind.IS_READ_WRITTEN_BY) {
131 kind = MatchKind.READ_WRITE;
132 } else if (relationKind == IndexRelationKind.IS_WRITTEN_BY) {
133 kind = MatchKind.WRITE;
134 } else {
135 throw new ArgumentError('Unsupported relation kind $relationKind');
136 }
137 }
138 return new SearchMatchImpl(
139 location.context,
140 location.libraryUri,
141 location.unitUri,
142 kind,
143 new SourceRange(location.offset, location.length),
144 location.isResolved,
145 location.isQualified);
146 }
147
148 Future<List<SearchMatch>> _searchDefinedNames(
149 String pattern, IndexNameKind nameKind) async {
150 RegExp regExp = new RegExp(pattern);
151 List<Location> locations = await _index.getDefinedNames(regExp, nameKind);
152 return locations.map((location) {
153 return _newMatchForLocation(location, MatchKind.DECLARATION);
154 }).toList();
155 }
156
157 Future<List<SearchMatch>> _searchReferences(Element element) async {
158 List<SearchMatch> matches = <SearchMatch>[];
159 await _addMatches(matches, element, IndexRelationKind.IS_REFERENCED_BY,
160 MatchKind.REFERENCE);
161 return matches;
162 }
163
164 Future<List<SearchMatch>> _searchReferences_Field(
165 PropertyInducingElement field) async {
166 List<SearchMatch> matches = <SearchMatch>[];
167 PropertyAccessorElement getter = field.getter;
168 PropertyAccessorElement setter = field.setter;
169 // field itself
170 if (!field.isSynthetic) {
171 await _addMatches(
172 matches, field, IndexRelationKind.IS_WRITTEN_BY, MatchKind.WRITE);
173 await _addMatches(matches, field, IndexRelationKind.IS_REFERENCED_BY,
174 MatchKind.REFERENCE);
175 }
176 // getter
177 if (getter != null) {
178 await _addMatches(
179 matches, getter, IndexRelationKind.IS_REFERENCED_BY, MatchKind.READ);
180 await _addMatches(matches, getter, IndexRelationKind.IS_INVOKED_BY,
181 MatchKind.INVOCATION);
182 }
183 // setter
184 if (setter != null) {
185 await _addMatches(
186 matches, setter, IndexRelationKind.IS_REFERENCED_BY, MatchKind.WRITE);
187 }
188 // done
189 return matches;
190 }
191
192 Future<List<SearchMatch>> _searchReferences_Function(Element element) async {
193 if (element is Member) {
194 element = (element as Member).baseElement;
195 }
196 List<SearchMatch> matches = <SearchMatch>[];
197 await _addMatches(matches, element, IndexRelationKind.IS_REFERENCED_BY,
198 MatchKind.REFERENCE);
199 await _addMatches(matches, element, IndexRelationKind.IS_INVOKED_BY,
200 MatchKind.INVOCATION);
201 return matches;
202 }
203
204 Future<List<SearchMatch>> _searchReferences_Getter(
205 PropertyAccessorElement getter) async {
206 List<SearchMatch> matches = <SearchMatch>[];
207 await _addMatches(matches, getter, IndexRelationKind.IS_REFERENCED_BY,
208 MatchKind.REFERENCE);
209 await _addMatches(
210 matches, getter, IndexRelationKind.IS_INVOKED_BY, MatchKind.INVOCATION);
211 return matches;
212 }
213
214 Future<List<SearchMatch>> _searchReferences_Import(
215 ImportElement element) async {
216 List<SearchMatch> matches = <SearchMatch>[];
217 LibraryElement libraryElement = element.library;
218 Source librarySource = libraryElement.source;
219 AnalysisContext context = libraryElement.context;
220 for (CompilationUnitElement unitElement in libraryElement.units) {
221 Source unitSource = unitElement.source;
222 CompilationUnit unit =
223 context.resolveCompilationUnit2(unitSource, librarySource);
224 _ImportElementReferencesVisitor visitor =
225 new _ImportElementReferencesVisitor(
226 element, unitSource.uri.toString());
227 unit.accept(visitor);
228 matches.addAll(visitor.matches);
229 }
230 return matches;
231 }
232
233 Future<List<SearchMatch>> _searchReferences_Library(Element element) async {
234 List<SearchMatch> matches = <SearchMatch>[];
235 LibraryElement libraryElement = element.library;
236 Source librarySource = libraryElement.source;
237 AnalysisContext context = libraryElement.context;
238 for (CompilationUnitElement unitElement in libraryElement.parts) {
239 Source unitSource = unitElement.source;
240 CompilationUnit unit =
241 context.resolveCompilationUnit2(unitSource, librarySource);
242 for (Directive directive in unit.directives) {
243 if (directive is PartOfDirective &&
244 directive.element == libraryElement) {
245 matches.add(new SearchMatchImpl(
246 context,
247 librarySource.uri.toString(),
248 unitSource.uri.toString(),
249 MatchKind.REFERENCE,
250 range.node(directive.libraryName),
251 true,
252 false));
253 }
254 }
255 }
256 return matches;
257 }
258
259 Future<List<SearchMatch>> _searchReferences_Local(
260 Element element, bool isRootNode(AstNode n)) async {
261 _LocalReferencesVisitor visitor = new _LocalReferencesVisitor(element);
262 AstProvider astProvider = _getAstProvider(element.source.fullName);
263 AstNode name = await astProvider.getResolvedNameForElement(element);
264 AstNode enclosingNode = name?.getAncestor(isRootNode);
265 enclosingNode?.accept(visitor);
266 return visitor.matches;
267 }
268
269 Future<List<SearchMatch>> _searchReferences_Parameter(
270 ParameterElement parameter) async {
271 List<SearchMatch> matches = <SearchMatch>[];
272 matches.addAll(await _searchReferences(parameter));
273 matches.addAll(await _searchReferences_Local(parameter, (AstNode node) {
274 AstNode parent = node.parent;
275 return parent is ClassDeclaration || parent is CompilationUnit;
276 }));
277 return matches;
278 }
279
280 Future<List<SearchMatch>> _searchReferences_Prefix(
281 PrefixElement element) async {
282 List<SearchMatch> matches = <SearchMatch>[];
283 LibraryElement libraryElement = element.library;
284 Source librarySource = libraryElement.source;
285 AnalysisContext context = libraryElement.context;
286 for (CompilationUnitElement unitElement in libraryElement.units) {
287 Source unitSource = unitElement.source;
288 CompilationUnit unit =
289 context.resolveCompilationUnit2(unitSource, librarySource);
290 _LocalReferencesVisitor visitor =
291 new _LocalReferencesVisitor(element, unitSource.uri.toString());
292 unit.accept(visitor);
293 matches.addAll(visitor.matches);
294 }
295 return matches;
296 } 100 }
297 } 101 }
298 102
299 /** 103 @visibleForTesting
300 * Implementation of [SearchMatch].
301 */
302 class SearchMatchImpl implements SearchMatch { 104 class SearchMatchImpl implements SearchMatch {
303 /** 105 @override
304 * The [AnalysisContext] containing the match. 106 final String file;
305 */
306 final AnalysisContext _context;
307 107
308 /** 108 @override
309 * The URI of the source of the library containing the match. 109 final Source librarySource;
310 */
311 final String libraryUri;
312 110
313 /** 111 @override
314 * The URI of the source of the unit containing the match. 112 final Source unitSource;
315 */
316 final String unitUri;
317 113
318 /** 114 @override
319 * The kind of the match. 115 final LibraryElement libraryElement;
320 */ 116
117 @override
118 final Element element;
119
120 @override
121 final bool isResolved;
122
123 @override
124 final bool isQualified;
125
126 @override
321 final MatchKind kind; 127 final MatchKind kind;
322 128
323 /** 129 @override
324 * The source range that was matched.
325 */
326 final SourceRange sourceRange; 130 final SourceRange sourceRange;
327 131
328 /** 132 SearchMatchImpl(
329 * Is `true` if the match is a resolved reference to some [Element]. 133 this.file,
330 */ 134 this.librarySource,
331 final bool isResolved; 135 this.unitSource,
332 136 this.libraryElement,
333 /** 137 this.element,
334 * Is `true` if field or method access is done using qualifier. 138 this.isResolved,
335 */ 139 this.isQualified,
336 final bool isQualified; 140 this.kind,
337 141 this.sourceRange);
338 Source _librarySource;
339 Source _unitSource;
340 LibraryElement _libraryElement;
341 Element _element;
342
343 SearchMatchImpl(this._context, this.libraryUri, this.unitUri, this.kind,
344 this.sourceRange, this.isResolved, this.isQualified);
345
346 /**
347 * Return the [Element] containing the match. Can return `null` if the unit
348 * does not exist, or its element was invalidated, or the element cannot be
349 * found, etc.
350 */
351 Element get element {
352 if (_element == null) {
353 CompilationUnitElement unitElement =
354 _context.getCompilationUnitElement(unitSource, librarySource);
355 if (unitElement != null) {
356 _ContainingElementFinder finder =
357 new _ContainingElementFinder(sourceRange.offset);
358 unitElement.accept(finder);
359 _element = finder.containingElement;
360 }
361 }
362 return _element;
363 }
364
365 /**
366 * The absolute path of the file containing the match.
367 */
368 String get file => unitSource.fullName;
369
370 @override
371 int get hashCode {
372 return JenkinsSmiHash.hash4(libraryUri.hashCode, unitUri.hashCode,
373 kind.hashCode, sourceRange.hashCode);
374 }
375
376 /**
377 * Return the [LibraryElement] for the [libraryUri] in the [context].
378 */
379 LibraryElement get libraryElement {
380 _libraryElement ??= _context.getLibraryElement(librarySource);
381 return _libraryElement;
382 }
383
384 /**
385 * The library [Source] of the reference.
386 */
387 Source get librarySource {
388 _librarySource ??= _context.sourceFactory.forUri(libraryUri);
389 return _librarySource;
390 }
391
392 /**
393 * The unit [Source] of the reference.
394 */
395 Source get unitSource {
396 _unitSource ??= _context.sourceFactory.forUri(unitUri);
397 return _unitSource;
398 }
399
400 @override
401 bool operator ==(Object object) {
402 if (identical(object, this)) {
403 return true;
404 }
405 if (object is SearchMatchImpl) {
406 return kind == object.kind &&
407 libraryUri == object.libraryUri &&
408 unitUri == object.unitUri &&
409 isResolved == object.isResolved &&
410 isQualified == object.isQualified &&
411 sourceRange == object.sourceRange;
412 }
413 return false;
414 }
415 142
416 @override 143 @override
417 String toString() { 144 String toString() {
418 StringBuffer buffer = new StringBuffer(); 145 StringBuffer buffer = new StringBuffer();
419 buffer.write("SearchMatch(kind="); 146 buffer.write("SearchMatch(kind=");
420 buffer.write(kind); 147 buffer.write(kind);
421 buffer.write(", libraryUri="); 148 buffer.write(", libraryUri=");
422 buffer.write(libraryUri); 149 buffer.write(librarySource.uri);
423 buffer.write(", unitUri="); 150 buffer.write(", unitUri=");
424 buffer.write(unitUri); 151 buffer.write(unitSource.uri);
425 buffer.write(", range="); 152 buffer.write(", range=");
426 buffer.write(sourceRange); 153 buffer.write(sourceRange);
427 buffer.write(", isResolved="); 154 buffer.write(", isResolved=");
428 buffer.write(isResolved); 155 buffer.write(isResolved);
429 buffer.write(", isQualified="); 156 buffer.write(", isQualified=");
430 buffer.write(isQualified); 157 buffer.write(isQualified);
431 buffer.write(")"); 158 buffer.write(")");
432 return buffer.toString(); 159 return buffer.toString();
433 } 160 }
434 161
435 /** 162 static SearchMatchImpl forElement(Element element) {
436 * Return elements of [matches] which has not-null elements. 163 return new SearchMatchImpl(
437 * 164 element.source.fullName,
438 * When [SearchMatch.element] is not `null` we cache its value, so it cannot 165 element.librarySource,
439 * become `null` later. 166 element.source,
440 */ 167 element.library,
441 static List<SearchMatch> withNotNullElement(List<SearchMatch> matches) { 168 element,
442 return matches.where((match) => match.element != null).toList(); 169 true,
170 true,
171 MatchKind.DECLARATION,
172 new SourceRange(element.nameOffset, element.nameLength));
173 }
174
175 static SearchMatchImpl forSearchResult(SearchResult result) {
176 Element enclosingElement = result.enclosingElement;
177 return new SearchMatchImpl(
178 enclosingElement.source.fullName,
179 enclosingElement.librarySource,
180 enclosingElement.source,
181 enclosingElement.library,
182 enclosingElement,
183 result.isResolved,
184 result.isQualified,
185 toMatchKind(result.kind),
186 new SourceRange(result.offset, result.length));
187 }
188
189 static MatchKind toMatchKind(SearchResultKind kind) {
190 if (kind == SearchResultKind.READ) {
191 return MatchKind.READ;
192 }
193 if (kind == SearchResultKind.READ_WRITE) {
194 return MatchKind.READ_WRITE;
195 }
196 if (kind == SearchResultKind.WRITE) {
197 return MatchKind.WRITE;
198 }
199 if (kind == SearchResultKind.INVOCATION) {
200 return MatchKind.INVOCATION;
201 }
202 return MatchKind.REFERENCE;
443 } 203 }
444 } 204 }
445
446 /**
447 * A visitor that finds the deep-most [Element] that contains the [offset].
448 */
449 class _ContainingElementFinder extends GeneralizingElementVisitor {
450 final int offset;
451 Element containingElement;
452
453 _ContainingElementFinder(this.offset);
454
455 visitElement(Element element) {
456 if (element is ElementImpl) {
457 if (element.codeOffset != null &&
458 element.codeOffset <= offset &&
459 offset <= element.codeOffset + element.codeLength) {
460 containingElement = element;
461 super.visitElement(element);
462 }
463 }
464 }
465 }
466
467 /**
468 * Visitor that adds [SearchMatch]es for [importElement], both with an explicit
469 * prefix or an implicit one.
470 */
471 class _ImportElementReferencesVisitor extends RecursiveAstVisitor {
472 final List<SearchMatch> matches = <SearchMatch>[];
473
474 final ImportElement importElement;
475 final AnalysisContext context;
476 final String libraryUri;
477 final String unitUri;
478 Set<Element> importedElements;
479
480 _ImportElementReferencesVisitor(ImportElement element, this.unitUri)
481 : importElement = element,
482 context = element.context,
483 libraryUri = element.library.source.uri.toString() {
484 importedElements = new NamespaceBuilder()
485 .createImportNamespaceForDirective(element)
486 .definedNames
487 .values
488 .toSet();
489 }
490
491 @override
492 visitExportDirective(ExportDirective node) {}
493
494 @override
495 visitImportDirective(ImportDirective node) {}
496
497 @override
498 visitSimpleIdentifier(SimpleIdentifier node) {
499 if (node.inDeclarationContext()) {
500 return;
501 }
502 if (importElement.prefix != null) {
503 if (node.staticElement == importElement.prefix) {
504 AstNode parent = node.parent;
505 if (parent is PrefixedIdentifier && parent.prefix == node) {
506 if (importedElements.contains(parent.staticElement)) {
507 _addMatchForPrefix(node, parent.identifier);
508 }
509 }
510 if (parent is MethodInvocation && parent.target == node) {
511 if (importedElements.contains(parent.methodName.staticElement)) {
512 _addMatchForPrefix(node, parent.methodName);
513 }
514 }
515 }
516 } else {
517 if (importedElements.contains(node.staticElement)) {
518 _addMatchForRange(range.startLength(node, 0));
519 }
520 }
521 }
522
523 void _addMatchForPrefix(SimpleIdentifier prefixNode, AstNode nextNode) {
524 _addMatchForRange(range.startStart(prefixNode, nextNode));
525 }
526
527 void _addMatchForRange(SourceRange range) {
528 matches.add(new SearchMatchImpl(
529 context, libraryUri, unitUri, MatchKind.REFERENCE, range, true, false));
530 }
531 }
532
533 /**
534 * Visitor that adds [SearchMatch]es for local elements of a block, method,
535 * class or a library - labels, local functions, local variables and parameters,
536 * type parameters, import prefixes.
537 */
538 class _LocalReferencesVisitor extends RecursiveAstVisitor {
539 final List<SearchMatch> matches = <SearchMatch>[];
540
541 final Element element;
542 final AnalysisContext context;
543 final String libraryUri;
544 final String unitUri;
545
546 _LocalReferencesVisitor(Element element, [String unitUri])
547 : element = element,
548 context = element.context,
549 libraryUri = element.library.source.uri.toString(),
550 unitUri = unitUri ?? element.source.uri.toString();
551
552 @override
553 visitSimpleIdentifier(SimpleIdentifier node) {
554 if (node.inDeclarationContext()) {
555 return;
556 }
557 if (node.bestElement == element) {
558 AstNode parent = node.parent;
559 MatchKind kind = MatchKind.REFERENCE;
560 if (element is FunctionElement) {
561 if (parent is MethodInvocation && parent.methodName == node) {
562 kind = MatchKind.INVOCATION;
563 }
564 } else if (element is VariableElement) {
565 bool isGet = node.inGetterContext();
566 bool isSet = node.inSetterContext();
567 if (isGet && isSet) {
568 kind = MatchKind.READ_WRITE;
569 } else if (isGet) {
570 if (parent is MethodInvocation && parent.methodName == node) {
571 kind = MatchKind.INVOCATION;
572 } else {
573 kind = MatchKind.READ;
574 }
575 } else if (isSet) {
576 kind = MatchKind.WRITE;
577 }
578 }
579 _addMatch(node, kind);
580 }
581 }
582
583 void _addMatch(AstNode node, MatchKind kind) {
584 bool isQualified = node.parent is Label;
585 matches.add(new SearchMatchImpl(context, libraryUri, unitUri, kind,
586 range.node(node), true, isQualified));
587 }
588 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698