Skip to content

Commit 7269b79

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Update message for opt-out packages run with sound null safety
This groups the message for opt-out packages and mentions running 'pub outdated' to looked opted in versions. Closes #42464 Change-Id: Ib3bc411c5f3523af3672bed8837e953aaa551479 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153964 Reviewed-by: Dmitry Stefantsov <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent fecc816 commit 7269b79

38 files changed

+475
-19
lines changed

pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7872,6 +7872,46 @@ const MessageCode messageStrongModeNNBDButOptOut = const MessageCode(
78727872
message:
78737873
r"""A library can't opt out of null safety by default, when using sound null safety.""");
78747874

7875+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
7876+
const Template<
7877+
Message Function(
7878+
List<String>
7879+
_names)> templateStrongModeNNBDPackageOptOut = const Template<
7880+
Message Function(List<String> _names)>(
7881+
messageTemplate:
7882+
r"""Cannot run with sound null safety as one or more dependencies do not
7883+
support null safety:
7884+
7885+
#names
7886+
7887+
Run 'pub outdated --mode=null-safety' to determine if versions of your
7888+
dependencies supporting null safety are available.""",
7889+
withArguments: _withArgumentsStrongModeNNBDPackageOptOut);
7890+
7891+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
7892+
const Code<Message Function(List<String> _names)>
7893+
codeStrongModeNNBDPackageOptOut =
7894+
const Code<Message Function(List<String> _names)>(
7895+
"StrongModeNNBDPackageOptOut",
7896+
templateStrongModeNNBDPackageOptOut,
7897+
);
7898+
7899+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
7900+
Message _withArgumentsStrongModeNNBDPackageOptOut(List<String> _names) {
7901+
if (_names.isEmpty) throw 'No names provided';
7902+
String names = itemizeNames(_names);
7903+
return new Message(codeStrongModeNNBDPackageOptOut,
7904+
message:
7905+
"""Cannot run with sound null safety as one or more dependencies do not
7906+
support null safety:
7907+
7908+
${names}
7909+
7910+
Run 'pub outdated --mode=null-safety' to determine if versions of your
7911+
dependencies supporting null safety are available.""",
7912+
arguments: {'names': _names});
7913+
}
7914+
78757915
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
78767916
const Code<Null> codeSuperAsExpression = messageSuperAsExpression;
78777917

