Always create DeclarationsTracker in AnalysisServer.
R=brianwilkerson@google.com
Change-Id: I1de49423d921da1fdf78ecd480a26e4577efcfe9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/101480
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index c60be02..4eb8f59 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -149,7 +149,9 @@
ByteStore byteStore;
nd.AnalysisDriverScheduler analysisDriverScheduler;
+
DeclarationsTracker declarationsTracker;
+ DeclarationsTrackerData declarationsTrackerData;
/// The controller for [onAnalysisSetChanged].
final StreamController _onAnalysisSetChangedController =
@@ -202,13 +204,20 @@
}
_analysisPerformanceLogger = new PerformanceLog(sink);
}
+
byteStore = createByteStore(resourceProvider);
+
analysisDriverScheduler = new nd.AnalysisDriverScheduler(
_analysisPerformanceLogger,
driverWatcher: pluginWatcher);
analysisDriverScheduler.status.listen(sendStatusNotificationNew);
analysisDriverScheduler.start();
+ declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
+ declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
+ analysisDriverScheduler.outOfBandWorker =
+ CompletionLibrariesWorker(declarationsTracker);
+
contextManager = new ContextManagerImpl(
resourceProvider,
sdkManager,
@@ -276,27 +285,6 @@
return _onAnalysisStartedController.stream;
}
- void createDeclarationsTracker(void Function(LibraryChange) listener) {
- if (declarationsTracker != null) return;
-
- declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
- declarationsTracker.changes.listen(listener);
-
- _addContextsToDeclarationsTracker();
-
- // Configure the scheduler to run the tracker.
- analysisDriverScheduler.outOfBandWorker =
- CompletionLibrariesWorker(declarationsTracker);
-
- // We might have done running drivers work, so ask the scheduler to check.
- analysisDriverScheduler.notify(null);
- }
-
- void disposeDeclarationsTracker() {
- declarationsTracker = null;
- analysisDriverScheduler.outOfBandWorker = null;
- }
-
/// The socket from which requests are being read has been closed.
void done() {}
@@ -389,10 +377,8 @@
/// Notify the declarations tracker that the file with the given [path] was
/// changed - added, updated, or removed. Schedule processing of the file.
void notifyDeclarationsTracker(String path) {
- if (declarationsTracker != null) {
- declarationsTracker.changeFile(path);
- analysisDriverScheduler.notify(null);
- }
+ declarationsTracker.changeFile(path);
+ analysisDriverScheduler.notify(null);
}
/// Read all files, resolve all URIs, and perform required analysis in
@@ -513,7 +499,7 @@
/// projects/contexts support.
void setAnalysisRoots(String requestId, List<String> includedPaths,
List<String> excludedPaths, Map<String, String> packageRoots) {
- declarationsTracker?.discardContexts();
+ declarationsTracker.discardContexts();
if (notificationManager != null) {
notificationManager.setAnalysisRoots(includedPaths, excludedPaths);
}
@@ -702,11 +688,9 @@
}
void _addContextsToDeclarationsTracker() {
- if (declarationsTracker != null) {
- for (var driver in driverMap.values) {
- declarationsTracker.addContext(driver.analysisContext);
- driver.resetUriResolution();
- }
+ for (var driver in driverMap.values) {
+ declarationsTracker.addContext(driver.analysisContext);
+ driver.resetUriResolution();
}
}
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 53a2d7f..e967188 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -513,7 +513,7 @@
DartdocDirectiveInfo _getDartdocDirectiveInfoFor(ResolvedUnitResult result) {
// TODO(brianwilkerson) Consider moving this to AnalysisServer.
return server.declarationsTracker
- ?.getContext(result.session.analysisContext)
+ .getContext(result.session.analysisContext)
?.dartdocDirectiveInfo ??
new DartdocDirectiveInfo();
}
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index ad3b6d2..26461fc 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -477,13 +477,23 @@
subscriptions.addAll(params.subscriptions);
if (subscriptions.contains(CompletionService.AVAILABLE_SUGGESTION_SETS)) {
- server.createDeclarationsTracker((change) {
+ var data = server.declarationsTrackerData;
+ var soFarLibraries = data.startListening((change) {
server.sendNotification(
- createCompletionAvailableSuggestionsNotification(change),
+ createCompletionAvailableSuggestionsNotification(
+ change.changed,
+ change.removed,
+ ),
);
});
+ server.sendNotification(
+ createCompletionAvailableSuggestionsNotification(
+ soFarLibraries,
+ [],
+ ),
+ );
} else {
- server.disposeDeclarationsTracker();
+ server.declarationsTrackerData.stopListening();
}
return CompletionSetSubscriptionsResult().toResponse(request.id);
diff --git a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
index bbe879f..bee0613 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -68,13 +68,14 @@
/// Convert the [LibraryChange] into the corresponding protocol notification.
protocol.Notification createCompletionAvailableSuggestionsNotification(
- LibraryChange change,
+ List<Library> changed,
+ List<int> removed,
) {
return protocol.CompletionAvailableSuggestionsParams(
- changedLibraries: change.changed.map((library) {
+ changedLibraries: changed.map((library) {
return _protocolAvailableSuggestionSet(library);
}).toList(),
- removedLibraries: change.removed,
+ removedLibraries: removed,
).toNotification();
}
@@ -219,3 +220,55 @@
tracker.doWork();
}
}
+
+class DeclarationsTrackerData {
+ final DeclarationsTracker _tracker;
+
+ /// The set of libraries reported by [_tracker] so far.
+ ///
+ /// We create [_tracker] at the server start, but the completion domain
+ /// should send available declarations only when the corresponding
+ /// subscription is done. OTOH, we don't want the changes stream grow
+ /// infinitely as the same libraries are changed multiple times. So, we drain
+ /// the changes stream in this map, and send it at subscription.
+ final Map<int, Library> _idToLibrary = {};
+
+ /// When the completion domain subscribes for changes, we start redirecting
+ /// changes to this listener.
+ void Function(LibraryChange) _listener = null;
+
+ DeclarationsTrackerData(this._tracker) {
+ _tracker.changes.listen((change) {
+ if (_listener != null) {
+ _listener(change);
+ } else {
+ for (var library in change.changed) {
+ _idToLibrary[library.id] = library;
+ }
+ for (var id in change.removed) {
+ _idToLibrary.remove(id);
+ }
+ }
+ });
+ }
+
+ /// Start listening for available libraries, and return the libraries that
+ /// were accumulated so far.
+ List<Library> startListening(void Function(LibraryChange) listener) {
+ if (_listener != null) {
+ throw StateError('Already listening.');
+ }
+ _listener = listener;
+
+ var accumulatedLibraries = _idToLibrary.values.toList();
+ _idToLibrary.clear();
+ return accumulatedLibraries;
+ }
+
+ void stopListening() {
+ if (_listener == null) {
+ throw StateError('Not listening.');
+ }
+ _listener = null;
+ }
+}