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

Side by Side Diff: pkg/analysis_server/lib/src/services/index2/index2.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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 import 'dart:async';
6
7 import 'package:analyzer/dart/ast/ast.dart';
8 import 'package:analyzer/dart/element/element.dart';
9 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
10 import 'package:analyzer/src/generated/source.dart';
11 import 'package:analyzer/src/summary/format.dart';
12 import 'package:analyzer/src/summary/idl.dart';
13 import 'package:analyzer/src/summary/index_unit.dart';
14 import 'package:collection/collection.dart';
15
16 /**
17 * Return a new [Index2] instance that keeps information in memory.
18 */
19 Index2 createMemoryIndex2() {
20 return new Index2._();
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 Index2 {
44 final Map<AnalysisContext, _ContextIndex> _contextIndexMap =
45 <AnalysisContext, _ContextIndex>{};
46
47 Index2._();
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 * Return the [_ContextIndex] instance for the given [context].
107 */
108 _ContextIndex _getContextIndex(AnalysisContext context) {
109 return _contextIndexMap.putIfAbsent(context, () {
110 return new _ContextIndex(context);
111 });
112 }
113
114 /**
115 * Complete with a list of all results returned by the [callback] for every
116 * context specific index.
117 */
118 Future<List<Location>> _mergeLocations(
119 Future<List<Location>> callback(_ContextIndex index)) async {
120 List<Location> locations = <Location>[];
121 for (_ContextIndex index in _contextIndexMap.values) {
122 List<Location> contextLocations = await callback(index);
123 locations.addAll(contextLocations);
124 }
125 return locations;
126 }
127 }
128
129 /**
130 * Information about location of a single relation in the index.
131 *
132 * The location is expressed as a library specific unit containing the index
133 * relation, offset within this [Source] and length.
134 *
135 * Clients may not extend, implement or mix-in this class.
136 */
137 class Location {
138 /**
139 * The [AnalysisContext] containing this location.
140 */
141 final AnalysisContext context;
142
143 /**
144 * The URI of the source of the library containing this location.
145 */
146 final String libraryUri;
147
148 /**
149 * The URI of the source of the unit containing this location.
150 */
151 final String unitUri;
152
153 /**
154 * The kind of usage at this location.
155 */
156 final IndexRelationKind kind;
157
158 /**
159 * The offset of this location within the [unitUri].
160 */
161 final int offset;
162
163 /**
164 * The length of this location.
165 */
166 final int length;
167
168 /**
169 * Is `true` if this location is qualified.
170 */
171 final bool isQualified;
172
173 /**
174 * Is `true` if this location is resolved.
175 */
176 final bool isResolved;
177
178 Location(this.context, this.libraryUri, this.unitUri, this.kind, this.offset,
179 this.length, this.isQualified, this.isResolved);
180
181 @override
182 String toString() => 'Location{librarySourceUri: $libraryUri, '
183 'unitSourceUri: $unitUri, offset: $offset, length: $length, '
184 'isQualified: $isQualified}, isResolved: $isResolved}';
185 }
186
187 /**
188 * Opaque identifier of a [PackageIndex].
189 */
190 abstract class PackageIndexId {}
191
192 /**
193 * Storage of [PackageIndex] objects.
194 */
195 abstract class PackageIndexStore {
196 /**
197 * Complete with identifiers of all [PackageIndex] objects.
198 */
199 Future<Iterable<PackageIndexId>> getIds();
200
201 /**
202 * Complete with the [PackageIndex] with the given [id].
203 */
204 Future<PackageIndex> getIndex(PackageIndexId id);
205
206 /**
207 * Put the given [indexBuilder] into the store.
208 */
209 void putIndex(String unitLibraryUri, String unitUnitUri,
210 PackageIndexBuilder indexBuilder);
211 }
212
213 /**
214 * The [AnalysisContext] specific index.
215 */
216 class _ContextIndex {
217 final AnalysisContext context;
218 final Map<String, PackageIndex> indexMap = <String, PackageIndex>{};
219
220 _ContextIndex(this.context);
221
222 /**
223 * Complete with a list of locations where elements of the given [kind] with
224 * names satisfying the given [regExp] are defined.
225 */
226 Future<List<Location>> getDefinedNames(
227 RegExp regExp, IndexNameKind kind) async {
228 return _mergeLocations((_PackageIndexRequester requester) {
229 return requester.getDefinedNames(context, regExp, kind);
230 });
231 }
232
233 /**
234 * Complete with a list of locations where the given [element] has relation
235 * of the given [kind].
236 */
237 Future<List<Location>> getRelations(Element element, IndexRelationKind kind) {
238 return _mergeLocations((_PackageIndexRequester requester) {
239 return requester.getRelations(context, element, kind);
240 });
241 }
242
243 /**
244 * Complete with a list of locations where a class members with the given
245 * [name] is referenced with a qualifier, but is not resolved.
246 */
247 Future<List<Location>> getUnresolvedMemberReferences(String name) async {
248 return _mergeLocations((_PackageIndexRequester requester) {
249 return requester.getUnresolvedMemberReferences(context, name);
250 });
251 }
252
253 /**
254 * Index the given fully resolved [unit].
255 */
256 void indexUnit(CompilationUnit unit) {
257 // Index the unit.
258 PackageIndexAssembler assembler = new PackageIndexAssembler();
259 assembler.index(unit);
260 PackageIndexBuilder indexBuilder = assembler.assemble();
261 // Put the index into the map.
262 List<int> indexBytes = indexBuilder.toBuffer();
263 PackageIndex index = new PackageIndex.fromBuffer(indexBytes);
264 String key = _getUnitKeyForElement(unit.element);
265 indexMap[key] = index;
266 }
267
268 /**
269 * Remove index information about the unit.
270 */
271 void removeUnit(Source librarySource, Source unitSource) {
272 String key = _getUnitKeyForSource(librarySource, unitSource);
273 indexMap.remove(key);
274 }
275
276 String _getUnitKeyForElement(CompilationUnitElement unitElement) {
277 Source librarySource = unitElement.library.source;
278 Source unitSource = unitElement.source;
279 return _getUnitKeyForSource(librarySource, unitSource);
280 }
281
282 String _getUnitKeyForSource(Source librarySource, Source unitSource) {
283 String unitLibraryUri = librarySource.uri.toString();
284 String unitUnitUri = unitSource.uri.toString();
285 return '$unitLibraryUri;$unitUnitUri';
286 }
287
288 Future<List<Location>> _mergeLocations(
289 List<Location> callback(_PackageIndexRequester requester)) async {
290 List<Location> locations = <Location>[];
291 for (PackageIndex index in indexMap.values) {
292 _PackageIndexRequester requester = new _PackageIndexRequester(index);
293 List<Location> indexLocations = callback(requester);
294 locations.addAll(indexLocations);
295 }
296 return locations;
297 }
298 }
299
300 /**
301 * Helper for requesting information from a single [PackageIndex].
302 */
303 class _PackageIndexRequester {
304 final PackageIndex index;
305
306 _PackageIndexRequester(this.index);
307
308 /**
309 * Return the [element]'s identifier in the [index] or `-1` if the
310 * [element] is not referenced in the [index].
311 */
312 int findElementId(Element element) {
313 // Find the id of the element's unit.
314 int unitId = getUnitId(element);
315 if (unitId == -1) {
316 return -1;
317 }
318 // Prepare information about the element.
319 ElementInfo info = PackageIndexAssembler.newElementInfo(unitId, element);
320 // Find the first occurrence of an element with the same offset.
321 int elementId = _findFirstOccurrence(index.elementOffsets, info.offset);
322 if (elementId == -1) {
323 return -1;
324 }
325 // Try to find the element id using offset, unit and kind.
326 for (;
327 elementId < index.elementOffsets.length &&
328 index.elementOffsets[elementId] == info.offset;
329 elementId++) {
330 if (index.elementUnits[elementId] == unitId &&
331 index.elementKinds[elementId] == info.kind) {
332 return elementId;
333 }
334 }
335 return -1;
336 }
337
338 /**
339 * Complete with a list of locations where elements of the given [kind] with
340 * names satisfying the given [regExp] are defined.
341 */
342 List<Location> getDefinedNames(
343 AnalysisContext context, RegExp regExp, IndexNameKind kind) {
344 List<Location> locations = <Location>[];
345 for (UnitIndex unitIndex in index.units) {
346 _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex);
347 List<Location> unitLocations =
348 requester.getDefinedNames(context, regExp, kind);
349 locations.addAll(unitLocations);
350 }
351 return locations;
352 }
353
354 /**
355 * Complete with a list of locations where the given [element] has relation
356 * of the given [kind].
357 */
358 List<Location> getRelations(
359 AnalysisContext context, Element element, IndexRelationKind kind) {
360 int elementId = findElementId(element);
361 if (elementId == -1) {
362 return const <Location>[];
363 }
364 List<Location> locations = <Location>[];
365 for (UnitIndex unitIndex in index.units) {
366 _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex);
367 List<Location> unitLocations =
368 requester.getRelations(context, elementId, kind);
369 locations.addAll(unitLocations);
370 }
371 return locations;
372 }
373
374 /**
375 * Return the identifier of [str] in the [index] or `-1` if [str] is not used
376 * in the [index].
377 */
378 int getStringId(String str) {
379 return binarySearch(index.strings, str);
380 }
381
382 /**
383 * Return the identifier of the [CompilationUnitElement] containing the
384 * [element] in the [index] or `-1` if not found.
385 */
386 int getUnitId(Element element) {
387 CompilationUnitElement unitElement =
388 PackageIndexAssembler.getUnitElement(element);
389 int libraryUriId = getUriId(unitElement.library.source.uri);
390 if (libraryUriId == -1) {
391 return -1;
392 }
393 int unitUriId = getUriId(unitElement.source.uri);
394 if (unitUriId == -1) {
395 return -1;
396 }
397 for (int i = 0; i < index.unitLibraryUris.length; i++) {
398 if (index.unitLibraryUris[i] == libraryUriId &&
399 index.unitUnitUris[i] == unitUriId) {
400 return i;
401 }
402 }
403 return -1;
404 }
405
406 /**
407 * Return the URI of the library source of the library specific [unit].
408 */
409 String getUnitLibraryUri(int unit) {
410 int id = index.unitLibraryUris[unit];
411 return index.strings[id];
412 }
413
414 /**
415 * Return the URI of the unit source of the library specific [unit].
416 */
417 String getUnitUnitUri(int unit) {
418 int id = index.unitUnitUris[unit];
419 return index.strings[id];
420 }
421
422 /**
423 * Complete with a list of locations where a class members with the given
424 * [name] is referenced with a qualifier, but is not resolved.
425 */
426 List<Location> getUnresolvedMemberReferences(
427 AnalysisContext context, String name) {
428 List<Location> locations = <Location>[];
429 for (UnitIndex unitIndex in index.units) {
430 _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex);
431 List<Location> unitLocations =
432 requester.getUnresolvedMemberReferences(context, name);
433 locations.addAll(unitLocations);
434 }
435 return locations;
436 }
437
438 /**
439 * Return the identifier of the [uri] in the [index] or `-1` if the [uri] is
440 * not used in the [index].
441 */
442 int getUriId(Uri uri) {
443 String str = uri.toString();
444 return getStringId(str);
445 }
446 }
447
448 /**
449 * Helper for requesting information from a single [UnitIndex].
450 */
451 class _UnitIndexRequester {
452 final _PackageIndexRequester packageRequester;
453 final UnitIndex unitIndex;
454
455 _UnitIndexRequester(this.packageRequester, this.unitIndex);
456
457 /**
458 * Complete with a list of locations where elements of the given [kind] with
459 * names satisfying the given [regExp] are defined.
460 */
461 List<Location> getDefinedNames(
462 AnalysisContext context, RegExp regExp, IndexNameKind kind) {
463 List<Location> locations = <Location>[];
464 String unitLibraryUri = null;
465 String unitUnitUri = null;
466 for (int i = 0; i < unitIndex.definedNames.length; i++) {
467 if (unitIndex.definedNameKinds[i] == kind) {
468 int nameIndex = unitIndex.definedNames[i];
469 String name = packageRequester.index.strings[nameIndex];
470 if (regExp.matchAsPrefix(name) != null) {
471 unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit);
472 unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit);
473 locations.add(new Location(context, unitLibraryUri, unitUnitUri, null,
474 unitIndex.definedNameOffsets[i], name.length, false, true));
475 }
476 }
477 }
478 return locations;
479 }
480
481 /**
482 * Return a list of locations where an element with the given [elementId] has
483 * relation of the given [kind].
484 */
485 List<Location> getRelations(
486 AnalysisContext context, int elementId, IndexRelationKind kind) {
487 // Find the first usage of the element.
488 int i = _findFirstOccurrence(unitIndex.usedElements, elementId);
489 if (i == -1) {
490 return const <Location>[];
491 }
492 // Create locations for every usage of the element.
493 List<Location> locations = <Location>[];
494 String unitLibraryUri = null;
495 String unitUnitUri = null;
496 for (;
497 i < unitIndex.usedElements.length &&
498 unitIndex.usedElements[i] == elementId;
499 i++) {
500 if (unitIndex.usedElementKinds[i] == kind) {
501 unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit);
502 unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit);
503 locations.add(new Location(
504 context,
505 unitLibraryUri,
506 unitUnitUri,
507 kind,
508 unitIndex.usedElementOffsets[i],
509 unitIndex.usedElementLengths[i],
510 unitIndex.usedElementIsQualifiedFlags[i],
511 true));
512 }
513 }
514 return locations;
515 }
516
517 /**
518 * Complete with a list of locations where a class members with the given
519 * [name] is referenced with a qualifier, but is not resolved.
520 */
521 List<Location> getUnresolvedMemberReferences(
522 AnalysisContext context, String name) {
523 // Find the name ID in the package index.
524 int nameId = packageRequester.getStringId(name);
525 if (nameId == -1) {
526 return const <Location>[];
527 }
528 // Find the first usage of the name.
529 int i = _findFirstOccurrence(unitIndex.usedNames, nameId);
530 if (i == -1) {
531 return const <Location>[];
532 }
533 // Create locations for every usage of the name.
534 List<Location> locations = <Location>[];
535 String unitLibraryUri = null;
536 String unitUnitUri = null;
537 for (;
538 i < unitIndex.usedNames.length && unitIndex.usedNames[i] == nameId;
539 i++) {
540 unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit);
541 unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit);
542 locations.add(new Location(
543 context,
544 unitLibraryUri,
545 unitUnitUri,
546 unitIndex.usedNameKinds[i],
547 unitIndex.usedNameOffsets[i],
548 name.length,
549 unitIndex.usedNameIsQualifiedFlags[i],
550 false));
551 }
552 return locations;
553 }
554 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698