Skip to content

Commit 6b40b26

Browse files
[nnbd_migration] Print warning when SDK_PATH is set and things go wrong.
Also clean up sanity checking code a little bit. Change-Id: I4274dad42687a4dc419090d656ec56168c982c29 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150661 Commit-Queue: Mike Fairhurst <[email protected]> Reviewed-by: Paul Berry <[email protected]>
1 parent 6428bab commit 6b40b26

File tree

5 files changed

+101
-40
lines changed

5 files changed

+101
-40
lines changed

pkg/nnbd_migration/lib/migration_cli.dart

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ import 'package:args/command_runner.dart';
2525
import 'package:cli_util/cli_logging.dart';
2626
import 'package:meta/meta.dart';
2727
import 'package:nnbd_migration/src/edit_plan.dart';
28+
import 'package:nnbd_migration/src/exceptions.dart';
2829
import 'package:nnbd_migration/src/front_end/dartfix_listener.dart';
2930
import 'package:nnbd_migration/src/front_end/driver_provider_impl.dart';
3031
import 'package:nnbd_migration/src/front_end/non_nullable_fix.dart';
32+
import 'package:nnbd_migration/src/messages.dart';
3133
import 'package:nnbd_migration/src/utilities/json.dart' as json;
3234
import 'package:nnbd_migration/src/utilities/source_edit_diff_formatter.dart';
3335
import 'package:path/path.dart' show Context;
@@ -236,6 +238,10 @@ class MigrationCli {
236238

237239
final Map<String, LineInfo> lineInfo = {};
238240

241+
/// The environment variables, tracked to help users debug if SDK_PATH was
242+
/// specified and that resulted in any [ExperimentStatusException]s.
243+
final Map<String, String> _environmentVariables;
244+
239245
DartFixListener _dartFixListener;
240246

241247
_FixCodeProcessor _fixCodeProcessor;
@@ -246,15 +252,17 @@ class MigrationCli {
246252

247253
bool _hasAnalysisErrors = false;
248254

249-
MigrationCli(
250-
{@required this.binaryName,
251-
@visibleForTesting this.loggerFactory = _defaultLoggerFactory,
252-
@visibleForTesting this.defaultSdkPathOverride,
253-
@visibleForTesting ResourceProvider resourceProvider,
254-
@visibleForTesting this.processManager = const ProcessManager.system()})
255-
: logger = loggerFactory(false),
255+
MigrationCli({
256+
@required this.binaryName,
257+
@visibleForTesting this.loggerFactory = _defaultLoggerFactory,
258+
@visibleForTesting this.defaultSdkPathOverride,
259+
@visibleForTesting ResourceProvider resourceProvider,
260+
@visibleForTesting this.processManager = const ProcessManager.system(),
261+
@visibleForTesting Map<String, String> environmentVariables,
262+
}) : logger = loggerFactory(false),
256263
resourceProvider =
257-
resourceProvider ?? PhysicalResourceProvider.INSTANCE;
264+
resourceProvider ?? PhysicalResourceProvider.INSTANCE,
265+
_environmentVariables = environmentVariables ?? Platform.environment;
258266

259267
@visibleForTesting
260268
DriverBasedAnalysisContext get analysisContext {
@@ -437,8 +445,12 @@ class MigrationCli {
437445
await _fixCodeProcessor.runFirstPhase();
438446
_fixCodeProcessor._progressBar.clear();
439447
_checkForErrors();
440-
} on StateError catch (e) {
448+
} on ExperimentStatusException catch (e) {
441449
logger.stdout(e.toString());
450+
final sdkPathVar = _environmentVariables['SDK_PATH'];
451+
if (sdkPathVar != null) {
452+
logger.stdout('$sdkPathEnvironmentVariableSet: $sdkPathVar');
453+
}
442454
exitCode = 1;
443455
}
444456
if (exitCode != null) return;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import 'package:analyzer/dart/analysis/features.dart';
2+
import 'package:analyzer/dart/analysis/results.dart';
3+
import 'package:nnbd_migration/src/messages.dart';
4+
5+
/// A [StateError] specific to the ways that the NNBD experiment can be
6+
/// misconfigured which may prevent the tool from working.
7+
class ExperimentStatusException extends StateError {
8+
/// A file included in the migration dir has already been migrated.
9+
ExperimentStatusException.migratedAlready(String path)
10+
: super('$migratedAlready: $path');
11+
12+
/// The SDK was analyzed without NNBD semantics.
13+
ExperimentStatusException.sdkExperimentDisabled() : super(nnbdExperimentOff);
14+
15+
/// The SDK does not contain the NNBD sources, it is the pre-unfork copy.
16+
ExperimentStatusException.sdkPreforkSources() : super(sdkNnbdOff);
17+
18+
/// Throw an [ExperimentStatusException] if the [result] seems to have
19+
/// incorrectly configured experiment flags/nnbd sources.
20+
static void sanityCheck(ResolvedUnitResult result) {
21+
final equalsParamType = result.typeProvider.objectType
22+
.getMethod('==')
23+
.parameters[0]
24+
.type
25+
.getDisplayString(withNullability: true);
26+
if (equalsParamType == 'Object*') {
27+
throw ExperimentStatusException.sdkExperimentDisabled();
28+
}
29+
30+
if (equalsParamType != 'Object') {
31+
throw ExperimentStatusException.sdkPreforkSources();
32+
}
33+
34+
if (result.unit.featureSet.isEnabled(Feature.non_nullable)) {
35+
// TODO(mfairhurst): Allow for skipping already migrated compilation units.
36+
throw ExperimentStatusException.migratedAlready(result.path);
37+
}
38+
}
39+
}

pkg/nnbd_migration/lib/src/messages.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ const String migratedAlready =
77
const String nnbdExperimentOff =
88
'Analyzer seems to need the nnbd experiment on in the SDK.';
99
const String sdkNnbdOff = 'Analysis seems to have an SDK without NNBD enabled.';
10+
const String sdkPathEnvironmentVariableSet =
11+
r'Note: $SDK_PATH environment variable is set and may point to outdated '
12+
'dart:core sources';

pkg/nnbd_migration/lib/src/nullability_migration_impl.dart

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import 'package:nnbd_migration/src/edge_builder.dart';
1717
import 'package:nnbd_migration/src/edit_plan.dart';
1818
import 'package:nnbd_migration/src/fix_aggregator.dart';
1919
import 'package:nnbd_migration/src/fix_builder.dart';
20-
import 'package:nnbd_migration/src/messages.dart';
20+
import 'package:nnbd_migration/src/exceptions.dart';
2121
import 'package:nnbd_migration/src/node_builder.dart';
2222
import 'package:nnbd_migration/src/nullability_node.dart';
2323
import 'package:nnbd_migration/src/postmortem_file.dart';
@@ -104,7 +104,7 @@ class NullabilityMigrationImpl implements NullabilityMigration {
104104

105105
@override
106106
void finalizeInput(ResolvedUnitResult result) {
107-
_sanityCheck(result);
107+
ExperimentStatusException.sanityCheck(result);
108108
if (!_propagated) {
109109
_propagated = true;
110110
_graph.propagate(_postmortemFileWriter);
@@ -160,7 +160,7 @@ class NullabilityMigrationImpl implements NullabilityMigration {
160160
}
161161

162162
void prepareInput(ResolvedUnitResult result) {
163-
_sanityCheck(result);
163+
ExperimentStatusException.sanityCheck(result);
164164
if (_variables == null) {
165165
_variables = Variables(_graph, result.typeProvider, _getLineInfo,
166166
instrumentation: _instrumentation,
@@ -184,7 +184,7 @@ class NullabilityMigrationImpl implements NullabilityMigration {
184184
}
185185

186186
void processInput(ResolvedUnitResult result) {
187-
_sanityCheck(result);
187+
ExperimentStatusException.sanityCheck(result);
188188
var unit = result.unit;
189189
try {
190190
DecoratedTypeParameterBounds.current = _decoratedTypeParameterBounds;
@@ -207,26 +207,6 @@ class NullabilityMigrationImpl implements NullabilityMigration {
207207
_graph.update(_postmortemFileWriter);
208208
}
209209

210-
void _sanityCheck(ResolvedUnitResult result) {
211-
final equalsParamType = result.typeProvider.objectType
212-
.getMethod('==')
213-
.parameters[0]
214-
.type
215-
.getDisplayString(withNullability: true);
216-
if (equalsParamType == 'Object*') {
217-
throw StateError(nnbdExperimentOff);
218-
}
219-
220-
if (equalsParamType != 'Object') {
221-
throw StateError(sdkNnbdOff);
222-
}
223-
224-
if (result.unit.featureSet.isEnabled(Feature.non_nullable)) {
225-
// TODO(jcollins-g): Allow for skipping already migrated compilation units.
226-
throw StateError('$migratedAlready: ${result.path}');
227-
}
228-
}
229-
230210
static Location _computeLocation(
231211
LineInfo lineInfo, SourceEdit edit, Source source) {
232212
final locationInfo = lineInfo.getLocation(edit.offset);

pkg/nnbd_migration/test/migration_cli_test.dart

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import 'package:nnbd_migration/src/front_end/non_nullable_fix.dart';
2525
import 'package:nnbd_migration/src/front_end/web/edit_details.dart';
2626
import 'package:nnbd_migration/src/front_end/web/file_details.dart';
2727
import 'package:nnbd_migration/src/front_end/web/navigation_tree.dart';
28+
import 'package:nnbd_migration/src/messages.dart' as messages;
2829
import 'package:path/path.dart' as path;
2930
import 'package:test/test.dart';
3031
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -81,14 +82,16 @@ class _MigrationCli extends MigrationCli {
8182
Future<void> Function() _runWhilePreviewServerActive;
8283

8384
_MigrationCli(_MigrationCliTestBase test,
84-
{this.injectArtificialException = false})
85+
{this.injectArtificialException = false,
86+
Map<String, String> environmentVariables})
8587
: super(
8688
binaryName: 'nnbd_migration',
8789
loggerFactory: (isVerbose) => test.logger = _TestLogger(isVerbose),
8890
defaultSdkPathOverride:
8991
test.resourceProvider.convertPath(mock_sdk.sdkRoot),
9092
resourceProvider: test.resourceProvider,
91-
processManager: test.processManager);
93+
processManager: test.processManager,
94+
environmentVariables: environmentVariables);
9295

9396
@override
9497
Future<void> blockUntilSignalInterrupt() async {
@@ -141,6 +144,8 @@ mixin _MigrationCliTestMethods on _MigrationCliTestBase {
141144
@override
142145
/*late*/ _TestLogger logger;
143146

147+
Map<String, String> environmentVariables = {};
148+
144149
final hasVerboseHelpMessage = contains('for verbose help output');
145150

146151
final hasUsageText = contains('Usage: nnbd_migration');
@@ -281,6 +286,7 @@ mixin _MigrationCliTestMethods on _MigrationCliTestBase {
281286

282287
void setUp() {
283288
resourceProvider.newFolder(resourceProvider.pathContext.current);
289+
environmentVariables.clear();
284290
}
285291

286292
Map<String, String> simpleProject(
@@ -343,10 +349,30 @@ int${migrated ? '?' : ''} f() => null;
343349
await cli.run(MigrationCli.createParser().parse([projectDir]));
344350
assertErrorExit(cli, withUsage: false);
345351
var output = logger.stdoutBuffer.toString();
346-
expect(
347-
output,
348-
contains(
349-
'Bad state: Analysis seems to have an SDK without NNBD enabled'));
352+
expect(output, contains(messages.sdkNnbdOff));
353+
}
354+
355+
test_detect_old_sdk_environment_variable() async {
356+
environmentVariables['SDK_PATH'] = '/fake-old-sdk-path';
357+
var cli = _createCli();
358+
// Alter the mock SDK, changing the signature of Object.operator== to match
359+
// the signature that was present prior to NNBD. (This is what the
360+
// migration tool uses to detect an old SDK).
361+
var coreLib = resourceProvider.getFile(
362+
resourceProvider.convertPath('${mock_sdk.sdkRoot}/lib/core/core.dart'));
363+
var oldCoreLibText = coreLib.readAsStringSync();
364+
var newCoreLibText = oldCoreLibText.replaceAll(
365+
'external bool operator ==(Object other)',
366+
'external bool operator ==(dynamic other)');
367+
expect(newCoreLibText, isNot(oldCoreLibText));
368+
coreLib.writeAsStringSync(newCoreLibText);
369+
var projectDir = await createProjectDir(simpleProject());
370+
await cli.run(MigrationCli.createParser().parse([projectDir]));
371+
assertErrorExit(cli, withUsage: false);
372+
var output = logger.stdoutBuffer.toString();
373+
expect(output, contains(messages.sdkNnbdOff));
374+
expect(output, contains(messages.sdkPathEnvironmentVariableSet));
375+
expect(output, contains(environmentVariables['SDK_PATH']));
350376
}
351377

352378
test_flag_apply_changes_default() {
@@ -1547,7 +1573,8 @@ name: test
15471573
_MigrationCli _createCli({bool injectArtificialException = false}) {
15481574
mock_sdk.MockSdk(resourceProvider: resourceProvider);
15491575
return _MigrationCli(this,
1550-
injectArtificialException: injectArtificialException);
1576+
injectArtificialException: injectArtificialException,
1577+
environmentVariables: environmentVariables);
15511578
}
15521579

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

0 commit comments

Comments
 (0)