Add support for intermittent filesystems to the analysis server, this PR is a synced version of Devons PR https://dart-review.googlesource.com/c/sdk/+/72980, without the DAS protocol change.
Change-Id: I6ad1d423c2616ae31fc3f5954782d05e3d8adbda
Reviewed-on: https://dart-review.googlesource.com/73689
Commit-Queue: Jaime Wren <jwren@google.com>
Reviewed-by: Jaime Wren <jwren@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Devon Carew <devoncarew@google.com>
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 9b26c7f..2069432 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -38,6 +38,7 @@
import 'package:analysis_server/src/plugin/plugin_watcher.dart';
import 'package:analysis_server/src/protocol_server.dart' as server;
import 'package:analysis_server/src/search/search_domain.dart';
+import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
import 'package:analysis_server/src/server/diagnostic_server.dart';
import 'package:analysis_server/src/services/correction/namespace.dart';
import 'package:analysis_server/src/services/search/element_visitors.dart';
@@ -338,6 +339,8 @@
*/
DiagnosticServer diagnosticServer;
+ final DetachableFileSystemManager detachableFileSystemManager;
+
/**
* Initialize a newly created server to receive requests from and send
* responses to the given [channel].
@@ -347,12 +350,17 @@
* exceptions to show up in unit tests, but it should be set to false when
* running a full analysis server.
*/
- AnalysisServer(this.channel, this.resourceProvider, this.options,
- this.sdkManager, this.instrumentationService,
- {this.diagnosticServer,
- ResolverProvider fileResolverProvider: null,
- ResolverProvider packageResolverProvider: null})
- : notificationManager =
+ AnalysisServer(
+ this.channel,
+ this.resourceProvider,
+ this.options,
+ this.sdkManager,
+ this.instrumentationService, {
+ this.diagnosticServer,
+ ResolverProvider fileResolverProvider: null,
+ ResolverProvider packageResolverProvider: null,
+ this.detachableFileSystemManager: null,
+ }) : notificationManager =
new NotificationManager(channel, resourceProvider) {
_performance = performanceDuringStartup;
@@ -1006,7 +1014,7 @@
return contextManager.isInAnalysisRoot(file);
}
- Future<void> shutdown() async {
+ Future<void> shutdown() {
running = false;
if (options.analytics != null) {
@@ -1017,12 +1025,18 @@
});
}
+ if (options.enableUXExperiment2) {
+ detachableFileSystemManager?.dispose();
+ }
+
// Defer closing the channel and shutting down the instrumentation server so
// that the shutdown response can be sent and logged.
new Future(() {
instrumentationService.shutdown();
channel.close();
});
+
+ return new Future.value();
}
/**
@@ -1147,7 +1161,7 @@
return flutterServices[service]?.contains(file) ?? false;
}
- _scheduleAnalysisImplementedNotification() async {
+ Future<void> _scheduleAnalysisImplementedNotification() async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
Set<String> files = analysisServices[AnalysisService.IMPLEMENTED];
@@ -1197,6 +1211,12 @@
* the priority files' containing directory.
*/
bool enableUXExperiment1 = false;
+
+ /**
+ * User Experience, Experiment #2. This experiment introduces the notion of an
+ * intermittent file system.
+ */
+ bool enableUXExperiment2 = false;
}
/**
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 79c4663..8cfedbb 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -384,9 +384,17 @@
return new Response.invalidFilePathFormat(request, path);
}
}
- // continue in server
- server.setAnalysisRoots(request.id, includedPathList, excludedPathList,
- params.packageRoots ?? <String, String>{});
+ Map<String, String> packageRoots =
+ params.packageRoots ?? <String, String>{};
+
+ if (server.options.enableUXExperiment2 &&
+ server.detachableFileSystemManager != null) {
+ server.detachableFileSystemManager.setAnalysisRoots(
+ request.id, includedPathList, excludedPathList, packageRoots);
+ } else {
+ server.setAnalysisRoots(
+ request.id, includedPathList, excludedPathList, packageRoots);
+ }
return new AnalysisSetAnalysisRootsResult().toResponse(request.id);
}
diff --git a/pkg/analysis_server/lib/src/server/detachable_filesystem_manager.dart b/pkg/analysis_server/lib/src/server/detachable_filesystem_manager.dart
new file mode 100644
index 0000000..dc2cead
--- /dev/null
+++ b/pkg/analysis_server/lib/src/server/detachable_filesystem_manager.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/analysis_server.dart';
+
+/**
+ * A class that can be used to confirm an analysis server instance to better
+ * support intermittent file systems.
+ *
+ * See also [AnalysisServerOptions.detachableFileSystemManager].
+ */
+abstract class DetachableFileSystemManager {
+ /**
+ * Indicate that the [DetachableFileSystemManager] and the containing analysis
+ * server are being shut down.
+ */
+ void dispose();
+
+ /**
+ * Forward on the 'analysis.setAnalysisRoots' request.
+ *
+ * This class can choose to pass through all [setAnalysisRoots] calls to the
+ * underlying analysis server, it can choose to modify the given
+ * [includedPaths] and other parameters, or it could choose to delays calls to
+ * [setAnalysisRoots].
+ */
+ void setAnalysisRoots(String requestId, List<String> includedPaths,
+ List<String> excludedPaths, Map<String, String> packageRoots);
+
+ /**
+ * Called exactly once before any calls to [setAnalysisRoots].
+ */
+ void setAnalysisServer(AnalysisServer server);
+}
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 2fbce49..0ee7c49 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -7,6 +7,7 @@
import 'dart:math';
import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
import 'package:analysis_server/src/server/dev_server.dart';
import 'package:analysis_server/src/server/diagnostic_server.dart';
import 'package:analysis_server/src/server/http_server.dart';
@@ -272,6 +273,12 @@
static const String UX_EXPERIMENT_1 = "ux-experiment-1";
/**
+ * User Experience, Experiment #2. This experiment introduces the notion of an
+ * intermittent file system.
+ */
+ static const String UX_EXPERIMENT_2 = "ux-experiment-2";
+
+ /**
* The instrumentation server that is to be used by the analysis server.
*/
InstrumentationServer instrumentationServer;
@@ -288,6 +295,12 @@
*/
ResolverProvider packageResolverProvider;
+ /***
+ * An optional manager to handle file systems which may not always be
+ * available.
+ */
+ DetachableFileSystemManager detachableFileSystemManager;
+
SocketServer socketServer;
HttpAnalysisServer httpServer;
@@ -316,6 +329,7 @@
analysisServerOptions.cacheFolder = results[CACHE_FOLDER];
analysisServerOptions.useFastaParser = results[USE_FASTA_PARSER];
analysisServerOptions.enableUXExperiment1 = results[UX_EXPERIMENT_1];
+ analysisServerOptions.enableUXExperiment2 = results[UX_EXPERIMENT_2];
bool disableAnalyticsForSession = results[SUPPRESS_ANALYTICS_FLAG];
if (results.wasParsed(TRAIN_USING)) {
@@ -439,7 +453,8 @@
instrumentationService,
diagnosticServer,
fileResolverProvider,
- packageResolverProvider);
+ packageResolverProvider,
+ detachableFileSystemManager);
httpServer = new HttpAnalysisServer(socketServer);
diagnosticServer.httpServer = httpServer;
@@ -473,6 +488,8 @@
}
await instrumentationService.shutdown();
+ socketServer.analysisServer.shutdown();
+
try {
tempDriverDir.deleteSync(recursive: true);
} catch (_) {
@@ -487,10 +504,12 @@
stdioServer.serveStdio().then((_) async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
+
if (serve_http) {
httpServer.close();
}
await instrumentationService.shutdown();
+ socketServer.analysisServer.shutdown();
exit(0);
});
},
@@ -601,6 +620,11 @@
"this experiment changes the notion of analysis roots and priority "
"files.",
hide: true);
+ parser.addFlag(UX_EXPERIMENT_2,
+ help: "User Experience, Experiment #2, "
+ "this experiment introduces the notion of an intermittent file "
+ "system.",
+ hide: true);
return parser;
}
diff --git a/pkg/analysis_server/lib/src/socket_server.dart b/pkg/analysis_server/lib/src/socket_server.dart
index 250c072..4fd78db 100644
--- a/pkg/analysis_server/lib/src/socket_server.dart
+++ b/pkg/analysis_server/lib/src/socket_server.dart
@@ -6,6 +6,7 @@
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/channel/channel.dart';
+import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
import 'package:analysis_server/src/server/diagnostic_server.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
@@ -31,6 +32,7 @@
final DiagnosticServer diagnosticServer;
final ResolverProvider fileResolverProvider;
final ResolverProvider packageResolverProvider;
+ final DetachableFileSystemManager detachableFileSystemManager;
/**
* The analysis server that was created when a client established a
@@ -45,7 +47,8 @@
this.instrumentationService,
this.diagnosticServer,
this.fileResolverProvider,
- this.packageResolverProvider);
+ this.packageResolverProvider,
+ this.detachableFileSystemManager);
/**
* Create an analysis server which will communicate with the client using the
@@ -75,10 +78,17 @@
'File read mode was set to the unknown mode: $analysisServerOptions.fileReadMode');
}
- analysisServer = new AnalysisServer(serverChannel, resourceProvider,
- analysisServerOptions, sdkManager, instrumentationService,
- diagnosticServer: diagnosticServer,
- fileResolverProvider: fileResolverProvider,
- packageResolverProvider: packageResolverProvider);
+ analysisServer = new AnalysisServer(
+ serverChannel,
+ resourceProvider,
+ analysisServerOptions,
+ sdkManager,
+ instrumentationService,
+ diagnosticServer: diagnosticServer,
+ fileResolverProvider: fileResolverProvider,
+ packageResolverProvider: packageResolverProvider,
+ detachableFileSystemManager: detachableFileSystemManager,
+ );
+ detachableFileSystemManager?.setAnalysisServer(analysisServer);
}
}
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 7fc00fd..4628c6f 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -1307,6 +1307,14 @@
diagnosticsSite.socketServer.analysisServerOptions.useFastaParser));
buf.writeln(writeOption('Instrumentation enabled',
AnalysisEngine.instance.instrumentationService.isActive));
+ bool uxExp1 =
+ diagnosticsSite.socketServer.analysisServerOptions.enableUXExperiment1;
+ bool uxExp2 =
+ diagnosticsSite.socketServer.analysisServerOptions.enableUXExperiment2;
+ if (uxExp1 || uxExp2) {
+ buf.writeln(writeOption('UX Experiment 1', uxExp1));
+ buf.writeln(writeOption('ux Experiment 2', uxExp2));
+ }
buf.writeln(writeOption('Server process ID', pid));
buf.writeln('</div>');
diff --git a/pkg/analysis_server/lib/starter.dart b/pkg/analysis_server/lib/starter.dart
index 5059a59..aa4a30e 100644
--- a/pkg/analysis_server/lib/starter.dart
+++ b/pkg/analysis_server/lib/starter.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
import 'package:analysis_server/src/server/driver.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/plugin/resolver_provider.dart';
@@ -19,6 +20,12 @@
*/
factory ServerStarter() = Driver;
+ /***
+ * An optional manager to handle file systems which may not always be
+ * available.
+ */
+ void set detachableFileSystemManager(DetachableFileSystemManager manager);
+
/**
* Set the file resolver provider used to override the way file URI's
* are resolved in some contexts. The provider should return `null` if the
diff --git a/pkg/analysis_server/test/socket_server_test.dart b/pkg/analysis_server/test/socket_server_test.dart
index 931d87e7..d6957be 100644
--- a/pkg/analysis_server/test/socket_server_test.dart
+++ b/pkg/analysis_server/test/socket_server_test.dart
@@ -117,6 +117,7 @@
InstrumentationService.NULL_SERVICE,
null,
null,
+ null,
null);
}
}