pkg/front_end/lib/src/fasta/kernel/kernel_target.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ import '../messages.dart'
9797
messageConstConstructorNonFinalField,
9898
messageConstConstructorNonFinalFieldCause,
9999
messageConstConstructorRedirectionToNonConst,
100-
messageStrongModeNNBDButOptOut,
101100
noLength,
102101
templateFieldNonNullableNotInitializedByConstructorError,
103102
templateFieldNonNullableWithoutInitializerError,
@@ -255,7 +254,7 @@ class KernelTarget extends TargetImplementation {
255254
if (loader.nnbdMode == NnbdMode.Strong ||
256255
loader.nnbdMode == NnbdMode.Agnostic) {
257256
if (!builder.isNonNullableByDefault) {
258-
loader.addProblem(messageStrongModeNNBDButOptOut, -1, 1, fileUri);
257+
loader.registerStrongOptOutLibrary(builder);
259258
}
260259
}
261260
return builder;

pkg/front_end/lib/src/fasta/source/source_library_builder.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,8 +460,12 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
460460
// In strong and agnostic mode, the language version is not allowed to
461461
// opt a library out of nnbd.
462462
if (!isNonNullableByDefault) {
463-
addPostponedProblem(messageStrongModeNNBDButOptOut,
464-
_languageVersion.charOffset, _languageVersion.charCount, fileUri);
463+
if (_languageVersion.isExplicit) {
464+
addPostponedProblem(messageStrongModeNNBDButOptOut,
465+
_languageVersion.charOffset, _languageVersion.charCount, fileUri);
466+
} else {
467+
loader.registerStrongOptOutLibrary(this);
468+
}
465469
_languageVersion = new InvalidLanguageVersion(
466470
fileUri,
467471
_languageVersion.charOffset,

pkg/front_end/lib/src/fasta/source/source_loader.dart

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
2525
ScannerResult,
2626
Token,
2727
scan;
28+
import 'package:front_end/src/api_prototype/experimental_flags.dart';
2829

2930
import 'package:kernel/ast.dart'
3031
show
@@ -53,6 +54,8 @@ import 'package:kernel/core_types.dart' show CoreTypes;
5354

5455
import 'package:kernel/reference_from_index.dart' show ReferenceFromIndex;
5556

57+
import 'package:package_config/package_config.dart';
58+
5659
import '../../api_prototype/file_system.dart';
5760

5861
import '../../base/common.dart';
@@ -90,6 +93,7 @@ import '../fasta_codes.dart'
9093
messageObjectImplements,
9194
messageObjectMixesIn,
9295
messagePartOrphan,
96+
messageStrongModeNNBDButOptOut,
9397
messageTypedefCause,
9498
messageTypedefUnaliasedTypeCause,
9599
noLength,
@@ -107,6 +111,7 @@ import '../fasta_codes.dart'
107111
templateIllegalMixinDueToConstructorsCause,
108112
templateInternalProblemUriMissingScheme,
109113
templateSourceOutlineSummary,
114+
templateStrongModeNNBDPackageOptOut,
110115
templateUntranslatableUri;
111116

112117
import '../kernel/kernel_builder.dart'
@@ -326,6 +331,79 @@ class SourceLoader extends Loader {
326331
}
327332
}
328333

334+
Set<LibraryBuilder> _strongOptOutLibraries;
335+
336+
void registerStrongOptOutLibrary(LibraryBuilder libraryBuilder) {
337+
_strongOptOutLibraries ??= {};
338+
_strongOptOutLibraries.add(libraryBuilder);
339+
}
340+
341+
@override
342+
Future<Null> buildOutlines() async {
343+
await super.buildOutlines();
344+
345+
if (_strongOptOutLibraries != null) {
346+
// We have libraries that are opted out in strong mode "non-explicitly",
347+
// that is, either implicitly through the package version or loaded from
348+
// .dill as opt out.
349+
//
350+
// To reduce the verbosity of the error messages we try to reduce the
351+
// message to only include the package name once for packages that are
352+
// opted out.
353+
//
354+
// We use the current package config to retrieve the package based
355+
// language version to determine whether the package as a whole is opted
356+
// out. If so, we only include the package name and not the library uri
357+
// in the message. For package libraries with no corresponding package
358+
// config we include each library uri in the message. For non-package
359+
// libraries with no corresponding package config we generate a message
360+
// per library.
361+
Map<String, List<LibraryBuilder>> libraryByPackage = {};
362+
for (LibraryBuilder libraryBuilder in _strongOptOutLibraries) {
363+
Package package =
364+
target.uriTranslator.getPackage(libraryBuilder.importUri);
365+
366+
if (package != null &&
367+
package.languageVersion != null &&
368+
package.languageVersion is! InvalidLanguageVersion) {
369+
Version version = new Version(
370+
package.languageVersion.major, package.languageVersion.minor);
371+
if (version < enableNonNullableVersion) {
372+
(libraryByPackage[package?.name] ??= []).add(libraryBuilder);
373+
continue;
374+
}
375+
}
376+
if (libraryBuilder.importUri.scheme == 'package') {
377+
(libraryByPackage[null] ??= []).add(libraryBuilder);
378+
} else {
379+
// Emit a message that doesn't mention running 'pub'.
380+
addProblem(messageStrongModeNNBDButOptOut, -1, noLength,
381+
libraryBuilder.fileUri);
382+
}
383+
}
384+
if (libraryByPackage.isNotEmpty) {
385+
List<String> dependencies = [];
386+
libraryByPackage.forEach((String name, List<LibraryBuilder> libraries) {
387+
if (name != null) {
388+
dependencies.add('package:$name');
389+
} else {
390+
for (LibraryBuilder libraryBuilder in libraries) {
391+
dependencies.add(libraryBuilder.importUri.toString());
392+
}
393+
}
394+
});
395+
// Emit a message that suggests to run 'pub' to check for opted in
396+
// versions of the packages.
397+
addProblem(
398+
templateStrongModeNNBDPackageOptOut.withArguments(dependencies),
399+
-1,
400+
-1,
401+
null);
402+
_strongOptOutLibraries = null;
403+
}
404+
}
405+
}
406+
329407
List<int> getSource(List<int> bytes) {
330408
// bytes is 0-terminated. We don't want that included.
331409
if (bytes is Uint8List) {

pkg/front_end/messages.status

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
# Note that test/spelling: Status will have no effect. Spelling errors can
66
# always be fixed by either spelling correctly or updating the dictionary.
77

8-
StrongModeNNBDButOptOut/analyzerCode: Fail
9-
StrongModeNNBDButOptOut/example: Fail
10-
118
AbstractClassInstantiation/example: Fail
129
AbstractClassMember/part_wrapped_script5: Fail
1310
AbstractClassMember/part_wrapped_script6: Fail
@@ -638,6 +635,10 @@ SourceOutlineSummary/example: Fail
638635
SpreadMapEntryTypeMismatch/analyzerCode: Fail # There's no analyzer code for that error yet.
639636
SpreadTypeMismatch/analyzerCode: Fail # There's no analyzer code for that error yet.
640637
StackOverflow/example: Fail
638+
StrongModeNNBDButOptOut/analyzerCode: Fail
639+
StrongModeNNBDButOptOut/example: Fail
640+
StrongModeNNBDPackageOptOut/analyzerCode: Fail
641+
StrongModeNNBDPackageOptOut/example: Fail
641642
SuperAsExpression/example: Fail
642643
SuperAsIdentifier/example: Fail
643644
SuperclassHasNoDefaultConstructor/example: Fail

pkg/front_end/messages.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,16 @@ Unspecified:
11881188
StrongModeNNBDButOptOut:
11891189
template: "A library can't opt out of null safety by default, when using sound null safety."
11901190

1191+
StrongModeNNBDPackageOptOut:
1192+
template: |
1193+
Cannot run with sound null safety as one or more dependencies do not
1194+
support null safety:
1195+
1196+
#names
1197+
1198+
Run 'pub outdated --mode=null-safety' to determine if versions of your
1199+
dependencies supporting null safety are available.
1200+
11911201
AbstractNotSync:
11921202
template: "Abstract methods can't use 'async', 'async*', or 'sync*'."
11931203
analyzerCode: NON_SYNC_ABSTRACT_METHOD

pkg/front_end/test/fasta/testing/suite.dart

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ class FastaContext extends ChainContext with MatchContext {
203203
final Map<Component, List<Iterable<String>>> componentToDiagnostics =
204204
<Component, List<Iterable<String>>>{};
205205
final Uri platformBinaries;
206-
final Map<Uri, UriTranslator> _uriTranslators = {};
206+
final Map<UriConfiguration, UriTranslator> _uriTranslators = {};
207207
final Map<Uri, TestOptions> _testOptions = {};
208208
final Map<Uri, LinkDependenciesOptions> _linkDependencies = {};
209209
final Map<Uri, Uri> _librariesJson = {};
@@ -364,9 +364,8 @@ class FastaContext extends ChainContext with MatchContext {
364364

365365
Future<UriTranslator> computeUriTranslator(
366366
TestDescription description) async {
367-
Uri librariesSpecificationUri =
368-
computeLibrariesSpecificationUri(description);
369-
UriTranslator uriTranslator = _uriTranslators[librariesSpecificationUri];
367+
UriConfiguration uriConfiguration = computeUriConfiguration(description);
368+
UriTranslator uriTranslator = _uriTranslators[uriConfiguration];
370369
if (uriTranslator == null) {
371370
Uri sdk = Uri.base.resolve("sdk/");
372371
Uri packages = Uri.base.resolve(".packages");
@@ -376,7 +375,7 @@ class FastaContext extends ChainContext with MatchContext {
376375
throw message.plainTextFormatted.join("\n");
377376
}
378377
..sdkRoot = sdk
379-
..packagesFileUri = packages
378+
..packagesFileUri = uriConfiguration.packageConfigUri ?? packages
380379
..environmentDefines = {}
381380
..experimentalFlags =
382381
testOptions.computeExperimentalFlags(experimentalFlags)
@@ -385,14 +384,15 @@ class FastaContext extends ChainContext with MatchContext {
385384
: (testOptions.nnbdAgnosticMode
386385
? NnbdMode.Agnostic
387386
: NnbdMode.Strong)
388-
..librariesSpecificationUri = librariesSpecificationUri;
387+
..librariesSpecificationUri =
388+
uriConfiguration.librariesSpecificationUri;
389389
if (testOptions.overwriteCurrentSdkVersion != null) {
390390
compilerOptions.currentSdkVersion =
391391
testOptions.overwriteCurrentSdkVersion;
392392
}
393393
ProcessedOptions options = new ProcessedOptions(options: compilerOptions);
394394
uriTranslator = await options.getUriTranslator();
395-
_uriTranslators[librariesSpecificationUri] = uriTranslator;
395+
_uriTranslators[uriConfiguration] = uriTranslator;
396396
}
397397
return uriTranslator;
398398
}
@@ -431,11 +431,15 @@ class FastaContext extends ChainContext with MatchContext {
431431
}
432432
nnbdMode = NnbdMode.Weak;
433433
} else {
434-
File f = new File.fromUri(description.uri.resolve(line));
435-
if (!f.existsSync()) {
436-
throw new UnsupportedError("No file found: $f ($line)");
434+
Uri uri = description.uri.resolve(line);
435+
if (uri.scheme != 'package') {
436+
File f = new File.fromUri(uri);
437+
if (!f.existsSync()) {
438+
throw new UnsupportedError("No file found: $f ($line)");
439+
}
440+
uri = f.uri;
437441
}
438-
content.add(f.uri);
442+
content.add(uri);
439443
}
440444
}
441445
}
@@ -461,6 +465,20 @@ class FastaContext extends ChainContext with MatchContext {
461465
}
462466
}
463467

468+
/// Custom package config used for [description].
469+
Uri computePackageConfigUri(TestDescription description) {
470+
Uri packageConfig =
471+
description.uri.resolve(".dart_tool/package_config.json");
472+
return new File.fromUri(packageConfig).existsSync() ? packageConfig : null;
473+
}
474+
475+
UriConfiguration computeUriConfiguration(TestDescription description) {
476+
Uri librariesSpecificationUri =
477+
computeLibrariesSpecificationUri(description);
478+
Uri packageConfigUri = computePackageConfigUri(description);
479+
return new UriConfiguration(librariesSpecificationUri, packageConfigUri);
480+
}
481+
464482
Expectation get verificationError => expectationSet["VerificationError"];
465483

466484
Future ensurePlatformUris() async {
@@ -666,7 +684,7 @@ class Outline extends Step<TestDescription, ComponentResult, FastaContext> {
666684
linkDependenciesOptions.component = p;
667685
List<Library> keepLibraries = new List<Library>();
668686
for (Library lib in p.libraries) {
669-
if (linkDependenciesOptions.content.contains(lib.fileUri)) {
687+
if (linkDependenciesOptions.content.contains(lib.importUri)) {
670688
keepLibraries.add(lib);
671689
}
672690
}
@@ -896,3 +914,22 @@ class MatchHierarchy
896914
".hierarchy.expect", "$sb", uri, result);
897915
}
898916
}
917+
918+
class UriConfiguration {
919+
final Uri librariesSpecificationUri;
920+
final Uri packageConfigUri;
921+
922+
UriConfiguration(this.librariesSpecificationUri, this.packageConfigUri);
923+
924+
@override
925+
int get hashCode =>
926+
librariesSpecificationUri.hashCode * 13 + packageConfigUri.hashCode * 17;
927+
928+
@override
929+
bool operator ==(Object other) {
930+
if (identical(this, other)) return true;
931+
return other is UriConfiguration &&
932+
librariesSpecificationUri == other.librariesSpecificationUri &&
933+
packageConfigUri == other.packageConfigUri;
934+
}
935+
}

pkg/front_end/test/spell_checking_list_code.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,7 @@ subst
10521052
substed
10531053
substitutes
10541054
substitutor
1055+
suggests
10551056
sum
10561057
summarizing
10571058
superclasses
@@ -1223,6 +1224,7 @@ vary
12231224
vb
12241225
vector
12251226
vegorov
1227+
verbosity
12261228
versa
12271229
vice
12281230
violated

pkg/front_end/test/spell_checking_list_messages.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ num1%.3ms
4545
o
4646
opt
4747
opts
48+
outdated
4849
part(s)
4950
patch(es)
5051
pubspec.yaml
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"configVersion": 2,
3+
"packages": [
4+
{
5+
"name": "opt_out_package",
6+
"rootUri": "../opt_out_package/lib/",
7+
"languageVersion": "2.7"
8+
},
9+
{
10+
"name": "opt_in_package",
11+
"rootUri": "../opt_in_package/lib/"
12+
}
13+
14+
]
15+
}

0 commit comments

Comments
 (0)