| // Copyright (c) 2025, 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:io'; |
| import 'dart:isolate'; |
| |
| import 'package:path/path.dart' as path; |
| |
| /// The compiled version of the analysis server snapshot that should be used |
| /// for integration tests. Set by [getAnalysisServerPath]. |
| String? _compiledServerPath; |
| |
| /// The path of the `pkg/analysis_server` folder, resolved using the active |
| /// `package_config.json`. |
| String get analysisServerPackagePath { |
| // Locate the root of the analysis server package without using |
| // `Platform.script` as it fails when run through the `dart test`. |
| // https://github.com/dart-lang/test/issues/110 |
| var serverLibUri = Isolate.resolvePackageUriSync( |
| Uri.parse('package:analysis_server/'), |
| ); |
| return path.normalize(path.join(serverLibUri!.toFilePath(), '..')); |
| } |
| |
| /// The path of the `package_config.json` file in the root of the SDK, |
| /// computed by resolving the path to `pkg:analysis_server`. |
| String get sdkPackageConfigPath { |
| return path.normalize( |
| path.join(sdkRootPath, '.dart_tool', 'package_config.json'), |
| ); |
| } |
| |
| /// The path the SDK, computed as the parent of the `pkg/analysis_server` |
| /// folder, resolved using the active `package_config.json`. |
| String get sdkRootPath { |
| return path.normalize(path.join(analysisServerPackagePath, '..', '..')); |
| } |
| |
| /// Gets the path of the analysis server entry point which may be the snapshot |
| /// from the current SDK (default) or a compiled version of the source script |
| /// depending on the `TEST_SERVER_SNAPSHOT` environment variable. |
| Future<String> getAnalysisServerPath(String dartSdkPath) async { |
| // If we have already computed the path once, use that. |
| if (_compiledServerPath case var compiledServerPath?) { |
| return compiledServerPath; |
| } |
| |
| // The 'TEST_SERVER_SNAPSHOT' env variable can either be: |
| // |
| // - Unset, in which case the tests run from the SDK compiled snapshot |
| // - The string 'false' which will cause the server to compiled from source. |
| // This is a simple way to run from source using the test_all file that |
| // runs all tests in a single isolate and will trigger a single |
| // compilation for all integration tests. |
| // - A path to a pre-compiled snapshot. |
| // This allows configuring VS Code to pre-compile the snapshot once and |
| // then use 'dart test' which will run each sweet in a separate isolate |
| // without each test/isolate having to compile. |
| var snapshotPath = switch (Platform.environment['TEST_SERVER_SNAPSHOT']) { |
| // Compile on the fly |
| 'false' => await _compileTemporaryServerSnapshot(), |
| // Default, use the SDK-bundled snapshot |
| 'true' || '' || null => path.join( |
| dartSdkPath, |
| 'bin', |
| 'snapshots', |
| 'analysis_server.dart.snapshot', |
| ), |
| // Custom path in the env variable |
| String snapshotPath => snapshotPath, |
| }; |
| |
| return _compiledServerPath = path.normalize(snapshotPath); |
| } |
| |
| /// Compiles a temporary snapshot for the analysis server into a temporary file |
| /// and returns the full path. |
| /// |
| /// This function can only be called once in a single process/isolate. |
| Future<String> _compileTemporaryServerSnapshot() async { |
| if (_compiledServerPath != null) { |
| throw 'Snapshot is already compiled or being compiled'; |
| } |
| |
| var dartBinary = Platform.resolvedExecutable; |
| var tempSnapshotDirectory = Directory.systemTemp.createTempSync( |
| 'analysisServer_test_integration_compiledServer', |
| ); |
| var tempSnapshotFilePath = path.join( |
| tempSnapshotDirectory.path, |
| 'analysis_server.dart.snapshot', |
| ); |
| var sourcePath = path.join(analysisServerPackagePath, 'bin', 'server.dart'); |
| var result = await Process.run(dartBinary, [ |
| 'compile', |
| 'kernel', |
| sourcePath, |
| '-o', |
| tempSnapshotFilePath, |
| ]); |
| if (result.exitCode != 0) { |
| throw 'Failed to compile analysis server:\n' |
| 'Exit code: ${result.exitCode}\n' |
| 'stdout: ${result.stdout}\n' |
| 'stderr: ${result.stderr}\n'; |
| } |
| return tempSnapshotFilePath; |
| } |