dart-sdk/pkg/analysis_server/tool/migration_runner.dart
Konstantin Shcheglov c3655ed435 Remove FolderBasedDartSdk.defaultSdkDirectory() and getSdkProperty().
It is up to the higher level clients to decide how to find SDK.

It is not API, and is not referenced internally, so we can land it
without going through breaking changes.

Change-Id: Id428519fa9bb3c38368f095c0f358e07f65c45b4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/154081
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
2020-07-14 18:09:30 +00:00

176 lines
5.9 KiB
Dart

// Copyright (c) 2019, 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.
/// This executable provides the ability to run the migration tool in process
/// on a single package. It should be invoked with two command-line arguments:
/// a path to a configuration file and the name of a package to migrate.
///
/// The configuration file format is a JSON map, with the following keys:
/// - `sdk_root`: path to the SDK source code on the user's machine (this is the
/// directory that contains `pkg`, `third_party`, `tests`, etc.
/// - `output_root`: if present, path to the directory on the user's machine
/// where output HTML files should go. A subdirectory will be created for
/// each package that is migrated.
/// - `external_packages`: a map (name => path) of additional non-SDK packages
/// that may need to be migrated.
/// - `port`: if present, the port where a server should be spawned serving HTML
/// pages.
library migration_runner;
import 'dart:convert';
import 'dart:io' as io;
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
import 'package:analysis_server/src/utilities/mocks.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:cli_util/cli_util.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
Future<void> main(List<String> args) async {
if (args.length != 2) {
throw StateError(
'Exactly two arguments are required: the path to a JSON configuration '
'file, and the name of the package to migrate');
}
var testInfoJsonPath = args[0];
var testInfoJson = json.decode(io.File(testInfoJsonPath).readAsStringSync());
var packageName = args[1];
var testInfo = TestInfo(testInfoJson);
var packageRoot = testInfo.packageRoot(packageName);
var port = testInfo.port;
print('Preparing to migrate');
var migrationTest = MigrationTest();
migrationTest.setUp();
print('Migrating');
await migrationTest.run(packageRoot, port);
if (port == null) {
print('Done');
io.exit(0);
} else {
print('Done. Please point your browser to localhost:$port/\$filePath');
}
}
class MigrationBase {
ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
MockServerChannel serverChannel;
AnalysisServer server;
AnalysisServer createAnalysisServer() {
//
// Create server
//
var options = AnalysisServerOptions();
var sdkPath = getSdkPath();
return AnalysisServer(
serverChannel,
resourceProvider,
options,
DartSdkManager(sdkPath),
CrashReportingAttachmentsBuilder.empty,
InstrumentationService.NULL_SERVICE);
}
void processNotification(Notification notification) {
if (notification.event == SERVER_NOTIFICATION_ERROR) {
fail('${notification.toJson()}');
}
}
Future<Response> sendAnalysisSetAnalysisRoots(List<String> directories) {
var request =
AnalysisSetAnalysisRootsParams(directories, []).toRequest('0');
return waitResponse(request);
}
Future<Response> sendEditDartfix(List<String> directories, int port) {
var request = EditDartfixParams(directories,
includedFixes: ['non-nullable'], port: port)
.toRequest('1');
return waitResponse(request);
}
void setUp() {
serverChannel = MockServerChannel();
server = createAnalysisServer();
server.pluginManager = TestPluginManager();
// listen for notifications
var notificationStream = serverChannel.notificationController.stream;
notificationStream.listen((Notification notification) {
processNotification(notification);
});
}
void tearDown() {
server.done();
server = null;
serverChannel = null;
}
/// Returns a [Future] that completes when the server's analysis is complete.
Future waitForTasksFinished() {
return server.onAnalysisComplete;
}
/// Completes with a successful [Response] for the given [request].
Future<Response> waitResponse(Request request,
{bool throwOnError = true}) async {
return serverChannel.sendRequest(request, throwOnError: throwOnError);
}
}
class MigrationTest extends MigrationBase {
Future<void> run(String packageRoot, int port) async {
var packageRoots = <String>[packageRoot];
await sendAnalysisSetAnalysisRoots(packageRoots);
await sendEditDartfix(packageRoots, port);
}
}
class TestInfo {
static const Set<String> thirdPartyPackages = {
'charcode',
'collection',
'logging',
'meta',
'pedantic',
'typed_data'
};
static const Set<String> builtInPackages = {'meta', 'path'};
final Map<String, Object> testInfoJson;
TestInfo(this.testInfoJson);
Map<String, String> get externalPackages =>
((testInfoJson['external_packages'] ?? {}) as Map).cast<String, String>();
String get outputRoot => testInfoJson['output_root'];
int get port => testInfoJson['port'];
String get sdkRoot => testInfoJson['sdk_root'];
String packageRoot(String packageName) {
if (thirdPartyPackages.contains(packageName)) {
return path.join(sdkRoot, 'third_party', 'pkg', packageName);
} else if (builtInPackages.contains(packageName)) {
return path.join(sdkRoot, 'pkg', packageName);
} else if (externalPackages.containsKey(packageName)) {
return externalPackages[packageName];
} else {
throw StateError('Unrecognized package $packageName');
}
}
}