e97f1bdbf0
This should allow doing partial migration, specifically protocol files, which are imported by other libraries, but are a small library cycle that does not import much outside of it. Change-Id: I904c05d6d5b444ee9a9dbd1f7ada12aabdcc5165 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193583 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
178 lines
5.9 KiB
Dart
178 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.
|
|
|
|
// @dart = 2.9
|
|
|
|
/// 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');
|
|
}
|
|
}
|
|
}
|