Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit ac45f23

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Migration: Fix reporting of exceptions.
Permissive mode in the analyzer currently is broken, leading to a useless stacktrace if an exception occurs. As a quick fix, turn permissive mode off, so the exception just bubbles up normally and shows on the console. In follow-up CLs I'll actually fix permissive mode and add a user option to enable it. Fixes #42138. Change-Id: I59322ca9dd90b856c56a6ec335762b94ec6935b7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/149863 Reviewed-by: Mike Fairhurst <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent 0f505e0 commit ac45f23

File tree

3 files changed

+109
-8
lines changed

3 files changed

+109
-8
lines changed

pkg/nnbd_migration/lib/migration_cli.dart

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,19 @@ class MigrationCli {
257257
return stream.first;
258258
}
259259

260+
NonNullableFix createNonNullableFix(DartFixListener listener,
261+
ResourceProvider resourceProvider, LineInfo getLineInfo(String path),
262+
{List<String> included = const <String>[],
263+
int preferredPort,
264+
bool enablePreview = true,
265+
String summaryPath}) {
266+
return NonNullableFix(listener, resourceProvider, getLineInfo,
267+
included: included,
268+
preferredPort: preferredPort,
269+
enablePreview: enablePreview,
270+
summaryPath: summaryPath);
271+
}
272+
260273
/// Parses and validates command-line arguments, and stores the results in
261274
/// [options].
262275
///
@@ -365,7 +378,7 @@ class MigrationCli {
365378
_fixCodeProcessor = _FixCodeProcessor(context, this);
366379
_dartFixListener =
367380
DartFixListener(DriverProviderImpl(resourceProvider, context));
368-
nonNullableFix = NonNullableFix(
381+
nonNullableFix = createNonNullableFix(
369382
_dartFixListener, resourceProvider, _fixCodeProcessor.getLineInfo,
370383
included: [options.directory],
371384
preferredPort: options.previewPort,

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ 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): stop using permissive mode once the migration logic is
30-
/// mature enough.
31-
static const bool _usePermissiveMode = true;
29+
/// TODO(paulberry): allow this to be controlled by a command-line parameter.
30+
static const bool _usePermissiveMode = false;
3231

3332
// TODO(srawlins): Refactor to use
3433
// `Feature.non_nullable.firstSupportedVersion` when this becomes non-null.
@@ -101,6 +100,10 @@ class NonNullableFix {
101100

102101
int get numPhases => 3;
103102

103+
InstrumentationListener createInstrumentationListener(
104+
{MigrationSummary migrationSummary}) =>
105+
InstrumentationListener(migrationSummary: migrationSummary);
106+
104107
Future<void> finish() async {
105108
migration.finish();
106109
final state = MigrationState(
@@ -188,7 +191,7 @@ class NonNullableFix {
188191
}
189192

190193
void reset() {
191-
instrumentationListener = InstrumentationListener(
194+
instrumentationListener = createInstrumentationListener(
192195
migrationSummary: summaryPath == null
193196
? null
194197
: MigrationSummary(summaryPath, resourceProvider, includedRoot));

pkg/nnbd_migration/test/migration_cli_test.dart

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,21 @@ import 'dart:async';
66
import 'dart:convert';
77
import 'dart:io';
88

9+
import 'package:analyzer/dart/element/element.dart';
10+
import 'package:analyzer/file_system/file_system.dart' show ResourceProvider;
911
import 'package:analyzer/file_system/memory_file_system.dart';
1012
import 'package:analyzer/file_system/physical_file_system.dart';
13+
import 'package:analyzer/source/line_info.dart';
1114
import 'package:analyzer/src/test_utilities/mock_sdk.dart' as mock_sdk;
1215
import 'package:args/args.dart';
1316
import 'package:cli_util/cli_logging.dart';
1417
import 'package:http/http.dart' as http;
1518
import 'package:meta/meta.dart';
19+
import 'package:nnbd_migration/instrumentation.dart';
1620
import 'package:nnbd_migration/migration_cli.dart';
21+
import 'package:nnbd_migration/src/front_end/dartfix_listener.dart';
22+
import 'package:nnbd_migration/src/front_end/instrumentation_listener.dart';
23+
import 'package:nnbd_migration/src/front_end/migration_summary.dart';
1724
import 'package:nnbd_migration/src/front_end/non_nullable_fix.dart';
1825
import 'package:nnbd_migration/src/front_end/web/edit_details.dart';
1926
import 'package:nnbd_migration/src/front_end/web/file_details.dart';
@@ -29,10 +36,54 @@ main() {
2936
});
3037
}
3138

39+
/// Specialization of [InstrumentationListener] that generates artificial
40+
/// exceptions, so that we can test they are properly propagated to top level.
41+
class _ExceptionGeneratingInstrumentationListener
42+
extends InstrumentationListener {
43+
_ExceptionGeneratingInstrumentationListener(
44+
{MigrationSummary migrationSummary})
45+
: super(migrationSummary: migrationSummary);
46+
47+
@override
48+
void externalDecoratedType(Element element, DecoratedTypeInfo decoratedType) {
49+
if (element.name == 'print') {
50+
throw StateError('Artificial exception triggered');
51+
}
52+
super.externalDecoratedType(element, decoratedType);
53+
}
54+
}
55+
56+
/// Specialization of [NonNullableFix] that generates artificial exceptions, so
57+
/// that we can test they are properly propagated to top level.
58+
class _ExceptionGeneratingNonNullableFix extends NonNullableFix {
59+
_ExceptionGeneratingNonNullableFix(DartFixListener listener,
60+
ResourceProvider resourceProvider, LineInfo Function(String) getLineInfo,
61+
{List<String> included = const <String>[],
62+
int preferredPort,
63+
bool enablePreview = true,
64+
String summaryPath})
65+
: super(listener, resourceProvider, getLineInfo,
66+
included: included,
67+
preferredPort: preferredPort,
68+
enablePreview: enablePreview,
69+
summaryPath: summaryPath);
70+
71+
@override
72+
InstrumentationListener createInstrumentationListener(
73+
{MigrationSummary migrationSummary}) =>
74+
_ExceptionGeneratingInstrumentationListener(
75+
migrationSummary: migrationSummary);
76+
}
77+
3278
class _MigrationCli extends MigrationCli {
79+
/// If `true`, then an artifical exception should be generated when migration
80+
/// encounters a reference to the `print` function.
81+
final bool injectArtificialException;
82+
3383
Future<void> Function() _runWhilePreviewServerActive;
3484

35-
_MigrationCli(_MigrationCliTestBase test)
85+
_MigrationCli(_MigrationCliTestBase test,
86+
{this.injectArtificialException = false})
3687
: super(
3788
binaryName: 'nnbd_migration',
3889
loggerFactory: (isVerbose) => test.logger = _TestLogger(isVerbose),
@@ -50,6 +101,29 @@ class _MigrationCli extends MigrationCli {
50101
_runWhilePreviewServerActive = null;
51102
}
52103

104+
@override
105+
NonNullableFix createNonNullableFix(DartFixListener listener,
106+
ResourceProvider resourceProvider, LineInfo getLineInfo(String path),
107+
{List<String> included = const <String>[],
108+
int preferredPort,
109+
bool enablePreview = true,
110+
String summaryPath}) {
111+
if (injectArtificialException) {
112+
return _ExceptionGeneratingNonNullableFix(
113+
listener, resourceProvider, getLineInfo,
114+
included: included,
115+
preferredPort: preferredPort,
116+
enablePreview: enablePreview,
117+
summaryPath: summaryPath);
118+
} else {
119+
return super.createNonNullableFix(listener, resourceProvider, getLineInfo,
120+
included: included,
121+
preferredPort: preferredPort,
122+
enablePreview: enablePreview,
123+
summaryPath: summaryPath);
124+
}
125+
}
126+
53127
Future<void> runWithPreviewServer(
54128
ArgResults argResults, Future<void> callback()) async {
55129
_runWhilePreviewServerActive = callback;
@@ -362,6 +436,16 @@ int${migrated ? '?' : ''} f() => null;
362436
assertProjectContents(projectDir, simpleProject(migrated: true));
363437
}
364438

439+
test_lifecycle_exception_handling() async {
440+
var projectContents = simpleProject(sourceText: 'main() { print(0); }');
441+
var projectDir = await createProjectDir(projectContents);
442+
var cli = _createCli(injectArtificialException: true);
443+
expect(
444+
() async => runWithPreviewServer(cli, [projectDir], (url) async {}),
445+
throwsA(TypeMatcher<Error>().having((e) => e.toString(), 'toString',
446+
contains('Artificial exception triggered'))));
447+
}
448+
365449
test_lifecycle_ignore_errors_disable() async {
366450
var projectContents = simpleProject(sourceText: '''
367451
int f() => null
@@ -1334,9 +1418,10 @@ name: test
13341418
headers: {'Content-Type': 'application/json; charset=UTF-8'});
13351419
}
13361420

1337-
_MigrationCli _createCli() {
1421+
_MigrationCli _createCli({bool injectArtificialException = false}) {
13381422
mock_sdk.MockSdk(resourceProvider: resourceProvider);
1339-
return _MigrationCli(this);
1423+
return _MigrationCli(this,
1424+
injectArtificialException: injectArtificialException);
13401425
}
13411426

13421427
Future<String> _getHelpText({@required bool verbose}) async {

0 commit comments

Comments
 (0)