Skip to content

Commit aa25664

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Migration: Add a flag to allow the user to ignore exceptions.
This should allow users to work around bugs while waiting for fixes from the migration team. Change-Id: I04fe08b4753ee1377a60ec60728a16560847536f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150542 Reviewed-by: Mike Fairhurst <[email protected]> Reviewed-by: Samuel Rawlins <[email protected]>
1 parent 977997b commit aa25664

File tree

6 files changed

+216
-56
lines changed

6 files changed

+216
-56
lines changed

pkg/nnbd_migration/lib/migration_cli.dart

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class CommandLineOptions {
4747
static const applyChangesFlag = 'apply-changes';
4848
static const helpFlag = 'help';
4949
static const ignoreErrorsFlag = 'ignore-errors';
50+
static const ignoreExceptionsFlag = 'ignore-exceptions';
5051
static const previewPortOption = 'preview-port';
5152
static const sdkPathOption = 'sdk-path';
5253
static const skipPubOutdatedFlag = 'skip-pub-outdated';
@@ -60,6 +61,8 @@ class CommandLineOptions {
6061

6162
final bool ignoreErrors;
6263

64+
final bool ignoreExceptions;
65+
6366
final int previewPort;
6467

6568
final String sdkPath;
@@ -74,6 +77,7 @@ class CommandLineOptions {
7477
{@required this.applyChanges,
7578
@required this.directory,
7679
@required this.ignoreErrors,
80+
@required this.ignoreExceptions,
7781
@required this.previewPort,
7882
@required this.sdkPath,
7983
@required this.skipPubOutdated,
@@ -238,6 +242,10 @@ class MigrationCli {
238242

239243
AnalysisContextCollection _contextCollection;
240244

245+
bool _hasExceptions = false;
246+
247+
bool _hasAnalysisErrors = false;
248+
241249
MigrationCli(
242250
{@required this.binaryName,
243251
@visibleForTesting this.loggerFactory = _defaultLoggerFactory,
@@ -275,6 +283,10 @@ class MigrationCli {
275283
return contextCollection.contexts.length > 1;
276284
}
277285

286+
@visibleForTesting
287+
bool get isPreviewServerRunning =>
288+
_fixCodeProcessor?.isPreviewServerRunnning ?? false;
289+
278290
Context get pathContext => resourceProvider.pathContext;
279291

280292
/// Blocks until an interrupt signal (control-C) is received. Tests may
@@ -289,12 +301,10 @@ class MigrationCli {
289301
ResourceProvider resourceProvider, LineInfo getLineInfo(String path),
290302
{List<String> included = const <String>[],
291303
int preferredPort,
292-
bool enablePreview = true,
293304
String summaryPath}) {
294305
return NonNullableFix(listener, resourceProvider, getLineInfo,
295306
included: included,
296307
preferredPort: preferredPort,
297-
enablePreview: enablePreview,
298308
summaryPath: summaryPath);
299309
}
300310

@@ -349,6 +359,8 @@ class MigrationCli {
349359
applyChanges: applyChanges,
350360
directory: migratePath,
351361
ignoreErrors: argResults[CommandLineOptions.ignoreErrorsFlag] as bool,
362+
ignoreExceptions:
363+
argResults[CommandLineOptions.ignoreExceptionsFlag] as bool,
352364
previewPort: previewPort,
353365
sdkPath: argResults[CommandLineOptions.sdkPathOption] as String ??
354366
defaultSdkPathOverride ??
@@ -408,13 +420,12 @@ class MigrationCli {
408420
await _withProgress(
409421
'${ansi.emphasized('Generating migration suggestions')}', () async {
410422
_fixCodeProcessor = _FixCodeProcessor(context, this);
411-
_dartFixListener =
412-
DartFixListener(DriverProviderImpl(resourceProvider, context));
423+
_dartFixListener = DartFixListener(
424+
DriverProviderImpl(resourceProvider, context), _exceptionReported);
413425
nonNullableFix = createNonNullableFix(
414426
_dartFixListener, resourceProvider, _fixCodeProcessor.getLineInfo,
415427
included: [options.directory],
416428
preferredPort: options.previewPort,
417-
enablePreview: options.webPreview,
418429
summaryPath: options.summary);
419430
nonNullableFix.rerunFunction = _rerunFunction;
420431
_fixCodeProcessor.registerCodeTask(nonNullableFix);
@@ -547,6 +558,7 @@ Use this interactive web view to review, improve, or apply the results.
547558
logger.stdout(
548559
'Note: analysis errors will result in erroneous migration suggestions.');
549560

561+
_hasAnalysisErrors = true;
550562
if (options.ignoreErrors) {
551563
logger.stdout('Continuing with migration suggestions due to the use of '
552564
'--${CommandLineOptions.ignoreErrorsFlag}.');
@@ -620,6 +632,43 @@ Use this interactive web view to review, improve, or apply the results.
620632
}
621633
}
622634

635+
void _exceptionReported(String detail) {
636+
if (_hasExceptions) return;
637+
_hasExceptions = true;
638+
if (options.ignoreExceptions) {
639+
logger.stdout('''
640+
Exception(s) occurred during migration. Attempting to perform
641+
migration anyway due to the use of --${CommandLineOptions.ignoreExceptionsFlag}.
642+
643+
To see exception details, re-run without --${CommandLineOptions.ignoreExceptionsFlag}.
644+
''');
645+
} else {
646+
exitCode = 1;
647+
if (_hasAnalysisErrors) {
648+
logger.stderr('''
649+
Aborting migration due to an exception. This may be due to a bug in
650+
the migration tool, or it may be due to errors in the source code
651+
being migrated. If possible, try to fix errors in the source code and
652+
re-try migrating. If that doesn't work, consider filing a bug report
653+
at:
654+
''');
655+
} else {
656+
logger.stderr('''
657+
Aborting migration due to an exception. This most likely is due to a
658+
bug in the migration tool. Please consider filing a bug report at:
659+
''');
660+
}
661+
logger.stderr('https://github.com/dart-lang/sdk/issues/new');
662+
logger.stderr('''
663+
To attempt to perform migration anyway, you may re-run with
664+
--${CommandLineOptions.ignoreExceptionsFlag}.
665+
666+
Exception details:
667+
''');
668+
logger.stderr(detail);
669+
}
670+
}
671+
623672
bool _isUriError(AnalysisError error) =>
624673
error.errorCode == CompileTimeErrorCode.URI_DOES_NOT_EXIST;
625674

@@ -697,6 +746,12 @@ Use this interactive web view to review, improve, or apply the results.
697746
help: 'Attempt to perform null safety analysis even if there are '
698747
'analysis errors in the project.',
699748
);
749+
parser.addFlag(CommandLineOptions.ignoreExceptionsFlag,
750+
defaultsTo: false,
751+
negatable: false,
752+
help:
753+
'Attempt to perform null safety analysis even if exceptions occur.',
754+
hide: hide);
700755
parser.addOption(CommandLineOptions.previewPortOption,
701756
help:
702757
'Run the preview server on the specified port. If not specified, '
@@ -780,6 +835,9 @@ class _FixCodeProcessor extends Object {
780835
_FixCodeProcessor(this.context, this._migrationCli)
781836
: pathsToProcess = _computePathsToProcess(context);
782837

838+
bool get isPreviewServerRunnning =>
839+
nonNullableFixTask?.isPreviewServerRunning ?? false;
840+
783841
LineInfo getLineInfo(String path) =>
784842
context.currentSession.getFile(path).lineInfo;
785843

@@ -863,7 +921,10 @@ class _FixCodeProcessor extends Object {
863921
await _task.processUnit(phase, result);
864922
});
865923
}
866-
await _task.finish();
924+
var state = await _task.finish();
925+
if (_migrationCli.exitCode == null && _migrationCli.options.webPreview) {
926+
await _task.startPreviewServer(state);
927+
}
867928
_progressBar.complete();
868929

869930
return nonNullableFixTask.previewUrls;

pkg/nnbd_migration/lib/src/front_end/dartfix_listener.dart

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@ class DartFixListener {
1515

1616
final List<DartFixSuggestion> suggestions = [];
1717

18-
DartFixListener(this.server);
19-
2018
/// Add the given [detail] to the list of details to be returned to the
2119
/// client.
22-
void addDetail(String detail) {
23-
throw UnimplementedError('TODO(paulberry)');
24-
}
20+
final void Function(String detail) reportException;
21+
22+
DartFixListener(this.server, this.reportException);
2523

2624
/// Record an edit to be sent to the client.
2725
///

pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ import 'package:yaml/yaml.dart';
2626
/// and determines whether the associated variable or parameter can be null
2727
/// then adds or removes a '?' trailing the named type as appropriate.
2828
class NonNullableFix {
29-
/// TODO(paulberry): allow this to be controlled by a command-line parameter.
30-
static const bool _usePermissiveMode = false;
31-
3229
// TODO(srawlins): Refactor to use
3330
// `Feature.non_nullable.firstSupportedVersion` when this becomes non-null.
3431
static const String _intendedMinimumSdkVersion = '2.9.0';
@@ -52,9 +49,6 @@ class NonNullableFix {
5249
/// which all included paths share.
5350
final String includedRoot;
5451

55-
/// Indicates whether the web preview of migration results should be launched.
56-
final bool enablePreview;
57-
5852
/// If non-null, the path to which a machine-readable summary of migration
5953
/// results should be written.
6054
final String summaryPath;
@@ -89,44 +83,26 @@ class NonNullableFix {
8983
List<String> previewUrls;
9084

9185
NonNullableFix(this.listener, this.resourceProvider, this._getLineInfo,
92-
{List<String> included = const [],
93-
this.preferredPort,
94-
this.enablePreview = true,
95-
this.summaryPath})
86+
{List<String> included = const [], this.preferredPort, this.summaryPath})
9687
: includedRoot =
9788
_getIncludedRoot(included, listener.server.resourceProvider) {
9889
reset();
9990
}
10091

92+
bool get isPreviewServerRunning => _server != null;
93+
10194
int get numPhases => 3;
10295

10396
InstrumentationListener createInstrumentationListener(
10497
{MigrationSummary migrationSummary}) =>
10598
InstrumentationListener(migrationSummary: migrationSummary);
10699

107-
Future<void> finish() async {
100+
Future<MigrationState> finish() async {
108101
migration.finish();
109102
final state = MigrationState(
110103
migration, includedRoot, listener, instrumentationListener);
111104
await state.refresh();
112-
113-
if (enablePreview && _server == null) {
114-
_server = HttpPreviewServer(state, rerun, preferredPort);
115-
_server.serveHttp();
116-
_allServers.add(_server);
117-
port = await _server.boundPort;
118-
authToken = await _server.authToken;
119-
120-
previewUrls = [
121-
// TODO(jcollins-g): Change protocol to only return a single string.
122-
Uri(
123-
scheme: 'http',
124-
host: 'localhost',
125-
port: port,
126-
path: state.pathMapper.map(includedRoot),
127-
queryParameters: {'authToken': authToken}).toString()
128-
];
129-
}
105+
return state;
130106
}
131107

132108
/// Processes the non-source files of the package rooted at [pkgFolder].
@@ -197,12 +173,32 @@ class NonNullableFix {
197173
: MigrationSummary(summaryPath, resourceProvider, includedRoot));
198174
adapter = NullabilityMigrationAdapter(listener);
199175
migration = NullabilityMigration(adapter, _getLineInfo,
200-
permissive: _usePermissiveMode,
201-
instrumentation: instrumentationListener);
176+
permissive: true, instrumentation: instrumentationListener);
202177
}
203178

204179
void shutdownServer() {
205180
_server?.close();
181+
_server = null;
182+
}
183+
184+
Future<void> startPreviewServer(MigrationState state) async {
185+
if (_server == null) {
186+
_server = HttpPreviewServer(state, rerun, preferredPort);
187+
_server.serveHttp();
188+
_allServers.add(_server);
189+
port = await _server.boundPort;
190+
authToken = await _server.authToken;
191+
192+
previewUrls = [
193+
// TODO(jcollins-g): Change protocol to only return a single string.
194+
Uri(
195+
scheme: 'http',
196+
host: 'localhost',
197+
port: port,
198+
path: state.pathMapper.map(includedRoot),
199+
queryParameters: {'authToken': authToken}).toString()
200+
];
201+
}
206202
}
207203

208204
/// Updates the Package Config file to specify a minimum Dart SDK version
@@ -447,7 +443,7 @@ class NullabilityMigrationAdapter implements NullabilityMigrationListener {
447443
@override
448444
void reportException(
449445
Source source, AstNode node, Object exception, StackTrace stackTrace) {
450-
listener.addDetail('''
446+
listener.reportException('''
451447
$exception
452448
453449
$stackTrace''');

pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ class NnbdMigrationTestBase extends AbstractAnalysisTest {
201201
// Compute the analysis results.
202202
var server = DriverProviderImpl(resourceProvider, driver.analysisContext);
203203
// Run the migration engine.
204-
var listener = DartFixListener(server);
204+
var listener = DartFixListener(server, _exceptionReported);
205205
var instrumentationListener = InstrumentationListener();
206206
var adapter = NullabilityMigrationAdapter(listener);
207207
var migration = NullabilityMigration(adapter, getLineInfo,
@@ -227,4 +227,8 @@ class NnbdMigrationTestBase extends AbstractAnalysisTest {
227227
resourceProvider, includedRoot, info, listener, migration, nodeMapper);
228228
infos = await builder.explainMigration();
229229
}
230+
231+
void _exceptionReported(String detail) {
232+
fail('Unexpected error during migration: $detail');
233+
}
230234
}

0 commit comments

Comments
 (0)