afcfbbeba8
(Part of https://github.com/dart-lang/sdk/issues/63288) This change migrates the packages owned by the developer experience team to use the new constructor declaration syntax, described in https://github.com/dart-lang/language/blob/main/accepted/future-releases/primary-constructors/feature-specification.md#abbreviations-of-in-body-constructor-declarations. This change was performed in an automated fashion, by (a) bumping the packages' SDK constraints to `3.13.0-0`, (b) enabling the lints `unnecessary_type_name_in_constructor` and `unnecessary_const_in_enum_constructor`, (c) fixing the resulting lint failures using `dart fix`, and then (d) reformatting the affected files. To ease code review, I've reverted unrelated formatting changes. Since this change requires bumping SDK constaints to `3.13.0-0`, it was only performed on packages that are *not* published on pub. (Packages that *are* published on pub should remain on lower language versions until at least after the stable version of 3.13 is released, so that we don't block users on the stable channel from receiving updates to those packages.) Change-Id: Ibb4daebafd239da58251e838ea6a3f336a6a6964 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/505046 Commit-Queue: Paul Berry <paulberry@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> SLSA-Policy-Verified: SLSA Policy Verification Service <devtools-gerritcodereview-exitgate@google.com>
197 lines
6.6 KiB
Dart
197 lines
6.6 KiB
Dart
// 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 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:analysis_server_client/protocol.dart';
|
|
import 'package:analysis_server_client/src/server_base.dart';
|
|
import 'package:path/path.dart';
|
|
|
|
export 'package:analysis_server_client/src/server_base.dart'
|
|
show NotificationProcessor;
|
|
|
|
/// Instances of the class [Server] manage a server process,
|
|
/// and facilitate communication to and from the server.
|
|
///
|
|
/// Clients may not extend, implement or mix-in this class.
|
|
class Server extends ServerBase {
|
|
/// Server process object, or `null` if server hasn't been started yet
|
|
/// or if the server has already been stopped.
|
|
Process? _process;
|
|
|
|
/// The stderr subscription or `null` if either
|
|
/// [listenToOutput] has not been called or [stop] has been called.
|
|
StreamSubscription<String>? _stderrSubscription;
|
|
|
|
/// The stdout subscription or `null` if either
|
|
/// [listenToOutput] has not been called or [stop] has been called.
|
|
StreamSubscription<String>? _stdoutSubscription;
|
|
|
|
new({super.listener, this._process, super.stdioPassthrough});
|
|
|
|
/// Force kill the server. Returns exit code future.
|
|
@override
|
|
Future<int> kill({String reason = 'none'}) {
|
|
listener?.killingServerProcess(reason);
|
|
final process = _process!;
|
|
_process = null;
|
|
process.kill();
|
|
return process.exitCode;
|
|
}
|
|
|
|
/// Start listening to output from the server,
|
|
/// and deliver notifications to [notificationProcessor].
|
|
@override
|
|
void listenToOutput({NotificationProcessor? notificationProcessor}) {
|
|
_stdoutSubscription = _process!.stdout
|
|
.transform(utf8.decoder)
|
|
.transform(LineSplitter())
|
|
.listen((line) => outputProcessor(line, notificationProcessor));
|
|
_stderrSubscription = _process!.stderr
|
|
.transform(utf8.decoder)
|
|
.transform(LineSplitter())
|
|
.listen((line) => errorProcessor(line, notificationProcessor));
|
|
}
|
|
|
|
/// Send a command to the server. An 'id' will be automatically assigned.
|
|
/// The returned [Future] will be completed when the server acknowledges
|
|
/// the command with a response.
|
|
/// If the server acknowledges the command with a normal (non-error) response,
|
|
/// the future will be completed with the 'result' field from the response.
|
|
/// If the server acknowledges the command with an error response,
|
|
/// the future will be completed with an error.
|
|
@override
|
|
Future<Map<String, Object?>?> send(
|
|
String method, Map<String, Object?>? params) =>
|
|
sendCommandWith(method, params, _process!.stdin.add);
|
|
|
|
/// Start the server.
|
|
///
|
|
/// If [profileServer] is `true`, the server will be started
|
|
/// with "--observe" and "--pause-isolates-on-exit", allowing the observatory
|
|
/// to be used.
|
|
///
|
|
/// If [serverPath] is specified, then that analysis server will be launched,
|
|
/// otherwise the analysis server snapshot in the SDK will be launched.
|
|
///
|
|
/// If [enableAsserts] is specified, then asserts will be enabled in the new
|
|
/// dart process for that server. This is typically just useful to enable
|
|
/// locally for debugging.
|
|
@override
|
|
Future start({
|
|
String? clientId,
|
|
String? clientVersion,
|
|
int? diagnosticPort,
|
|
String? instrumentationLogFile,
|
|
bool profileServer = false,
|
|
String? sdkPath,
|
|
String? serverPath,
|
|
int? servicePort,
|
|
bool suppressAnalytics = true,
|
|
bool useAnalysisHighlight2 = false,
|
|
bool enableAsserts = false,
|
|
String? dartBinary,
|
|
}) async {
|
|
if (_process != null) {
|
|
throw Exception('Process already started');
|
|
}
|
|
dartBinary ??= Platform.executable;
|
|
|
|
// The integration tests run 3x faster when run from snapshots
|
|
// (you need to run test.py with --use-sdk).
|
|
if (serverPath == null) {
|
|
// Look for snapshots/analysis_server.dart.snapshot.
|
|
serverPath = normalize(join(dirname(Platform.resolvedExecutable),
|
|
'snapshots', 'analysis_server.dart.snapshot'));
|
|
|
|
if (!FileSystemEntity.isFileSync(serverPath)) {
|
|
// Look for dart-sdk/bin/snapshots/analysis_server.dart.snapshot.
|
|
serverPath = normalize(join(dirname(Platform.resolvedExecutable),
|
|
'dart-sdk', 'bin', 'snapshots', 'analysis_server.dart.snapshot'));
|
|
}
|
|
}
|
|
|
|
var arguments = <String>[];
|
|
//
|
|
// Add VM arguments.
|
|
//
|
|
if (profileServer) {
|
|
if (servicePort == null) {
|
|
arguments.add('--observe');
|
|
} else {
|
|
arguments.add('--observe=$servicePort');
|
|
}
|
|
arguments.add('--pause-isolates-on-exit');
|
|
} else if (servicePort != null) {
|
|
arguments.add('--enable-vm-service=$servicePort');
|
|
}
|
|
if (Platform.packageConfig != null) {
|
|
arguments.add('--packages=${Platform.packageConfig}');
|
|
}
|
|
if (enableAsserts) {
|
|
arguments.add('--enable-asserts');
|
|
}
|
|
//
|
|
// Add the server executable.
|
|
//
|
|
arguments.add(serverPath);
|
|
|
|
arguments.addAll(getServerArguments(
|
|
clientId: clientId,
|
|
clientVersion: clientVersion,
|
|
suppressAnalytics: suppressAnalytics,
|
|
diagnosticPort: diagnosticPort,
|
|
instrumentationLogFile: instrumentationLogFile,
|
|
sdkPath: sdkPath,
|
|
useAnalysisHighlight2: useAnalysisHighlight2));
|
|
|
|
listener?.startingServer(dartBinary, arguments);
|
|
final process = await Process.start(dartBinary, arguments);
|
|
_process = process;
|
|
// ignore: unawaited_futures
|
|
process.exitCode.then((int code) {
|
|
if (code != 0 && _process != null) {
|
|
// Report an error if server abruptly terminated
|
|
listener?.unexpectedStop(code);
|
|
}
|
|
});
|
|
}
|
|
|
|
/// Attempt to gracefully shutdown the server.
|
|
/// If that fails, then kill the process.
|
|
@override
|
|
Future<int> stop({Duration? timeLimit}) async {
|
|
timeLimit ??= const Duration(seconds: 5);
|
|
|
|
final process = _process;
|
|
if (process == null) {
|
|
// Process already exited
|
|
return -1;
|
|
}
|
|
|
|
final future = send(serverRequestShutdown, null);
|
|
_process = null;
|
|
await future
|
|
// fall through to wait for exit
|
|
.timeout(timeLimit, onTimeout: () {
|
|
return {};
|
|
}).whenComplete(() async {
|
|
await _stderrSubscription?.cancel();
|
|
_stderrSubscription = null;
|
|
await _stdoutSubscription?.cancel();
|
|
_stdoutSubscription = null;
|
|
});
|
|
return process.exitCode.timeout(
|
|
timeLimit,
|
|
onTimeout: () {
|
|
listener?.killingServerProcess('server failed to exit');
|
|
process.kill();
|
|
return process.exitCode;
|
|
},
|
|
);
|
|
}
|
|
}
|