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

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

Issue 1801883002: Remove old index and search implementations. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 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) 2014, 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 library services.index;
6
7 import 'dart:async'; 5 import 'dart:async';
8 6
9 import 'package:analysis_server/src/provisional/index/index_core.dart'; 7 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analysis_server/src/services/index/indexable_element.dart';
11 import 'package:analyzer/dart/element/element.dart'; 8 import 'package:analyzer/dart/element/element.dart';
12 import 'package:analyzer/src/generated/engine.dart'; 9 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
13 10 import 'package:analyzer/src/generated/source.dart';
14 /** 11 import 'package:analyzer/src/summary/format.dart';
15 * A filter for [Element] names. 12 import 'package:analyzer/src/summary/idl.dart';
16 */ 13 import 'package:analyzer/src/summary/index_unit.dart';
17 typedef bool ElementNameFilter(String name); 14 import 'package:collection/collection.dart';
18 15
19 /** 16 /**
20 * The interface [Index] defines the behavior of objects that maintain an index 17 * Return a new [Index] instance that keeps information in memory.
21 * storing relations between indexable objects. 18 */
19 Index createMemoryIndex() {
20 return new Index._();
21 }
22
23 /**
24 * Return the index of the first occurrence of the [value] in the [sortedList],
25 * or `-1` if the [value] is not in the list.
26 */
27 int _findFirstOccurrence(List<int> sortedList, int value) {
28 // Find an occurrence.
29 int i = binarySearch(sortedList, value);
30 if (i == -1) {
31 return -1;
32 }
33 // Find the first occurrence.
34 while (i > 0 && sortedList[i - 1] == value) {
35 i--;
36 }
37 return i;
38 }
39
40 /**
41 * Interface for storing and requesting relations.
42 */
43 class Index {
44 final Map<AnalysisContext, _ContextIndex> _contextIndexMap =
45 <AnalysisContext, _ContextIndex>{};
46
47 Index._();
48
49 /**
50 * Complete with a list of locations where elements of the given [kind] with
51 * names satisfying the given [regExp] are defined.
52 */
53 Future<List<Location>> getDefinedNames(RegExp regExp, IndexNameKind kind) {
54 return _mergeLocations((_ContextIndex index) {
55 return index.getDefinedNames(regExp, kind);
56 });
57 }
58
59 /**
60 * Complete with a list of locations where the given [element] has relation
61 * of the given [kind].
62 */
63 Future<List<Location>> getRelations(Element element, IndexRelationKind kind) {
64 return _mergeLocations((_ContextIndex index) {
65 return index.getRelations(element, kind);
66 });
67 }
68
69 /**
70 * Complete with a list of locations where a class members with the given
71 * [name] is referenced with a qualifier, but is not resolved.
72 */
73 Future<List<Location>> getUnresolvedMemberReferences(String name) {
74 return _mergeLocations((_ContextIndex index) {
75 return index.getUnresolvedMemberReferences(name);
76 });
77 }
78
79 /**
80 * Index the given fully resolved [unit].
81 */
82 void indexUnit(CompilationUnit unit) {
83 if (unit == null || unit.element == null) {
84 return;
85 }
86 AnalysisContext context = unit.element.context;
87 _getContextIndex(context).indexUnit(unit);
88 }
89
90 /**
91 * Remove all index information for the given [context].
92 */
93 void removeContext(AnalysisContext context) {
94 _contextIndexMap.remove(context);
95 }
96
97 /**
98 * Remove index information about the unit in the given [context].
99 */
100 void removeUnit(
101 AnalysisContext context, Source librarySource, Source unitSource) {
102 _contextIndexMap[context]?.removeUnit(librarySource, unitSource);
103 }
104
105 /**
106 * Notify the index that the client is going to stop using it.
107 */
108 void stop() {}
109
110 /**
111 * Return the [_ContextIndex] instance for the given [context].
112 */
113 _ContextIndex _getContextIndex(AnalysisContext context) {
114 return _contextIndexMap.putIfAbsent(context, () {
115 return new _ContextIndex(context);
116 });
117 }
118
119 /**
120 * Complete with a list of all results returned by the [callback] for every
121 * context specific index.
122 */
123 Future<List<Location>> _mergeLocations(
124 Future<List<Location>> callback(_ContextIndex index)) async {
125 List<Location> locations = <Location>[];
126 for (_ContextIndex index in _contextIndexMap.values) {
127 List<Location> contextLocations = await callback(index);
128 locations.addAll(contextLocations);
129 }
130 return locations;
131 }
132 }
133
134 /**
135 * Information about location of a single relation in the index.
22 * 136 *
23 * Any modification operations are executed before any read operation. 137 * The location is expressed as a library specific unit containing the index
24 * There is no guarantee about the order in which the [Future]s for read 138 * relation, offset within this [Source] and length.
25 * operations will complete. 139 *
26 */ 140 * Clients may not extend, implement or mix-in this class.
27 abstract class Index implements IndexStore { 141 */
28 /** 142 class Location {
29 * Set the index contributors used by this index to the given list of 143 /**
30 * [contributors]. 144 * The [AnalysisContext] containing this location.
31 */ 145 */
32 void set contributors(List<IndexContributor> contributors); 146 final AnalysisContext context;
33 147
34 /** 148 /**
35 * Answers index statistics. 149 * The URI of the source of the library containing this location.
36 */ 150 */
37 String get statistics; 151 final String libraryUri;
38 152
39 /** 153 /**
40 * Returns top-level [Element]s whose names satisfy to [nameFilter]. 154 * The URI of the source of the unit containing this location.
41 */ 155 */
42 List<Element> getTopLevelDeclarations(ElementNameFilter nameFilter); 156 final String unitUri;
43 157
44 /** 158 /**
45 * Processes the given [object] in order to record the relationships. 159 * The kind of usage at this location.
46 * 160 */
47 * [context] - the [AnalysisContext] in which the [object] being indexed. 161 final IndexRelationKind kind;
48 * [object] - the object being indexed. 162
49 */ 163 /**
50 void index(AnalysisContext context, Object object); 164 * The offset of this location within the [unitUri].
51 165 */
52 /** 166 final int offset;
53 * Starts the index. 167
54 * Should be called before any other method. 168 /**
55 */ 169 * The length of this location.
56 void run(); 170 */
57 171 final int length;
58 /** 172
59 * Stops the index. 173 /**
60 * After calling this method operations may not be executed. 174 * Is `true` if this location is qualified.
61 */ 175 */
62 void stop(); 176 final bool isQualified;
63 } 177
64 178 /**
65 /** 179 * Is `true` if this location is resolved.
66 * An [Element] which is used to index references to the name without specifying 180 */
67 * a concrete kind of this name - field, method or something else. 181 final bool isResolved;
68 */ 182
69 class IndexableName implements IndexableObject { 183 Location(this.context, this.libraryUri, this.unitUri, this.kind, this.offset,
70 /** 184 this.length, this.isQualified, this.isResolved);
71 * The name to be indexed.
72 */
73 final String name;
74
75 /**
76 * Initialize a newly created indexable name to represent the given [name].
77 */
78 IndexableName(this.name);
79 185
80 @override 186 @override
81 String get filePath => null; 187 String toString() => 'Location{librarySourceUri: $libraryUri, '
82 188 'unitSourceUri: $unitUri, offset: $offset, length: $length, '
83 @override 189 'isQualified: $isQualified}, isResolved: $isResolved}';
84 IndexableNameKind get kind => IndexableNameKind.INSTANCE; 190 }
85 191
86 @override 192 /**
87 int get offset { 193 * Opaque identifier of a [PackageIndex].
194 */
195 abstract class PackageIndexId {}
196
197 /**
198 * Storage of [PackageIndex] objects.
199 */
200 abstract class PackageIndexStore {
201 /**
202 * Complete with identifiers of all [PackageIndex] objects.
203 */
204 Future<Iterable<PackageIndexId>> getIds();
205
206 /**
207 * Complete with the [PackageIndex] with the given [id].
208 */
209 Future<PackageIndex> getIndex(PackageIndexId id);
210
211 /**
212 * Put the given [indexBuilder] into the store.
213 */
214 void putIndex(String unitLibraryUri, String unitUnitUri,
215 PackageIndexBuilder indexBuilder);
216 }
217
218 /**
219 * The [AnalysisContext] specific index.
220 */
221 class _ContextIndex {
222 final AnalysisContext context;
223 final Map<String, PackageIndex> indexMap = <String, PackageIndex>{};
224
225 _ContextIndex(this.context);
226
227 /**
228 * Complete with a list of locations where elements of the given [kind] with
229 * names satisfying the given [regExp] are defined.
230 */
231 Future<List<Location>> getDefinedNames(
232 RegExp regExp, IndexNameKind kind) async {
233 return _mergeLocations((_PackageIndexRequester requester) {
234 return requester.getDefinedNames(context, regExp, kind);
235 });
236 }
237
238 /**
239 * Complete with a list of locations where the given [element] has relation
240 * of the given [kind].
241 */
242 Future<List<Location>> getRelations(Element element, IndexRelationKind kind) {
243 return _mergeLocations((_PackageIndexRequester requester) {
244 return requester.getRelations(context, element, kind);
245 });
246 }
247
248 /**
249 * Complete with a list of locations where a class members with the given
250 * [name] is referenced with a qualifier, but is not resolved.
251 */
252 Future<List<Location>> getUnresolvedMemberReferences(String name) async {
253 return _mergeLocations((_PackageIndexRequester requester) {
254 return requester.getUnresolvedMemberReferences(context, name);
255 });
256 }
257
258 /**
259 * Index the given fully resolved [unit].
260 */
261 void indexUnit(CompilationUnit unit) {
262 // Index the unit.
263 PackageIndexAssembler assembler = new PackageIndexAssembler();
264 assembler.index(unit);
265 PackageIndexBuilder indexBuilder = assembler.assemble();
266 // Put the index into the map.
267 List<int> indexBytes = indexBuilder.toBuffer();
268 PackageIndex index = new PackageIndex.fromBuffer(indexBytes);
269 String key = _getUnitKeyForElement(unit.element);
270 indexMap[key] = index;
271 }
272
273 /**
274 * Remove index information about the unit.
275 */
276 void removeUnit(Source librarySource, Source unitSource) {
277 String key = _getUnitKeyForSource(librarySource, unitSource);
278 indexMap.remove(key);
279 }
280
281 String _getUnitKeyForElement(CompilationUnitElement unitElement) {
282 Source librarySource = unitElement.library.source;
283 Source unitSource = unitElement.source;
284 return _getUnitKeyForSource(librarySource, unitSource);
285 }
286
287 String _getUnitKeyForSource(Source librarySource, Source unitSource) {
288 String unitLibraryUri = librarySource.uri.toString();
289 String unitUnitUri = unitSource.uri.toString();
290 return '$unitLibraryUri;$unitUnitUri';
291 }
292
293 Future<List<Location>> _mergeLocations(
294 List<Location> callback(_PackageIndexRequester requester)) async {
295 List<Location> locations = <Location>[];
296 for (PackageIndex index in indexMap.values) {
297 _PackageIndexRequester requester = new _PackageIndexRequester(index);
298 List<Location> indexLocations = callback(requester);
299 locations.addAll(indexLocations);
300 }
301 return locations;
302 }
303 }
304
305 /**
306 * Helper for requesting information from a single [PackageIndex].
307 */
308 class _PackageIndexRequester {
309 final PackageIndex index;
310
311 _PackageIndexRequester(this.index);
312
313 /**
314 * Return the [element]'s identifier in the [index] or `-1` if the
315 * [element] is not referenced in the [index].
316 */
317 int findElementId(Element element) {
318 // Find the id of the element's unit.
319 int unitId = getUnitId(element);
320 if (unitId == -1) {
321 return -1;
322 }
323 // Prepare information about the element.
324 ElementInfo info = PackageIndexAssembler.newElementInfo(unitId, element);
325 // Find the first occurrence of an element with the same offset.
326 int elementId = _findFirstOccurrence(index.elementOffsets, info.offset);
327 if (elementId == -1) {
328 return -1;
329 }
330 // Try to find the element id using offset, unit and kind.
331 for (;
332 elementId < index.elementOffsets.length &&
333 index.elementOffsets[elementId] == info.offset;
334 elementId++) {
335 if (index.elementUnits[elementId] == unitId &&
336 index.elementKinds[elementId] == info.kind) {
337 return elementId;
338 }
339 }
88 return -1; 340 return -1;
89 } 341 }
90 342
91 @override 343 /**
92 bool operator ==(Object object) => 344 * Complete with a list of locations where elements of the given [kind] with
93 object is IndexableName && object.name == name; 345 * names satisfying the given [regExp] are defined.
94 346 */
95 @override 347 List<Location> getDefinedNames(
96 String toString() => name; 348 AnalysisContext context, RegExp regExp, IndexNameKind kind) {
97 } 349 List<Location> locations = <Location>[];
98 350 for (UnitIndex unitIndex in index.units) {
99 /** 351 _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex);
100 * The kind of an indexable name. 352 List<Location> unitLocations =
101 */ 353 requester.getDefinedNames(context, regExp, kind);
102 class IndexableNameKind implements IndexableObjectKind<IndexableName> { 354 locations.addAll(unitLocations);
103 /** 355 }
104 * The unique instance of this class. 356 return locations;
105 */ 357 }
106 static final IndexableNameKind INSTANCE = 358
107 new IndexableNameKind._(IndexableObjectKind.nextIndex); 359 /**
108 360 * Complete with a list of locations where the given [element] has relation
109 /** 361 * of the given [kind].
110 * The index uniquely identifying this kind. 362 */
111 */ 363 List<Location> getRelations(
112 final int index; 364 AnalysisContext context, Element element, IndexRelationKind kind) {
113 365 int elementId = findElementId(element);
114 /** 366 if (elementId == -1) {
115 * Initialize a newly created kind to have the given [index]. 367 return const <Location>[];
116 */ 368 }
117 IndexableNameKind._(this.index) { 369 List<Location> locations = <Location>[];
118 IndexableObjectKind.register(this); 370 for (UnitIndex unitIndex in index.units) {
119 } 371 _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex);
120 372 List<Location> unitLocations =
121 @override 373 requester.getRelations(context, elementId, kind);
122 IndexableName decode(AnalysisContext context, String filePath, int offset) { 374 locations.addAll(unitLocations);
123 throw new UnsupportedError( 375 }
124 'Indexable names cannot be decoded through their kind'); 376 return locations;
125 } 377 }
126 378
127 @override 379 /**
128 int encodeHash(StringToInt stringToInt, IndexableName indexable) { 380 * Return the identifier of [str] in the [index] or `-1` if [str] is not used
129 String name = indexable.name; 381 * in the [index].
130 return stringToInt(name); 382 */
131 } 383 int getStringId(String str) {
132 } 384 return binarySearch(index.strings, str);
133 385 }
134 /** 386
135 * Constants used when populating and accessing the index. 387 /**
136 */ 388 * Return the identifier of the [CompilationUnitElement] containing the
137 class IndexConstants { 389 * [element] in the [index] or `-1` if not found.
138 /** 390 */
139 * Left: the Universe or a Library. 391 int getUnitId(Element element) {
140 * Defines an Element. 392 CompilationUnitElement unitElement =
141 * Right: an Element declaration. 393 PackageIndexAssembler.getUnitElement(element);
142 */ 394 int libraryUriId = getUriId(unitElement.library.source.uri);
143 static final RelationshipImpl DEFINES = 395 if (libraryUriId == -1) {
144 RelationshipImpl.getRelationship("defines"); 396 return -1;
145 397 }
146 /** 398 int unitUriId = getUriId(unitElement.source.uri);
147 * Left: class. 399 if (unitUriId == -1) {
148 * Has ancestor (extended or implemented, directly or indirectly). 400 return -1;
149 * Right: other class declaration. 401 }
150 */ 402 for (int i = 0; i < index.unitLibraryUris.length; i++) {
151 static final RelationshipImpl HAS_ANCESTOR = 403 if (index.unitLibraryUris[i] == libraryUriId &&
152 RelationshipImpl.getRelationship("has-ancestor"); 404 index.unitUnitUris[i] == unitUriId) {
153 405 return i;
154 /** 406 }
155 * Left: class. 407 }
156 * Is extended by. 408 return -1;
157 * Right: other class declaration. 409 }
158 */ 410
159 static final RelationshipImpl IS_EXTENDED_BY = 411 /**
160 RelationshipImpl.getRelationship("is-extended-by"); 412 * Return the URI of the library source of the library specific [unit].
161 413 */
162 /** 414 String getUnitLibraryUri(int unit) {
163 * Left: class. 415 int id = index.unitLibraryUris[unit];
164 * Is implemented by. 416 return index.strings[id];
165 * Right: other class declaration. 417 }
166 */ 418
167 static final RelationshipImpl IS_IMPLEMENTED_BY = 419 /**
168 RelationshipImpl.getRelationship("is-implemented-by"); 420 * Return the URI of the unit source of the library specific [unit].
169 421 */
170 /** 422 String getUnitUnitUri(int unit) {
171 * Left: class. 423 int id = index.unitUnitUris[unit];
172 * Is mixed into. 424 return index.strings[id];
173 * Right: other class declaration. 425 }
174 */ 426
175 static final RelationshipImpl IS_MIXED_IN_BY = 427 /**
176 RelationshipImpl.getRelationship("is-mixed-in-by"); 428 * Complete with a list of locations where a class members with the given
177 429 * [name] is referenced with a qualifier, but is not resolved.
178 /** 430 */
179 * Left: local variable, parameter. 431 List<Location> getUnresolvedMemberReferences(
180 * Is read at. 432 AnalysisContext context, String name) {
181 * Right: location. 433 List<Location> locations = <Location>[];
182 */ 434 for (UnitIndex unitIndex in index.units) {
183 static final RelationshipImpl IS_READ_BY = 435 _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex);
184 RelationshipImpl.getRelationship("is-read-by"); 436 List<Location> unitLocations =
185 437 requester.getUnresolvedMemberReferences(context, name);
186 /** 438 locations.addAll(unitLocations);
187 * Left: local variable, parameter. 439 }
188 * Is both read and written at. 440 return locations;
189 * Right: location. 441 }
190 */ 442
191 static final RelationshipImpl IS_READ_WRITTEN_BY = 443 /**
192 RelationshipImpl.getRelationship("is-read-written-by"); 444 * Return the identifier of the [uri] in the [index] or `-1` if the [uri] is
193 445 * not used in the [index].
194 /** 446 */
195 * Left: local variable, parameter. 447 int getUriId(Uri uri) {
196 * Is written at. 448 String str = uri.toString();
197 * Right: location. 449 return getStringId(str);
198 */ 450 }
199 static final RelationshipImpl IS_WRITTEN_BY = 451 }
200 RelationshipImpl.getRelationship("is-written-by"); 452
201 453 /**
202 /** 454 * Helper for requesting information from a single [UnitIndex].
203 * Left: function, method, variable, getter. 455 */
204 * Is invoked at. 456 class _UnitIndexRequester {
205 * Right: location. 457 final _PackageIndexRequester packageRequester;
206 */ 458 final UnitIndex unitIndex;
207 static final RelationshipImpl IS_INVOKED_BY = 459
208 RelationshipImpl.getRelationship("is-invoked-by"); 460 _UnitIndexRequester(this.packageRequester, this.unitIndex);
209 461
210 /** 462 /**
211 * Left: function, function type, class, field, method. 463 * Complete with a list of locations where elements of the given [kind] with
212 * Is referenced (and not invoked, read/written) at. 464 * names satisfying the given [regExp] are defined.
213 * Right: location. 465 */
214 */ 466 List<Location> getDefinedNames(
215 static final RelationshipImpl IS_REFERENCED_BY = 467 AnalysisContext context, RegExp regExp, IndexNameKind kind) {
216 RelationshipImpl.getRelationship("is-referenced-by"); 468 List<Location> locations = <Location>[];
217 469 String unitLibraryUri = null;
218 /** 470 String unitUnitUri = null;
219 * Left: name element. 471 for (int i = 0; i < unitIndex.definedNames.length; i++) {
220 * Is defined by. 472 if (unitIndex.definedNameKinds[i] == kind) {
221 * Right: concrete element declaration. 473 int nameIndex = unitIndex.definedNames[i];
222 */ 474 String name = packageRequester.index.strings[nameIndex];
223 static final RelationshipImpl NAME_IS_DEFINED_BY = 475 if (regExp.matchAsPrefix(name) != null) {
224 RelationshipImpl.getRelationship("name-is-defined-by"); 476 unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit);
225 477 unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit);
226 IndexConstants._(); 478 locations.add(new Location(context, unitLibraryUri, unitUnitUri, null,
227 } 479 unitIndex.definedNameOffsets[i], name.length, false, true));
228 480 }
229 /** 481 }
230 * Instances of the class [LocationImpl] represent a location related to an 482 }
231 * element. 483 return locations;
232 * 484 }
233 * The location is expressed as an offset and length, but the offset is relative 485
234 * to the resource containing the element rather than the start of the element 486 /**
235 * within that resource. 487 * Return a list of locations where an element with the given [elementId] has
236 */ 488 * relation of the given [kind].
237 class LocationImpl implements Location { 489 */
238 static const int _FLAG_QUALIFIED = 1 << 0; 490 List<Location> getRelations(
239 static const int _FLAG_RESOLVED = 1 << 1; 491 AnalysisContext context, int elementId, IndexRelationKind kind) {
240 492 // Find the first usage of the element.
241 /** 493 int i = _findFirstOccurrence(unitIndex.usedElements, elementId);
242 * An empty array of locations. 494 if (i == -1) {
243 */ 495 return const <Location>[];
244 static const List<LocationImpl> EMPTY_LIST = const <LocationImpl>[]; 496 }
245 497 // Create locations for every usage of the element.
246 /** 498 List<Location> locations = <Location>[];
247 * The indexable object containing this location. 499 String unitLibraryUri = null;
248 */ 500 String unitUnitUri = null;
249 final IndexableObject indexable; 501 for (;
250 502 i < unitIndex.usedElements.length &&
251 /** 503 unitIndex.usedElements[i] == elementId;
252 * The offset of this location within the resource containing the element. 504 i++) {
253 */ 505 if (unitIndex.usedElementKinds[i] == kind) {
254 final int offset; 506 unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit);
255 507 unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit);
256 /** 508 locations.add(new Location(
257 * The length of this location. 509 context,
258 */ 510 unitLibraryUri,
259 final int length; 511 unitUnitUri,
260 512 kind,
261 /** 513 unitIndex.usedElementOffsets[i],
262 * The flags of this location. 514 unitIndex.usedElementLengths[i],
263 */ 515 unitIndex.usedElementIsQualifiedFlags[i],
264 int _flags; 516 true));
265 517 }
266 /** 518 }
267 * Initializes a newly created location to be relative to the given 519 return locations;
268 * [indexable] object at the given [offset] with the given [length]. 520 }
269 */ 521
270 LocationImpl(this.indexable, this.offset, this.length, 522 /**
271 {bool isQualified: false, bool isResolved: true}) { 523 * Complete with a list of locations where a class members with the given
272 if (indexable == null) { 524 * [name] is referenced with a qualifier, but is not resolved.
273 throw new ArgumentError("indexable object cannot be null"); 525 */
274 } 526 List<Location> getUnresolvedMemberReferences(
275 _flags = 0; 527 AnalysisContext context, String name) {
276 if (isQualified) { 528 // Find the name ID in the package index.
277 _flags |= _FLAG_QUALIFIED; 529 int nameId = packageRequester.getStringId(name);
278 } 530 if (nameId == -1) {
279 if (isResolved) { 531 return const <Location>[];
280 _flags |= _FLAG_RESOLVED; 532 }
281 } 533 // Find the first usage of the name.
282 } 534 int i = _findFirstOccurrence(unitIndex.usedNames, nameId);
283 535 if (i == -1) {
284 /** 536 return const <Location>[];
285 * The element containing this location. 537 }
286 */ 538 // Create locations for every usage of the name.
287 @deprecated 539 List<Location> locations = <Location>[];
288 Element get element { 540 String unitLibraryUri = null;
289 if (indexable is IndexableElement) { 541 String unitUnitUri = null;
290 return (indexable as IndexableElement).element; 542 for (;
291 } 543 i < unitIndex.usedNames.length && unitIndex.usedNames[i] == nameId;
292 return null; 544 i++) {
293 } 545 unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit);
294 546 unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit);
295 @override 547 locations.add(new Location(
296 bool get isQualified => (_flags & _FLAG_QUALIFIED) != 0; 548 context,
297 549 unitLibraryUri,
298 @override 550 unitUnitUri,
299 bool get isResolved => (_flags & _FLAG_RESOLVED) != 0; 551 unitIndex.usedNameKinds[i],
300 552 unitIndex.usedNameOffsets[i],
301 @override 553 name.length,
302 String toString() { 554 unitIndex.usedNameIsQualifiedFlags[i],
303 String flagsStr = ''; 555 false));
304 if (isQualified) { 556 }
305 flagsStr += ' qualified'; 557 return locations;
306 } 558 }
307 if (isResolved) { 559 }
308 flagsStr += ' resolved';
309 }
310 return '[$offset - ${offset + length}) $flagsStr in $indexable';
311 }
312 }
313
314 /**
315 * A [LocationImpl] with attached data.
316 */
317 class LocationWithData<D> extends LocationImpl {
318 final D data;
319
320 LocationWithData(LocationImpl location, this.data)
321 : super(location.indexable, location.offset, location.length);
322 }
323
324 /**
325 * Relationship between an element and a location. Relationships are identified
326 * by a globally unique identifier.
327 */
328 class RelationshipImpl implements Relationship {
329 /**
330 * A table mapping relationship identifiers to relationships.
331 */
332 static Map<String, RelationshipImpl> _RELATIONSHIP_MAP = {};
333
334 /**
335 * The next artificial hash code.
336 */
337 static int _NEXT_HASH_CODE = 0;
338
339 /**
340 * The artificial hash code for this object.
341 */
342 final int _hashCode = _NEXT_HASH_CODE++;
343
344 /**
345 * The unique identifier for this relationship.
346 */
347 final String identifier;
348
349 /**
350 * Initialize a newly created relationship with the given unique identifier.
351 */
352 RelationshipImpl(this.identifier);
353
354 @override
355 int get hashCode => _hashCode;
356
357 @override
358 String toString() => identifier;
359
360 /**
361 * Returns the relationship with the given unique [identifier].
362 */
363 static RelationshipImpl getRelationship(String identifier) {
364 RelationshipImpl relationship = _RELATIONSHIP_MAP[identifier];
365 if (relationship == null) {
366 relationship = new RelationshipImpl(identifier);
367 _RELATIONSHIP_MAP[identifier] = relationship;
368 }
369 return relationship;
370 }
371 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698