mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
Listen for context add/remove and unit invalidation to update the index.
R=brianwilkerson@google.com BUG= Review URL: https://codereview.chromium.org/1783503004 .
This commit is contained in:
parent
9292d1bc2b
commit
4d48fa56d0
7 changed files with 108 additions and 36 deletions
|
@ -39,6 +39,7 @@ import 'package:analyzer/src/generated/source_io.dart';
|
|||
import 'package:analyzer/src/generated/utilities_general.dart';
|
||||
import 'package:analyzer/src/task/dart.dart';
|
||||
import 'package:analyzer/src/util/glob.dart';
|
||||
import 'package:analyzer/task/dart.dart';
|
||||
import 'package:plugin/plugin.dart';
|
||||
|
||||
typedef void OptionUpdater(AnalysisOptionsImpl options);
|
||||
|
@ -83,7 +84,7 @@ class AnalysisServer {
|
|||
* a 1 millisecond delay so that the VM and dart:io can deliver content
|
||||
* to stdin. This should be removed once the underlying problem is fixed.
|
||||
*/
|
||||
static int performOperationDelayFreqency = 25;
|
||||
static int performOperationDelayFrequency = 25;
|
||||
|
||||
/**
|
||||
* The options of this server instance.
|
||||
|
@ -354,6 +355,7 @@ class AnalysisServer {
|
|||
_performance = performanceAfterStartup;
|
||||
});
|
||||
});
|
||||
_setupIndexInvalidation();
|
||||
Notification notification =
|
||||
new ServerConnectedParams(VERSION).toNotification();
|
||||
channel.sendNotification(notification);
|
||||
|
@ -675,23 +677,6 @@ class AnalysisServer {
|
|||
return context.getErrors(source);
|
||||
}
|
||||
|
||||
// TODO(brianwilkerson) Add the following method after 'prioritySources' has
|
||||
// been added to InternalAnalysisContext.
|
||||
// /**
|
||||
// * Return a list containing the full names of all of the sources that are
|
||||
// * priority sources.
|
||||
// */
|
||||
// List<String> getPriorityFiles() {
|
||||
// List<String> priorityFiles = new List<String>();
|
||||
// folderMap.values.forEach((ContextDirectory directory) {
|
||||
// InternalAnalysisContext context = directory.context;
|
||||
// context.prioritySources.forEach((Source source) {
|
||||
// priorityFiles.add(source.fullName);
|
||||
// });
|
||||
// });
|
||||
// return priorityFiles;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns resolved [AstNode]s at the given [offset] of the given [file].
|
||||
*
|
||||
|
@ -709,6 +694,23 @@ class AnalysisServer {
|
|||
return nodes;
|
||||
}
|
||||
|
||||
// TODO(brianwilkerson) Add the following method after 'prioritySources' has
|
||||
// been added to InternalAnalysisContext.
|
||||
// /**
|
||||
// * Return a list containing the full names of all of the sources that are
|
||||
// * priority sources.
|
||||
// */
|
||||
// List<String> getPriorityFiles() {
|
||||
// List<String> priorityFiles = new List<String>();
|
||||
// folderMap.values.forEach((ContextDirectory directory) {
|
||||
// InternalAnalysisContext context = directory.context;
|
||||
// context.prioritySources.forEach((Source source) {
|
||||
// priorityFiles.add(source.fullName);
|
||||
// });
|
||||
// });
|
||||
// return priorityFiles;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns resolved [CompilationUnit]s of the Dart file with the given [path].
|
||||
*
|
||||
|
@ -1452,14 +1454,42 @@ class AnalysisServer {
|
|||
*/
|
||||
int now = new DateTime.now().millisecondsSinceEpoch;
|
||||
if (now > _nextPerformOperationDelayTime &&
|
||||
performOperationDelayFreqency > 0) {
|
||||
_nextPerformOperationDelayTime = now + performOperationDelayFreqency;
|
||||
performOperationDelayFrequency > 0) {
|
||||
_nextPerformOperationDelayTime = now + performOperationDelayFrequency;
|
||||
new Future.delayed(new Duration(milliseconds: 1), performOperation);
|
||||
} else {
|
||||
new Future(performOperation);
|
||||
}
|
||||
performOperationPending = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen for context events and invalidate index.
|
||||
*
|
||||
* It is possible that this method will do more in the future, e.g. listening
|
||||
* for summary information and linking pre-indexed packages into the index,
|
||||
* but for now we only invalidate project specific index information.
|
||||
*/
|
||||
void _setupIndexInvalidation() {
|
||||
if (index2 == null) {
|
||||
return;
|
||||
}
|
||||
onContextsChanged.listen((ContextsChangedEvent event) {
|
||||
for (AnalysisContext context in event.added) {
|
||||
context
|
||||
.onResultChanged(RESOLVED_UNIT)
|
||||
.listen((ResultChangedEvent event) {
|
||||
if (event.wasInvalidated) {
|
||||
LibrarySpecificUnit target = event.target;
|
||||
index2.removeUnit(event.context, target.library, target.unit);
|
||||
}
|
||||
});
|
||||
}
|
||||
for (AnalysisContext context in event.removed) {
|
||||
index2.removeContext(context);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class AnalysisServerOptions {
|
||||
|
@ -1662,7 +1692,7 @@ class ServerPerformance {
|
|||
int slowRequestCount = 0;
|
||||
|
||||
/**
|
||||
* Log performation information about the given request.
|
||||
* Log performance information about the given request.
|
||||
*/
|
||||
void logRequest(Request request) {
|
||||
++requestCount;
|
||||
|
|
|
@ -343,7 +343,7 @@ class Driver implements ServerStarter {
|
|||
// TODO (danrubel) Remove this workaround
|
||||
// once the underlying VM and dart:io issue has been fixed.
|
||||
if (results[INTERNAL_DELAY_FREQUENCY] != null) {
|
||||
AnalysisServer.performOperationDelayFreqency =
|
||||
AnalysisServer.performOperationDelayFrequency =
|
||||
int.parse(results[INTERNAL_DELAY_FREQUENCY], onError: (_) => 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -94,6 +94,14 @@ class Index2 {
|
|||
_contextIndexMap.remove(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove index information about the unit in the given [context].
|
||||
*/
|
||||
void removeUnit(
|
||||
AnalysisContext context, Source librarySource, Source unitSource) {
|
||||
_contextIndexMap[context]?.removeUnit(librarySource, unitSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the [_ContextIndex] instance for the given [context].
|
||||
*/
|
||||
|
@ -207,8 +215,7 @@ class _ContextIndex {
|
|||
*/
|
||||
Future<List<Location>> getDefinedNames(
|
||||
RegExp regExp, IndexNameKind kind) async {
|
||||
return _mergeLocations((PackageIndex index) {
|
||||
_PackageIndexRequester requester = new _PackageIndexRequester(index);
|
||||
return _mergeLocations((_PackageIndexRequester requester) {
|
||||
return requester.getDefinedNames(context, regExp, kind);
|
||||
});
|
||||
}
|
||||
|
@ -218,8 +225,7 @@ class _ContextIndex {
|
|||
* of the given [kind].
|
||||
*/
|
||||
Future<List<Location>> getRelations(Element element, IndexRelationKind kind) {
|
||||
return _mergeLocations((PackageIndex index) {
|
||||
_PackageIndexRequester requester = new _PackageIndexRequester(index);
|
||||
return _mergeLocations((_PackageIndexRequester requester) {
|
||||
return requester.getRelations(context, element, kind);
|
||||
});
|
||||
}
|
||||
|
@ -229,8 +235,7 @@ class _ContextIndex {
|
|||
* [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 _mergeLocations((_PackageIndexRequester requester) {
|
||||
return requester.getUnresolvedMemberReferences(context, name);
|
||||
});
|
||||
}
|
||||
|
@ -250,6 +255,14 @@ class _ContextIndex {
|
|||
indexMap[key] = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove index information about the unit.
|
||||
*/
|
||||
void removeUnit(Source librarySource, Source unitSource) {
|
||||
String key = _getUnitKeyForSource(librarySource, unitSource);
|
||||
indexMap.remove(key);
|
||||
}
|
||||
|
||||
String _getUnitKeyForElement(CompilationUnitElement unitElement) {
|
||||
Source librarySource = unitElement.library.source;
|
||||
Source unitSource = unitElement.source;
|
||||
|
@ -263,10 +276,11 @@ class _ContextIndex {
|
|||
}
|
||||
|
||||
Future<List<Location>> _mergeLocations(
|
||||
List<Location> callback(PackageIndex index)) async {
|
||||
List<Location> callback(_PackageIndexRequester requester)) async {
|
||||
List<Location> locations = <Location>[];
|
||||
for (PackageIndex index in indexMap.values) {
|
||||
List<Location> indexLocations = callback(index);
|
||||
_PackageIndexRequester requester = new _PackageIndexRequester(index);
|
||||
List<Location> indexLocations = callback(requester);
|
||||
locations.addAll(indexLocations);
|
||||
}
|
||||
return locations;
|
||||
|
|
|
@ -22,10 +22,9 @@ import 'package:analyzer/src/summary/idl.dart';
|
|||
* A [SearchEngine] implementation.
|
||||
*/
|
||||
class SearchEngineImpl2 implements SearchEngine {
|
||||
final AnalysisContext context;
|
||||
final Index2 _index;
|
||||
|
||||
SearchEngineImpl2(this.context, this._index);
|
||||
SearchEngineImpl2(this._index);
|
||||
|
||||
@override
|
||||
Future<List<SearchMatch>> searchAllSubtypes(ClassElement type) async {
|
||||
|
@ -111,7 +110,7 @@ class SearchEngineImpl2 implements SearchEngine {
|
|||
|
||||
SearchMatch _newMatchForLocation(Location location, MatchKind kind) =>
|
||||
new SearchMatch(
|
||||
context,
|
||||
location.context,
|
||||
location.libraryUri,
|
||||
location.unitUri,
|
||||
kind,
|
||||
|
@ -176,6 +175,7 @@ class SearchEngineImpl2 implements SearchEngine {
|
|||
List<SearchMatch> matches = <SearchMatch>[];
|
||||
LibraryElement libraryElement = element.library;
|
||||
Source librarySource = libraryElement.source;
|
||||
AnalysisContext context = libraryElement.context;
|
||||
for (CompilationUnitElement unitElement in libraryElement.units) {
|
||||
Source unitSource = unitElement.source;
|
||||
CompilationUnit unit =
|
||||
|
@ -193,6 +193,7 @@ class SearchEngineImpl2 implements SearchEngine {
|
|||
List<SearchMatch> matches = <SearchMatch>[];
|
||||
LibraryElement libraryElement = element.library;
|
||||
Source librarySource = libraryElement.source;
|
||||
AnalysisContext context = libraryElement.context;
|
||||
for (CompilationUnitElement unitElement in libraryElement.parts) {
|
||||
Source unitSource = unitElement.source;
|
||||
CompilationUnit unit =
|
||||
|
@ -237,6 +238,7 @@ class SearchEngineImpl2 implements SearchEngine {
|
|||
List<SearchMatch> matches = <SearchMatch>[];
|
||||
LibraryElement libraryElement = element.library;
|
||||
Source librarySource = libraryElement.source;
|
||||
AnalysisContext context = libraryElement.context;
|
||||
for (CompilationUnitElement unitElement in libraryElement.units) {
|
||||
Source unitSource = unitElement.source;
|
||||
CompilationUnit unit =
|
||||
|
|
|
@ -1707,7 +1707,7 @@ class GetHandler {
|
|||
// TODO(brianwilkerson) Add items for the SDK contexts (currently only one).
|
||||
buffer.write('</p>');
|
||||
|
||||
int freq = AnalysisServer.performOperationDelayFreqency;
|
||||
int freq = AnalysisServer.performOperationDelayFrequency;
|
||||
String delay = freq > 0 ? '1 ms every $freq ms' : 'off';
|
||||
|
||||
buffer.write('<p><b>Performance Data</b></p>');
|
||||
|
|
|
@ -197,12 +197,38 @@ class A {}
|
|||
RegExp regExp = new RegExp(r'^A$');
|
||||
expect(await index.getDefinedNames(regExp, IndexNameKind.topLevel),
|
||||
hasLength(1));
|
||||
// remove the context - no
|
||||
// remove the context - no top-level declarations
|
||||
index.removeContext(context);
|
||||
expect(
|
||||
await index.getDefinedNames(regExp, IndexNameKind.topLevel), isEmpty);
|
||||
}
|
||||
|
||||
test_removeUnit() async {
|
||||
RegExp regExp = new RegExp(r'^[AB]$');
|
||||
Source sourceA = addSource('/a.dart', 'class A {}');
|
||||
Source sourceB = addSource('/b.dart', 'class B {}');
|
||||
CompilationUnit unitA = resolveLibraryUnit(sourceA);
|
||||
CompilationUnit unitB = resolveLibraryUnit(sourceB);
|
||||
index.indexUnit(unitA);
|
||||
index.indexUnit(unitB);
|
||||
{
|
||||
List<Location> locations =
|
||||
await index.getDefinedNames(regExp, IndexNameKind.topLevel);
|
||||
expect(locations, hasLength(2));
|
||||
expect(locations.map((l) => l.libraryUri),
|
||||
unorderedEquals([sourceA.uri.toString(), sourceB.uri.toString()]));
|
||||
}
|
||||
// remove a.dart - no a.dart location
|
||||
index.removeUnit(context, sourceA, sourceA);
|
||||
{
|
||||
List<Location> locations =
|
||||
await index.getDefinedNames(regExp, IndexNameKind.topLevel);
|
||||
expect(locations, hasLength(1));
|
||||
expect(locations.map((l) => l.libraryUri),
|
||||
unorderedEquals([sourceB.uri.toString()]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given list of [locations] has a [Location] corresponding
|
||||
* to the [element].
|
||||
|
|
|
@ -70,7 +70,7 @@ class SearchEngineImpl2Test extends AbstractSingleUnitTest {
|
|||
void setUp() {
|
||||
super.setUp();
|
||||
index = createMemoryIndex2();
|
||||
searchEngine = new SearchEngineImpl2(context, index);
|
||||
searchEngine = new SearchEngineImpl2(index);
|
||||
}
|
||||
|
||||
test_searchAllSubtypes() async {
|
||||
|
|
Loading…
Reference in a new issue