dartdev: Support running the AOT analyis_server snapshot for analyze command

The `dart analyze` command is quite separate from the `dart language-server` command. This CL adds support for `dart analyze`.

Work towards https://github.com/dart-lang/sdk/issues/50498

Change-Id: I60a846ae5d3452c2bb050bd07502084ff44b82c0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425188
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
Sam Rawlins
2025-05-02 11:49:21 -07:00
committed by Commit Queue
parent d7b3562cf4
commit 060e4e208c
9 changed files with 54 additions and 50 deletions
@@ -30,14 +30,7 @@ class Sdk {
/// Path to the 'dart' executable in the Dart SDK.
String get dart {
var basename = path.basename(Platform.executable);
// It's possible that `Platform.executable` won't include the '.exe'
// extension on Windows (e.g., launching `dart` from `cmd.exe` where `dart`
// is on the `PATH`). Append '.exe' in this case so the
// `checkArtifactExists` check won't fail.
if (Platform.isWindows && !basename.endsWith('.exe')) {
basename += '.exe';
}
var basename = Platform.isWindows ? 'dart.exe' : 'dart';
return path.absolute(
_runFromBuildRoot ? sdkPath : path.absolute(sdkPath, 'bin'),
basename,
+30 -18
View File
@@ -37,7 +37,8 @@ class AnalysisServer {
this.enabledExperiments = const [],
this.disableStatusNotificationDebouncing = false,
this.suppressAnalytics = false,
});
bool useAotSnapshot = false,
}) : _useAotSnapshot = useAotSnapshot;
final String? cacheDirectoryPath;
final File? packagesFile;
@@ -48,6 +49,7 @@ class AnalysisServer {
final List<String> enabledExperiments;
final bool disableStatusNotificationDebouncing;
final bool suppressAnalytics;
final bool _useAotSnapshot;
Process? _process;
@@ -107,24 +109,8 @@ class AnalysisServer {
/// Starts the process and returns the pid for it.
Future<int> start({bool setAnalysisRoots = true}) async {
preAnalysisServerStart?.call(commandName, analysisRoots, argResults);
final command = [
sdk.analysisServerSnapshot,
if (suppressAnalytics) '--${Driver.SUPPRESS_ANALYTICS_FLAG}',
'--${Driver.CLIENT_ID}=dart-$commandName',
'--disable-server-feature-completion',
'--disable-server-feature-search',
if (disableStatusNotificationDebouncing)
'--disable-status-notification-debouncing',
'--disable-silent-analysis-exceptions',
'--sdk',
sdkPath.path,
if (cacheDirectoryPath != null) '--cache=$cacheDirectoryPath',
if (packagesFile != null) '--packages=${packagesFile!.path}',
if (enabledExperiments.isNotEmpty)
'--$experimentFlagName=${enabledExperiments.join(',')}'
];
final process = await startDartProcess(sdk, command);
final process = await _startProcess();
_process = process;
_shutdownResponseReceived = false;
// This callback hookup can't throw.
@@ -206,6 +192,32 @@ class AnalysisServer {
return process.pid;
}
Future<Process> _startProcess() {
final executable = _useAotSnapshot ? sdk.dartAotRuntime : sdk.dart;
final arguments = [
if (_useAotSnapshot)
sdk.analysisServerAotSnapshot
else
sdk.analysisServerSnapshot,
if (suppressAnalytics) '--${Driver.SUPPRESS_ANALYTICS_FLAG}',
'--${Driver.CLIENT_ID}=dart-$commandName',
'--disable-server-feature-completion',
'--disable-server-feature-search',
if (disableStatusNotificationDebouncing)
'--disable-status-notification-debouncing',
'--disable-silent-analysis-exceptions',
'--sdk',
sdkPath.path,
if (cacheDirectoryPath != null) '--cache=$cacheDirectoryPath',
if (packagesFile != null) '--packages=${packagesFile!.path}',
if (enabledExperiments.isNotEmpty)
'--$experimentFlagName=${enabledExperiments.join(',')}',
];
log.trace('$executable ${arguments.join(' ')}');
return Process.start(executable, arguments);
}
Future<String> getVersion() {
return _sendCommand('server.getVersion')
.then((response) => response['version']);
+12 -3
View File
@@ -90,6 +90,11 @@ class AnalyzeCommand extends DartdevCommand {
help: 'The path to the Dart SDK.',
hide: !verbose,
)
..addFlag(
useAotSnapshotFlag,
help: 'Use the AOT analysis server snapshot',
hide: true,
)
..addExperimentalFlags();
}
@@ -129,20 +134,23 @@ class AnalyzeCommand extends DartdevCommand {
final printMemory = args.flag('memory') && jsonFormat;
io.Directory sdkPath;
final useAotSnapshot = args.flag(useAotSnapshotFlag);
if (args.wasParsed('sdk-path')) {
sdkPath = io.Directory(args.option('sdk-path')!);
if (!sdkPath.existsSync()) {
usageException('Invalid Dart SDK path: ${sdkPath.path}');
}
final snapshotName = useAotSnapshot
? 'analysis_server_aot.dart.snapshot'
: 'analysis_server.dart.snapshot';
final snapshotPath = path.join(
sdkPath.path,
'bin',
'snapshots',
'analysis_server.dart.snapshot',
snapshotName,
);
if (!io.File(snapshotPath).existsSync()) {
usageException(
'Invalid Dart SDK path has no analysis_server.dart.snapshot file: '
usageException("Invalid Dart SDK path has no '$snapshotName' file: "
'${sdkPath.path}');
}
} else {
@@ -180,6 +188,7 @@ class AnalyzeCommand extends DartdevCommand {
disableStatusNotificationDebouncing: true,
enabledExperiments: args.enabledExperiments,
suppressAnalytics: suppressAnalytics,
useAotSnapshot: useAotSnapshot,
);
server.onErrors.listen((FileAnalysisErrors fileErrors) {
@@ -35,7 +35,7 @@ For more information about the server's capabilities and configuration, see:
usageLineLength: dartdevUsageLineLength,
includeHelpFlag: false,
defaultToLsp: true,
)..addFlag(_useAotSnapshotFlag,
)..addFlag(useAotSnapshotFlag,
help: 'Use the AOT analysis server snapshot', hide: true);
}
@@ -49,11 +49,11 @@ For more information about the server's capabilities and configuration, see:
args = [...args, '--$protocol=$lsp'];
}
try {
if (argResults!.flag(_useAotSnapshotFlag)) {
if (argResults!.flag(useAotSnapshotFlag)) {
if (!Sdk.checkArtifactExists(sdk.dartAotRuntime)) {
return _genericErrorExitCode;
}
args.remove('--$_useAotSnapshotFlag');
args.remove('--$useAotSnapshotFlag');
VmInteropHandler.run(
sdk.dartAotRuntime,
[sdk.analysisServerAotSnapshot, ...args],
@@ -77,7 +77,5 @@ For more information about the server's capabilities and configuration, see:
}
}
static const _useAotSnapshotFlag = 'use-aot-snapshot';
static const _genericErrorExitCode = 255;
}
-14
View File
@@ -12,7 +12,6 @@ import 'package:cli_util/cli_logging.dart';
import 'package:path/path.dart' as path;
import 'experiments.dart';
import 'sdk.dart';
import 'utils.dart';
// Initialize a default logger. We'll replace this with a verbose logger if
@@ -86,19 +85,6 @@ extension DartDevCommand<T> on Command<T> {
globalResults!.multiOption(experimentFlagName);
}
/// A utility method to start a Dart VM instance with the given arguments and an
/// optional current working directory.
///
/// [arguments] should contain the snapshot path.
Future<Process> startDartProcess(
Sdk sdk,
List<String> arguments, {
String? cwd,
}) {
log.trace('${sdk.dart} ${arguments.join(' ')}');
return Process.start(sdk.dart, arguments, workingDirectory: cwd);
}
Future<int> runProcess(
List<String> command, {
bool logToTrace = false,
+2
View File
@@ -288,3 +288,5 @@ class Runtime {
return Runtime._(version, channel);
}
}
const useAotSnapshotFlag = 'use-aot-snapshot';
+1
View File
@@ -42,6 +42,7 @@ declare_args() {
# ......utils/gen_snapshot or utils/gen_snapshot.exe (if not on ia32)
# ......snapshots/
# ........analysis_server.dart.snapshot
# ........analysis_server_aot.dart.snapshot (AOT snapshot, if not on ia32)
# ........dart2bytecode.snapshot (AOT snapshot, for selected targets)
# ........dart2js_aot.dart.snapshot (AOT snapshot, if not on ia32)
# ........dart2js.dart.snapshot (JIT snapshot only on ia32)
+2 -2
View File
@@ -9,13 +9,14 @@ aot_snapshot("analysis_server_aot") {
main_dart = "../../pkg/analysis_server/bin/server.dart"
name = "analysis_server_aot"
output = "$root_gen_dir/analysis_server_aot.dart.snapshot"
vm_args = [ "-Dbuilt_as_aot=true" ]
args = [ "-Dbuilt_as_aot=true" ]
}
aot_snapshot("analysis_server_aot_product") {
main_dart = "../../pkg/analysis_server/bin/server.dart"
name = "analysis_server_aot_product"
output = "$root_gen_dir/analysis_server_aot_product.dart.snapshot"
args = [ "-Dbuilt_as_aot=true" ]
# dartaotruntime in the dart sdk has dart_product_config applied to it,
# so it is built in product mode in both release and
@@ -32,5 +33,4 @@ application_snapshot("analysis_server") {
"--sdk=" + rebase_path("../../sdk/"),
"--train-using=" + rebase_path("../../pkg/compiler/lib"),
]
vm_args = [ "-Dbuilt_as_aot=false" ]
}
+3
View File
@@ -98,6 +98,9 @@ template("aot_snapshot") {
if (product_mode) {
args += [ "-Ddart.vm.product=true" ]
}
if (defined(invoker.args)) {
args += invoker.args
}
}
# Whether to build an AOT snapshot, which can be opened by dlopen.