Transition DAS to analysis / idle when setAnalysisRoots with no Dart files.
Bug: https://github.com/dart-lang/sdk/issues/40096
Change-Id: I84b83d374e325f1c3c90be30c5c33ed6007b8849
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136921
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 07829e6..df1d016 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -475,6 +475,7 @@
throw RequestFailure(Response.unsupportedFeature(requestId, e.message));
}
addContextsToDeclarationsTracker();
+ analysisDriverScheduler.transitionToAnalyzingToIdleIfNoFilesToAnalyze();
}
/// Implementation for `analysis.setSubscriptions`.
diff --git a/pkg/analysis_server/test/analysis/update_content_test.dart b/pkg/analysis_server/test/analysis/update_content_test.dart
index ddfe39d..6e794cd 100644
--- a/pkg/analysis_server/test/analysis/update_content_test.dart
+++ b/pkg/analysis_server/test/analysis/update_content_test.dart
@@ -186,8 +186,8 @@
@failingTest
Future<void> test_sendNoticesAfterNopChange() async {
// The errors are empty on the last line.
- createProject();
addTestFile('');
+ createProject();
await server.onAnalysisComplete;
// add an overlay
server.updateContent(
@@ -206,8 +206,8 @@
@failingTest
Future<void> test_sendNoticesAfterNopChange_flushedUnit() async {
// The list of errors is empty on the last line.
- createProject();
addTestFile('');
+ createProject();
await server.onAnalysisComplete;
// add an overlay
server.updateContent(
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index 4640cbb..e966735 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -98,33 +98,64 @@
});
}
- Future test_serverStatusNotifications() {
+ Future test_serverStatusNotifications_hasFile() async {
server.serverServices.add(ServerService.STATUS);
- var pkgFolder = convertPath('/pkg');
- newFolder(pkgFolder);
- newFolder(join(pkgFolder, 'lib'));
- newFile(join(pkgFolder, 'lib', 'test.dart'), content: 'class C {}');
- server.setAnalysisRoots('0', [pkgFolder], [], {});
- // Pump the event queue to make sure the server has finished any
- // analysis.
- return pumpEventQueue(times: 5000).then((_) {
- List<Notification> notifications = channel.notificationsReceived;
- expect(notifications, isNotEmpty);
- // expect at least one notification indicating analysis is in progress
- expect(notifications.any((Notification notification) {
- if (notification.event == SERVER_NOTIFICATION_STATUS) {
- var params = ServerStatusParams.fromNotification(notification);
- if (params.analysis != null) {
- return params.analysis.isAnalyzing;
- }
+
+ newFile('/test/lib/a.dart', content: r'''
+class A {}
+''');
+ server.setAnalysisRoots('0', [convertPath('/test')], [], {});
+
+ // Pump the event queue, so that the server has finished any analysis.
+ await pumpEventQueue(times: 5000);
+
+ var notifications = channel.notificationsReceived;
+ expect(notifications, isNotEmpty);
+
+ // At least one notification indicating analysis is in progress.
+ expect(notifications.any((Notification notification) {
+ if (notification.event == SERVER_NOTIFICATION_STATUS) {
+ var params = ServerStatusParams.fromNotification(notification);
+ if (params.analysis != null) {
+ return params.analysis.isAnalyzing;
}
- return false;
- }), isTrue);
- // the last notification should indicate that analysis is complete
- Notification notification = notifications[notifications.length - 1];
- var params = ServerStatusParams.fromNotification(notification);
- expect(params.analysis.isAnalyzing, isFalse);
- });
+ }
+ return false;
+ }), isTrue);
+
+ // The last notification should indicate that analysis is complete.
+ var notification = notifications[notifications.length - 1];
+ var params = ServerStatusParams.fromNotification(notification);
+ expect(params.analysis.isAnalyzing, isFalse);
+ }
+
+ Future test_serverStatusNotifications_noFiles() async {
+ server.serverServices.add(ServerService.STATUS);
+
+ newFolder('/test');
+ server.setAnalysisRoots('0', [convertPath('/test')], [], {});
+
+ // Pump the event queue, so that the server has finished any analysis.
+ await pumpEventQueue(times: 5000);
+
+ var notifications = channel.notificationsReceived;
+ expect(notifications, isNotEmpty);
+
+ // At least one notification indicating analysis is in progress.
+ expect(notifications.any((Notification notification) {
+ if (notification.event == SERVER_NOTIFICATION_STATUS) {
+ var params = ServerStatusParams.fromNotification(notification);
+ if (params.analysis != null) {
+ return params.analysis.isAnalyzing;
+ }
+ }
+ return false;
+ }), isTrue);
+
+ // The last notification should indicate that analysis is complete.
+ var notification = notifications[notifications.length - 1];
+ var params = ServerStatusParams.fromNotification(notification);
+ expect(params.analysis.isAnalyzing, isFalse);
}
Future<void>
@@ -142,7 +173,7 @@
});
// We respect subscriptions, even for excluded files.
- await server.onAnalysisComplete;
+ await pumpEventQueue();
expect(channel.notificationsReceived.any((notification) {
return notification.event == ANALYSIS_NOTIFICATION_NAVIGATION;
}), isTrue);
@@ -163,7 +194,7 @@
});
// We respect subscriptions, even for excluded files.
- await server.onAnalysisComplete;
+ await pumpEventQueue();
expect(channel.notificationsReceived.any((notification) {
return notification.event == ANALYSIS_NOTIFICATION_NAVIGATION;
}), isTrue);
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 9064ac6..79b998e 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -1943,6 +1943,17 @@
_run();
}
+ /// Usually we transition status to analyzing only if there are files to
+ /// analyze. However when used in the server, there are rare cases when
+ /// analysis roots don't have any Dart files, but for consistency we still
+ /// want to get status to transition to analysis, and back to idle.
+ void transitionToAnalyzingToIdleIfNoFilesToAnalyze() {
+ if (!_hasFilesToAnalyze) {
+ _statusSupport.transitionToAnalyzing();
+ _statusSupport.transitionToIdle();
+ }
+ }
+
/// Return a future that will be completed the next time the status is idle.
///
/// If the status is currently idle, the returned future will be signaled