Split out analysis_servers (#599)
diff --git a/lib/src/analysis_server.dart b/lib/src/analysis_server.dart
index 3259650..a91ee05 100644
--- a/lib/src/analysis_server.dart
+++ b/lib/src/analysis_server.dart
@@ -12,10 +12,8 @@
import 'package:analysis_server_lib/analysis_server_lib.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;
-import 'package:pedantic/pedantic.dart';
import 'common.dart';
-import 'common_server_impl.dart' show BadRequest;
import 'flutter_web.dart';
import 'protos/dart_services.pb.dart' as proto;
import 'pub.dart';
@@ -35,157 +33,6 @@
// Use very long timeouts to ensure that the server has enough time to restart.
const Duration _ANALYSIS_SERVER_TIMEOUT = Duration(seconds: 35);
-class AnalysisServersWrapper {
- AnalysisServersWrapper();
-
- FlutterWebManager _flutterWebManager;
- DartAnalysisServerWrapper _dartAnalysisServer;
- FlutterAnalysisServerWrapper _flutterAnalysisServer;
-
- bool get running =>
- _dartAnalysisServer.analysisServer != null &&
- _flutterAnalysisServer.analysisServer != null;
-
- // If non-null, this value indicates that the server is starting/restarting
- // and holds the time at which that process began. If null, the server is
- // ready to handle requests.
- DateTime _restartingSince = DateTime.now();
-
- bool get isRestarting => (_restartingSince != null);
-
- // If the server has been trying and failing to restart for more than a half
- // hour, something is seriously wrong.
- bool get isHealthy => (_restartingSince == null ||
- DateTime.now().difference(_restartingSince).inMinutes < 30);
-
- Future<void> warmup() async {
- _logger.info('Beginning AnalysisServersWrapper init().');
- _dartAnalysisServer = DartAnalysisServerWrapper();
- _flutterWebManager = FlutterWebManager(SdkManager.flutterSdk);
- _flutterAnalysisServer = FlutterAnalysisServerWrapper(_flutterWebManager);
-
- await _dartAnalysisServer.init();
- _logger.info('Dart analysis server initialized.');
-
- await _flutterAnalysisServer.init();
- _logger.info('Flutter analysis server initialized.');
-
- unawaited(_dartAnalysisServer.onExit.then((int code) {
- _logger.severe('dartAnalysisServer exited, code: $code');
- if (code != 0) {
- exit(code);
- }
- }));
-
- unawaited(_flutterAnalysisServer.onExit.then((int code) {
- _logger.severe('flutterAnalysisServer exited, code: $code');
- if (code != 0) {
- exit(code);
- }
- }));
-
- _restartingSince = null;
-
- return Future.wait(<Future<dynamic>>[
- _flutterWebManager.warmup(),
- _flutterAnalysisServer.warmup(),
- _dartAnalysisServer.warmup(),
- ]);
- }
-
- Future<void> _restart() async {
- _logger.warning('Restarting');
- await shutdown();
- _logger.info('shutdown');
-
- await warmup();
- _logger.warning('Restart complete');
- }
-
- Future<dynamic> shutdown() {
- _restartingSince = DateTime.now();
-
- return Future.wait(<Future<dynamic>>[
- _flutterWebManager.dispose(),
- _flutterAnalysisServer.shutdown(),
- _dartAnalysisServer.shutdown(),
- ]);
- }
-
- AnalysisServerWrapper _getCorrectAnalysisServer(String source) {
- final imports = getAllImportsFor(source);
- return _flutterWebManager.usesFlutterWeb(imports)
- ? _flutterAnalysisServer
- : _dartAnalysisServer;
- }
-
- Future<proto.AnalysisResults> analyze(String source) => _perfLogAndRestart(
- source,
- () => _getCorrectAnalysisServer(source).analyze(source),
- 'analysis',
- 'Error during analyze on "$source"');
-
- Future<proto.CompleteResponse> complete(String source, int offset) =>
- _perfLogAndRestart(
- source,
- () => _getCorrectAnalysisServer(source).complete(source, offset),
- 'completions',
- 'Error during complete on "$source" at $offset');
-
- Future<proto.FixesResponse> getFixes(String source, int offset) =>
- _perfLogAndRestart(
- source,
- () => _getCorrectAnalysisServer(source).getFixes(source, offset),
- 'fixes',
- 'Error during fixes on "$source" at $offset');
-
- Future<proto.AssistsResponse> getAssists(String source, int offset) =>
- _perfLogAndRestart(
- source,
- () => _getCorrectAnalysisServer(source).getAssists(source, offset),
- 'assists',
- 'Error during assists on "$source" at $offset');
-
- Future<proto.FormatResponse> format(String source, int offset) =>
- _perfLogAndRestart(
- source,
- () => _getCorrectAnalysisServer(source).format(source, offset),
- 'format',
- 'Error during format on "$source" at $offset');
-
- Future<Map<String, String>> dartdoc(String source, int offset) =>
- _perfLogAndRestart(
- source,
- () => _getCorrectAnalysisServer(source).dartdoc(source, offset),
- 'dartdoc',
- 'Error during dartdoc on "$source" at $offset');
-
- Future<T> _perfLogAndRestart<T>(String source, Future<T> Function() body,
- String action, String errorDescription) async {
- await _checkPackageReferences(source);
- try {
- final watch = Stopwatch()..start();
- final response = await body();
- _logger.info('PERF: Computed $action in ${watch.elapsedMilliseconds}ms.');
- return response;
- } catch (e, st) {
- _logger.severe(errorDescription, e, st);
- await _restart();
- rethrow;
- }
- }
-
- /// Check that the set of packages referenced is valid.
- Future<void> _checkPackageReferences(String source) async {
- final imports = getAllImportsFor(source);
-
- if (_flutterWebManager.hasUnsupportedImport(imports)) {
- throw BadRequest(
- 'Unsupported input: ${_flutterWebManager.getUnsupportedImport(imports)}');
- }
- }
-}
-
class DartAnalysisServerWrapper extends AnalysisServerWrapper {
Directory _tempProject;
DartAnalysisServerWrapper() : super(SdkManager.sdk.sdkPath);
diff --git a/lib/src/analysis_servers.dart b/lib/src/analysis_servers.dart
new file mode 100644
index 0000000..766d80d
--- /dev/null
+++ b/lib/src/analysis_servers.dart
@@ -0,0 +1,172 @@
+// Copyright (c) 2020, 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.
+
+/// A wrapper around an analysis server instance
+library services.analysis_servers;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:logging/logging.dart';
+import 'package:pedantic/pedantic.dart';
+
+import 'analysis_server.dart';
+import 'common_server_impl.dart' show BadRequest;
+import 'flutter_web.dart';
+import 'protos/dart_services.pb.dart' as proto;
+import 'pub.dart';
+import 'sdk_manager.dart';
+
+final Logger _logger = Logger('analysis_servers');
+
+class AnalysisServersWrapper {
+ AnalysisServersWrapper();
+
+ FlutterWebManager _flutterWebManager;
+ DartAnalysisServerWrapper _dartAnalysisServer;
+ FlutterAnalysisServerWrapper _flutterAnalysisServer;
+
+ bool get running =>
+ _dartAnalysisServer.analysisServer != null &&
+ _flutterAnalysisServer.analysisServer != null;
+
+ // If non-null, this value indicates that the server is starting/restarting
+ // and holds the time at which that process began. If null, the server is
+ // ready to handle requests.
+ DateTime _restartingSince = DateTime.now();
+
+ bool get isRestarting => (_restartingSince != null);
+
+ // If the server has been trying and failing to restart for more than a half
+ // hour, something is seriously wrong.
+ bool get isHealthy => (_restartingSince == null ||
+ DateTime.now().difference(_restartingSince).inMinutes < 30);
+
+ Future<void> warmup() async {
+ _logger.info('Beginning AnalysisServersWrapper init().');
+ _dartAnalysisServer = DartAnalysisServerWrapper();
+ _flutterWebManager = FlutterWebManager(SdkManager.flutterSdk);
+ _flutterAnalysisServer = FlutterAnalysisServerWrapper(_flutterWebManager);
+
+ await _dartAnalysisServer.init();
+ _logger.info('Dart analysis server initialized.');
+
+ await _flutterAnalysisServer.init();
+ _logger.info('Flutter analysis server initialized.');
+
+ unawaited(_dartAnalysisServer.onExit.then((int code) {
+ _logger.severe('dartAnalysisServer exited, code: $code');
+ if (code != 0) {
+ exit(code);
+ }
+ }));
+
+ unawaited(_flutterAnalysisServer.onExit.then((int code) {
+ _logger.severe('flutterAnalysisServer exited, code: $code');
+ if (code != 0) {
+ exit(code);
+ }
+ }));
+
+ _restartingSince = null;
+
+ return Future.wait(<Future<dynamic>>[
+ _flutterWebManager.warmup(),
+ _flutterAnalysisServer.warmup(),
+ _dartAnalysisServer.warmup(),
+ ]);
+ }
+
+ Future<void> _restart() async {
+ _logger.warning('Restarting');
+ await shutdown();
+ _logger.info('shutdown');
+
+ await warmup();
+ _logger.warning('Restart complete');
+ }
+
+ Future<dynamic> shutdown() {
+ _restartingSince = DateTime.now();
+
+ return Future.wait(<Future<dynamic>>[
+ _flutterWebManager.dispose(),
+ _flutterAnalysisServer.shutdown(),
+ _dartAnalysisServer.shutdown(),
+ ]);
+ }
+
+ AnalysisServerWrapper _getCorrectAnalysisServer(String source) {
+ final imports = getAllImportsFor(source);
+ return _flutterWebManager.usesFlutterWeb(imports)
+ ? _flutterAnalysisServer
+ : _dartAnalysisServer;
+ }
+
+ Future<proto.AnalysisResults> analyze(String source) => _perfLogAndRestart(
+ source,
+ () => _getCorrectAnalysisServer(source).analyze(source),
+ 'analysis',
+ 'Error during analyze on "$source"');
+
+ Future<proto.CompleteResponse> complete(String source, int offset) =>
+ _perfLogAndRestart(
+ source,
+ () => _getCorrectAnalysisServer(source).complete(source, offset),
+ 'completions',
+ 'Error during complete on "$source" at $offset');
+
+ Future<proto.FixesResponse> getFixes(String source, int offset) =>
+ _perfLogAndRestart(
+ source,
+ () => _getCorrectAnalysisServer(source).getFixes(source, offset),
+ 'fixes',
+ 'Error during fixes on "$source" at $offset');
+
+ Future<proto.AssistsResponse> getAssists(String source, int offset) =>
+ _perfLogAndRestart(
+ source,
+ () => _getCorrectAnalysisServer(source).getAssists(source, offset),
+ 'assists',
+ 'Error during assists on "$source" at $offset');
+
+ Future<proto.FormatResponse> format(String source, int offset) =>
+ _perfLogAndRestart(
+ source,
+ () => _getCorrectAnalysisServer(source).format(source, offset),
+ 'format',
+ 'Error during format on "$source" at $offset');
+
+ Future<Map<String, String>> dartdoc(String source, int offset) =>
+ _perfLogAndRestart(
+ source,
+ () => _getCorrectAnalysisServer(source).dartdoc(source, offset),
+ 'dartdoc',
+ 'Error during dartdoc on "$source" at $offset');
+
+ Future<T> _perfLogAndRestart<T>(String source, Future<T> Function() body,
+ String action, String errorDescription) async {
+ await _checkPackageReferences(source);
+ try {
+ final watch = Stopwatch()..start();
+ final response = await body();
+ _logger.info('PERF: Computed $action in ${watch.elapsedMilliseconds}ms.');
+ return response;
+ } catch (e, st) {
+ _logger.severe(errorDescription, e, st);
+ await _restart();
+ rethrow;
+ }
+ }
+
+ /// Check that the set of packages referenced is valid.
+ Future<void> _checkPackageReferences(String source) async {
+ final imports = getAllImportsFor(source);
+
+ if (_flutterWebManager.hasUnsupportedImport(imports)) {
+ throw BadRequest(
+ 'Unsupported input: ${_flutterWebManager.getUnsupportedImport(imports)}');
+ }
+ }
+}
diff --git a/lib/src/common_server_impl.dart b/lib/src/common_server_impl.dart
index c383277..e523307 100644
--- a/lib/src/common_server_impl.dart
+++ b/lib/src/common_server_impl.dart
@@ -12,7 +12,7 @@
import 'package:pedantic/pedantic.dart';
import '../version.dart';
-import 'analysis_server.dart';
+import 'analysis_servers.dart';
import 'common.dart';
import 'compiler.dart';
import 'protos/dart_services.pb.dart' as proto;
diff --git a/test/flutter_analysis_server_test.dart b/test/flutter_analysis_server_test.dart
index 92cfaee..9791eca 100644
--- a/test/flutter_analysis_server_test.dart
+++ b/test/flutter_analysis_server_test.dart
@@ -6,6 +6,7 @@
import 'package:dart_services/src/common.dart';
import 'package:dart_services/src/analysis_server.dart';
+import 'package:dart_services/src/analysis_servers.dart';
import 'package:dart_services/src/common_server_impl.dart';
import 'package:dart_services/src/common_server_api.dart';
import 'package:dart_services/src/flutter_web.dart';