| Index: pkg/analysis_server/lib/src/services/index2/index2.dart
|
| diff --git a/pkg/analysis_server/lib/src/services/index2/index2.dart b/pkg/analysis_server/lib/src/services/index2/index2.dart
|
| index a3da32b1fdd3e94ebbb82a7f3b67e797284d6a26..6e6d704ac6fa7b62ce516ab8b29318ad97f49a4f 100644
|
| --- a/pkg/analysis_server/lib/src/services/index2/index2.dart
|
| +++ b/pkg/analysis_server/lib/src/services/index2/index2.dart
|
| @@ -6,6 +6,7 @@ import 'dart:async';
|
|
|
| import 'package:analyzer/dart/ast/ast.dart';
|
| import 'package:analyzer/dart/element/element.dart';
|
| +import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
|
| import 'package:analyzer/src/generated/source.dart';
|
| import 'package:analyzer/src/summary/format.dart';
|
| import 'package:analyzer/src/summary/idl.dart';
|
| @@ -16,8 +17,7 @@ import 'package:collection/collection.dart';
|
| * Return a new [Index2] instance that keeps information in memory.
|
| */
|
| Index2 createMemoryIndex2() {
|
| - _MemoryPackageIndexStore store = new _MemoryPackageIndexStore();
|
| - return new Index2(store);
|
| + return new Index2._();
|
| }
|
|
|
| /**
|
| @@ -41,71 +41,80 @@ int _findFirstOccurrence(List<int> sortedList, int value) {
|
| * Interface for storing and requesting relations.
|
| */
|
| class Index2 {
|
| - final PackageIndexStore _store;
|
| + final Map<AnalysisContext, _ContextIndex> _contextIndexMap =
|
| + <AnalysisContext, _ContextIndex>{};
|
|
|
| - Index2(this._store);
|
| + Index2._();
|
|
|
| /**
|
| * Complete with a list of locations where elements of the given [kind] with
|
| * names satisfying the given [regExp] are defined.
|
| */
|
| - Future<List<Location>> getDefinedNames(
|
| - RegExp regExp, IndexNameKind kind) async {
|
| - List<Location> locations = <Location>[];
|
| - Iterable<PackageIndexId> ids = await _store.getIds();
|
| - for (PackageIndexId id in ids) {
|
| - PackageIndex index = await _store.getIndex(id);
|
| - _PackageIndexRequester requester = new _PackageIndexRequester(index);
|
| - List<Location> packageLocations = requester.getDefinedNames(regExp, kind);
|
| - locations.addAll(packageLocations);
|
| - }
|
| - return locations;
|
| + Future<List<Location>> getDefinedNames(RegExp regExp, IndexNameKind kind) {
|
| + return _mergeLocations((_ContextIndex index) {
|
| + return index.getDefinedNames(regExp, kind);
|
| + });
|
| }
|
|
|
| /**
|
| * Complete with a list of locations where the given [element] has relation
|
| * of the given [kind].
|
| */
|
| - Future<List<Location>> getRelations(
|
| - Element element, IndexRelationKind kind) async {
|
| - List<Location> locations = <Location>[];
|
| - Iterable<PackageIndexId> ids = await _store.getIds();
|
| - for (PackageIndexId id in ids) {
|
| - PackageIndex index = await _store.getIndex(id);
|
| - _PackageIndexRequester requester = new _PackageIndexRequester(index);
|
| - List<Location> packageLocations = requester.getRelations(element, kind);
|
| - locations.addAll(packageLocations);
|
| - }
|
| - return locations;
|
| + Future<List<Location>> getRelations(Element element, IndexRelationKind kind) {
|
| + return _mergeLocations((_ContextIndex index) {
|
| + return index.getRelations(element, kind);
|
| + });
|
| }
|
|
|
| /**
|
| * Complete with a list of locations where a class members with the given
|
| * [name] is referenced with a qualifier, but is not resolved.
|
| */
|
| - Future<List<Location>> getUnresolvedMemberReferences(String name) async {
|
| - List<Location> locations = <Location>[];
|
| - Iterable<PackageIndexId> ids = await _store.getIds();
|
| - for (PackageIndexId id in ids) {
|
| - PackageIndex index = await _store.getIndex(id);
|
| - _PackageIndexRequester requester = new _PackageIndexRequester(index);
|
| - List<Location> packageLocations =
|
| - requester.getUnresolvedMemberReferences(name);
|
| - locations.addAll(packageLocations);
|
| - }
|
| - return locations;
|
| + Future<List<Location>> getUnresolvedMemberReferences(String name) {
|
| + return _mergeLocations((_ContextIndex index) {
|
| + return index.getUnresolvedMemberReferences(name);
|
| + });
|
| }
|
|
|
| /**
|
| * Index the given fully resolved [unit].
|
| */
|
| void indexUnit(CompilationUnit unit) {
|
| - PackageIndexAssembler assembler = new PackageIndexAssembler();
|
| - assembler.index(unit);
|
| - PackageIndexBuilder indexBuilder = assembler.assemble();
|
| - String unitLibraryUri = unit.element.library.source.uri.toString();
|
| - String unitUnitUri = unit.element.source.uri.toString();
|
| - _store.putIndex(unitLibraryUri, unitUnitUri, indexBuilder);
|
| + if (unit == null || unit.element == null) {
|
| + return;
|
| + }
|
| + AnalysisContext context = unit.element.context;
|
| + _getContextIndex(context).indexUnit(unit);
|
| + }
|
| +
|
| + /**
|
| + * Remove all index information for the given [context].
|
| + */
|
| + void removeContext(AnalysisContext context) {
|
| + _contextIndexMap.remove(context);
|
| + }
|
| +
|
| + /**
|
| + * Return the [_ContextIndex] instance for the given [context].
|
| + */
|
| + _ContextIndex _getContextIndex(AnalysisContext context) {
|
| + return _contextIndexMap.putIfAbsent(context, () {
|
| + return new _ContextIndex(context);
|
| + });
|
| + }
|
| +
|
| + /**
|
| + * Complete with a list of all results returned by the [callback] for every
|
| + * context specific index.
|
| + */
|
| + Future<List<Location>> _mergeLocations(
|
| + Future<List<Location>> callback(_ContextIndex index)) async {
|
| + List<Location> locations = <Location>[];
|
| + for (_ContextIndex index in _contextIndexMap.values) {
|
| + List<Location> contextLocations = await callback(index);
|
| + locations.addAll(contextLocations);
|
| + }
|
| + return locations;
|
| }
|
| }
|
|
|
| @@ -119,6 +128,11 @@ class Index2 {
|
| */
|
| class Location {
|
| /**
|
| + * The [AnalysisContext] containing this location.
|
| + */
|
| + final AnalysisContext context;
|
| +
|
| + /**
|
| * The URI of the source of the library containing this location.
|
| */
|
| final String libraryUri;
|
| @@ -143,8 +157,8 @@ class Location {
|
| */
|
| final bool isQualified;
|
|
|
| - Location(this.libraryUri, this.unitUri, this.offset, this.length,
|
| - this.isQualified);
|
| + Location(this.context, this.libraryUri, this.unitUri, this.offset,
|
| + this.length, this.isQualified);
|
|
|
| @override
|
| String toString() => 'Location{librarySourceUri: $libraryUri, '
|
| @@ -179,38 +193,84 @@ abstract class PackageIndexStore {
|
| }
|
|
|
| /**
|
| - * A [PackageIndexId] for [_MemoryPackageIndexStore].
|
| + * The [AnalysisContext] specific index.
|
| */
|
| -class _MemoryPackageIndexId implements PackageIndexId {
|
| - final String key;
|
| +class _ContextIndex {
|
| + final AnalysisContext context;
|
| + final Map<String, PackageIndex> indexMap = <String, PackageIndex>{};
|
|
|
| - _MemoryPackageIndexId(this.key);
|
| -}
|
| + _ContextIndex(this.context);
|
|
|
| -/**
|
| - * A [PackageIndexStore] that keeps objects in memory;
|
| - */
|
| -class _MemoryPackageIndexStore implements PackageIndexStore {
|
| - final Map<String, PackageIndex> indexMap = <String, PackageIndex>{};
|
| + /**
|
| + * Complete with a list of locations where elements of the given [kind] with
|
| + * names satisfying the given [regExp] are defined.
|
| + */
|
| + Future<List<Location>> getDefinedNames(
|
| + RegExp regExp, IndexNameKind kind) async {
|
| + return _mergeLocations((PackageIndex index) {
|
| + _PackageIndexRequester requester = new _PackageIndexRequester(index);
|
| + return requester.getDefinedNames(context, regExp, kind);
|
| + });
|
| + }
|
|
|
| - @override
|
| - Future<Iterable<PackageIndexId>> getIds() async {
|
| - return indexMap.keys.map((key) => new _MemoryPackageIndexId(key));
|
| + /**
|
| + * Complete with a list of locations where the given [element] has relation
|
| + * of the given [kind].
|
| + */
|
| + Future<List<Location>> getRelations(Element element, IndexRelationKind kind) {
|
| + return _mergeLocations((PackageIndex index) {
|
| + _PackageIndexRequester requester = new _PackageIndexRequester(index);
|
| + return requester.getRelations(context, element, kind);
|
| + });
|
| }
|
|
|
| - @override
|
| - Future<PackageIndex> getIndex(PackageIndexId id) async {
|
| - return indexMap[(id as _MemoryPackageIndexId).key];
|
| + /**
|
| + * Complete with a list of locations where a class members with the given
|
| + * [name] is referenced with a qualifier, but is not resolved.
|
| + */
|
| + Future<List<Location>> getUnresolvedMemberReferences(String name) async {
|
| + return _mergeLocations((PackageIndex index) {
|
| + _PackageIndexRequester requester = new _PackageIndexRequester(index);
|
| + return requester.getUnresolvedMemberReferences(context, name);
|
| + });
|
| }
|
|
|
| - @override
|
| - putIndex(String unitLibraryUri, String unitUnitUri,
|
| - PackageIndexBuilder indexBuilder) {
|
| + /**
|
| + * Index the given fully resolved [unit].
|
| + */
|
| + void indexUnit(CompilationUnit unit) {
|
| + // Index the unit.
|
| + PackageIndexAssembler assembler = new PackageIndexAssembler();
|
| + assembler.index(unit);
|
| + PackageIndexBuilder indexBuilder = assembler.assemble();
|
| + // Put the index into the map.
|
| List<int> indexBytes = indexBuilder.toBuffer();
|
| PackageIndex index = new PackageIndex.fromBuffer(indexBytes);
|
| - String key = '$unitLibraryUri;$unitUnitUri';
|
| + String key = _getUnitKeyForElement(unit.element);
|
| indexMap[key] = index;
|
| }
|
| +
|
| + String _getUnitKeyForElement(CompilationUnitElement unitElement) {
|
| + Source librarySource = unitElement.library.source;
|
| + Source unitSource = unitElement.source;
|
| + return _getUnitKeyForSource(librarySource, unitSource);
|
| + }
|
| +
|
| + String _getUnitKeyForSource(Source librarySource, Source unitSource) {
|
| + String unitLibraryUri = librarySource.uri.toString();
|
| + String unitUnitUri = unitSource.uri.toString();
|
| + return '$unitLibraryUri;$unitUnitUri';
|
| + }
|
| +
|
| + Future<List<Location>> _mergeLocations(
|
| + List<Location> callback(PackageIndex index)) async {
|
| + List<Location> locations = <Location>[];
|
| + for (PackageIndex index in indexMap.values) {
|
| + List<Location> indexLocations = callback(index);
|
| + locations.addAll(indexLocations);
|
| + }
|
| + return locations;
|
| + }
|
| }
|
|
|
| /**
|
| @@ -260,11 +320,13 @@ class _PackageIndexRequester {
|
| * Complete with a list of locations where elements of the given [kind] with
|
| * names satisfying the given [regExp] are defined.
|
| */
|
| - List<Location> getDefinedNames(RegExp regExp, IndexNameKind kind) {
|
| + List<Location> getDefinedNames(
|
| + AnalysisContext context, RegExp regExp, IndexNameKind kind) {
|
| List<Location> locations = <Location>[];
|
| for (UnitIndex unitIndex in index.units) {
|
| _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex);
|
| - List<Location> unitLocations = requester.getDefinedNames(regExp, kind);
|
| + List<Location> unitLocations =
|
| + requester.getDefinedNames(context, regExp, kind);
|
| locations.addAll(unitLocations);
|
| }
|
| return locations;
|
| @@ -274,7 +336,8 @@ class _PackageIndexRequester {
|
| * Complete with a list of locations where the given [element] has relation
|
| * of the given [kind].
|
| */
|
| - List<Location> getRelations(Element element, IndexRelationKind kind) {
|
| + List<Location> getRelations(
|
| + AnalysisContext context, Element element, IndexRelationKind kind) {
|
| int elementId = findElementId(element);
|
| if (elementId == -1) {
|
| return const <Location>[];
|
| @@ -282,7 +345,8 @@ class _PackageIndexRequester {
|
| List<Location> locations = <Location>[];
|
| for (UnitIndex unitIndex in index.units) {
|
| _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex);
|
| - List<Location> unitLocations = requester.getRelations(elementId, kind);
|
| + List<Location> unitLocations =
|
| + requester.getRelations(context, elementId, kind);
|
| locations.addAll(unitLocations);
|
| }
|
| return locations;
|
| @@ -340,12 +404,13 @@ class _PackageIndexRequester {
|
| * Complete with a list of locations where a class members with the given
|
| * [name] is referenced with a qualifier, but is not resolved.
|
| */
|
| - List<Location> getUnresolvedMemberReferences(String name) {
|
| + List<Location> getUnresolvedMemberReferences(
|
| + AnalysisContext context, String name) {
|
| List<Location> locations = <Location>[];
|
| for (UnitIndex unitIndex in index.units) {
|
| _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex);
|
| List<Location> unitLocations =
|
| - requester.getUnresolvedMemberReferences(name);
|
| + requester.getUnresolvedMemberReferences(context, name);
|
| locations.addAll(unitLocations);
|
| }
|
| return locations;
|
| @@ -374,7 +439,8 @@ class _UnitIndexRequester {
|
| * Complete with a list of locations where elements of the given [kind] with
|
| * names satisfying the given [regExp] are defined.
|
| */
|
| - List<Location> getDefinedNames(RegExp regExp, IndexNameKind kind) {
|
| + List<Location> getDefinedNames(
|
| + AnalysisContext context, RegExp regExp, IndexNameKind kind) {
|
| List<Location> locations = <Location>[];
|
| String unitLibraryUri = null;
|
| String unitUnitUri = null;
|
| @@ -385,7 +451,7 @@ class _UnitIndexRequester {
|
| if (regExp.matchAsPrefix(name) != null) {
|
| unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit);
|
| unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit);
|
| - locations.add(new Location(unitLibraryUri, unitUnitUri,
|
| + locations.add(new Location(context, unitLibraryUri, unitUnitUri,
|
| unitIndex.definedNameOffsets[i], name.length, false));
|
| }
|
| }
|
| @@ -397,7 +463,8 @@ class _UnitIndexRequester {
|
| * Return a list of locations where an element with the given [elementId] has
|
| * relation of the given [kind].
|
| */
|
| - List<Location> getRelations(int elementId, IndexRelationKind kind) {
|
| + List<Location> getRelations(
|
| + AnalysisContext context, int elementId, IndexRelationKind kind) {
|
| // Find the first usage of the element.
|
| int i = _findFirstOccurrence(unitIndex.usedElements, elementId);
|
| if (i == -1) {
|
| @@ -415,6 +482,7 @@ class _UnitIndexRequester {
|
| unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit);
|
| unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit);
|
| locations.add(new Location(
|
| + context,
|
| unitLibraryUri,
|
| unitUnitUri,
|
| unitIndex.usedElementOffsets[i],
|
| @@ -429,14 +497,15 @@ class _UnitIndexRequester {
|
| * Complete with a list of locations where a class members with the given
|
| * [name] is referenced with a qualifier, but is not resolved.
|
| */
|
| - List<Location> getUnresolvedMemberReferences(String name) {
|
| + List<Location> getUnresolvedMemberReferences(
|
| + AnalysisContext context, String name) {
|
| // Find the name ID in the package index.
|
| int nameId = packageRequester.getStringId(name);
|
| if (nameId == -1) {
|
| return const <Location>[];
|
| }
|
| // Find the first usage of the name.
|
| - int i =_findFirstOccurrence(unitIndex.usedNames, nameId);
|
| + int i = _findFirstOccurrence(unitIndex.usedNames, nameId);
|
| if (i == -1) {
|
| return const <Location>[];
|
| }
|
| @@ -444,11 +513,12 @@ class _UnitIndexRequester {
|
| List<Location> locations = <Location>[];
|
| String unitLibraryUri = null;
|
| String unitUnitUri = null;
|
| - for (; i < unitIndex.usedNames.length &&
|
| - unitIndex.usedNames[i] == nameId; i++) {
|
| + for (;
|
| + i < unitIndex.usedNames.length && unitIndex.usedNames[i] == nameId;
|
| + i++) {
|
| unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit);
|
| unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit);
|
| - locations.add(new Location(unitLibraryUri, unitUnitUri,
|
| + locations.add(new Location(context, unitLibraryUri, unitUnitUri,
|
| unitIndex.usedNameOffsets[i], name.length, true));
|
| }
|
| return locations;
|
|
|