Files
Paul Berry afcfbbeba8 Migrate developer experience packages to new constructor decl syntax.
(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>
2026-05-27 14:52:58 -07:00

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;
},
);
}
}