[cfe] Only use experimental release version when flag is not on by default
Change-Id: I06267c6d3f0e5abb289e25fde8098aa0e3bead34
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166844
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/analysis_options_no_lints.yaml b/pkg/front_end/analysis_options_no_lints.yaml
index 6bbd1ac..25f50ec 100644
--- a/pkg/front_end/analysis_options_no_lints.yaml
+++ b/pkg/front_end/analysis_options_no_lints.yaml
@@ -4,16 +4,17 @@
analyzer:
exclude:
- - test/analyser_ignored/**
- - test/extensions/data/**
- parser_testcases/**
- - testcases/**
+ - test/analyser_ignored/**
+ - test/enable_non_nullable/data/**
+ - test/extensions/data/**
- test/id_testing/data/**
- test/language_versioning/data/**
- test/patching/data/**
- test/predicates/data/**
- test/static_types/data/**
- test/text_representation/data/**
+ - testcases/**
errors:
# Allow having TODOs in the code
todo: ignore
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 23cf4a1..7914ed3 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -24,6 +24,9 @@
expiredExperimentalFlags,
parseExperimentalFlag;
+import 'experimental_flags.dart' as flags
+ show getExperimentEnabledVersionInLibrary, isExperimentEnabledInLibrary;
+
import 'file_system.dart' show FileSystem;
import 'standard_file_system.dart' show StandardFileSystem;
@@ -132,6 +135,7 @@
/// Features not mentioned in the map will have their default value.
Map<ExperimentalFlag, bool> experimentalFlags = <ExperimentalFlag, bool>{};
+ Map<ExperimentalFlag, bool> defaultExperimentFlagsForTesting;
AllowedExperimentalFlags allowedExperimentalFlagsForTesting;
Map<ExperimentalFlag, Version> experimentEnabledVersionForTesting;
Map<ExperimentalFlag, Version> experimentReleasedVersionForTesting;
@@ -248,6 +252,23 @@
/// compiling the platform dill.
bool emitDeps = true;
+ bool isExperimentEnabledInLibrary(ExperimentalFlag flag, Uri importUri) {
+ return flags.isExperimentEnabledInLibrary(flag, importUri,
+ defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
+ experimentalFlags: experimentalFlags,
+ allowedExperimentalFlags: allowedExperimentalFlagsForTesting);
+ }
+
+ Version getExperimentEnabledVersionInLibrary(
+ ExperimentalFlag flag, Uri importUri) {
+ return flags.getExperimentEnabledVersionInLibrary(flag, importUri,
+ defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
+ allowedExperimentalFlags: allowedExperimentalFlagsForTesting,
+ experimentEnabledVersionForTesting: experimentEnabledVersionForTesting,
+ experimentReleasedVersionForTesting:
+ experimentReleasedVersionForTesting);
+ }
+
bool equivalent(CompilerOptions other,
{bool ignoreOnDiagnostic: true,
bool ignoreVerbose: true,
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
index 582b79e..9e21c12 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
@@ -83,7 +83,8 @@
/// defines the identity of a library, for instance `dart:core`, `package:foo`,
/// or `file:///path/dir/file.dart`.
bool isExperimentEnabledInLibrary(ExperimentalFlag flag, Uri canonicalUri,
- {Map<ExperimentalFlag, bool> experimentalFlags,
+ {Map<ExperimentalFlag, bool> defaultExperimentFlagsForTesting,
+ Map<ExperimentalFlag, bool> experimentalFlags,
AllowedExperimentalFlags allowedExperimentalFlags}) {
assert(defaultExperimentalFlags.containsKey(flag),
"No default value for $flag.");
@@ -96,6 +97,9 @@
if (experimentalFlags != null) {
enabled = experimentalFlags[flag];
}
+ if (defaultExperimentFlagsForTesting != null) {
+ enabled ??= defaultExperimentFlagsForTesting[flag];
+ }
enabled ??= defaultExperimentalFlags[flag];
if (!enabled) {
allowedExperimentalFlags ??= defaultAllowedExperimentalFlags;
@@ -119,13 +123,51 @@
return enabled;
}
-Version getExperimentEnabledVersion(ExperimentalFlag flag,
- {Map<ExperimentalFlag, Version> experimentReleasedVersionForTesting}) {
- Version version;
- if (experimentReleasedVersionForTesting != null) {
- version = experimentReleasedVersionForTesting[flag];
+/// Returns the version in which [flag] is enabled for the library with the
+/// [canonicalUri].
+Version getExperimentEnabledVersionInLibrary(
+ ExperimentalFlag flag, Uri canonicalUri,
+ {AllowedExperimentalFlags allowedExperimentalFlags,
+ Map<ExperimentalFlag, bool> defaultExperimentFlagsForTesting,
+ Map<ExperimentalFlag, Version> experimentEnabledVersionForTesting,
+ Map<ExperimentalFlag, Version> experimentReleasedVersionForTesting}) {
+ allowedExperimentalFlags ??= defaultAllowedExperimentalFlags;
+
+ Set<ExperimentalFlag> allowedFlags;
+ if (canonicalUri.scheme == 'dart') {
+ allowedFlags = allowedExperimentalFlags.forSdkLibrary(canonicalUri.path);
+ } else if (canonicalUri.scheme == 'package') {
+ int index = canonicalUri.path.indexOf('/');
+ String packageName;
+ if (index >= 0) {
+ packageName = canonicalUri.path.substring(0, index);
+ } else {
+ packageName = canonicalUri.path;
+ }
+ allowedFlags = allowedExperimentalFlags.forPackage(packageName);
}
- version ??= experimentReleasedVersion[flag];
- assert(version != null, "No version for enabling $flag.");
+ Version version;
+ bool enabledByDefault;
+ if (defaultExperimentFlagsForTesting != null) {
+ enabledByDefault = defaultExperimentFlagsForTesting[flag];
+ }
+ enabledByDefault ??= defaultExperimentalFlags[flag];
+ if (!enabledByDefault ||
+ allowedFlags != null && allowedFlags.contains(flag)) {
+ // If the feature is not enabled by default or is enabled by the allowed
+ // list use the experiment release version.
+ if (experimentReleasedVersionForTesting != null) {
+ version = experimentReleasedVersionForTesting[flag];
+ }
+ version ??= experimentReleasedVersion[flag];
+ } else {
+ // If the feature is enabled by default and is not enabled by the allowed
+ // list use the enabled version.
+ if (experimentEnabledVersionForTesting != null) {
+ version = experimentEnabledVersionForTesting[flag];
+ }
+ version ??= experimentEnabledVersion[flag];
+ }
+ assert(version != null, "No version for enabling $flag in $canonicalUri.");
return version;
}
diff --git a/pkg/front_end/lib/src/api_prototype/language_version.dart b/pkg/front_end/lib/src/api_prototype/language_version.dart
index a77b716..02db78f 100644
--- a/pkg/front_end/lib/src/api_prototype/language_version.dart
+++ b/pkg/front_end/lib/src/api_prototype/language_version.dart
@@ -23,8 +23,7 @@
import 'compiler_options.dart' show CompilerOptions;
-import 'experimental_flags.dart'
- show ExperimentalFlag, experimentReleasedVersion;
+import 'experimental_flags.dart' show ExperimentalFlag;
import 'file_system.dart' show FileSystem, FileSystemException;
/// Gets the language version for a specific URI.
@@ -34,7 +33,8 @@
/// specifies a language version that's too high).
///
/// The language version returned is valid though.
-Future<Version> languageVersionForUri(Uri uri, CompilerOptions options) async {
+Future<VersionAndPackageUri> languageVersionForUri(
+ Uri uri, CompilerOptions options) async {
return await CompilerContext.runWithOptions(
new ProcessedOptions(options: options, inputs: [uri]), (context) async {
// Get largest valid version / default version.
@@ -65,6 +65,13 @@
fileUri = uri;
package = uriTranslator.packages.packageOf(uri);
}
+ Uri packageUri = uri;
+ if (packageUri.scheme != 'dart' &&
+ packageUri.scheme != 'package' &&
+ package != null &&
+ package.name != null) {
+ packageUri = new Uri(scheme: 'package', path: package.name);
+ }
// Check file content for @dart annotation.
int major;
@@ -102,7 +109,7 @@
}
if (major != null && minor != null) {
// The file decided. Return result.
- return new Version(major, minor);
+ return new VersionAndPackageUri(new Version(major, minor), packageUri);
}
// Check package.
@@ -119,11 +126,13 @@
}
if (major != null && minor != null) {
// The package decided. Return result.
- return new Version(major, minor);
+ return new VersionAndPackageUri(new Version(major, minor), packageUri);
}
// Return default.
- return new Version(currentSdkVersionMajor, currentSdkVersionMinor);
+ return new VersionAndPackageUri(
+ new Version(currentSdkVersionMajor, currentSdkVersionMinor),
+ packageUri);
});
}
@@ -134,6 +143,16 @@
// This method is here in order to use the opt out hack here for test
// sources.
if (SourceLibraryBuilder.isOptOutTest(uri)) return true;
- Version uriVersion = await languageVersionForUri(uri, options);
- return (uriVersion < experimentReleasedVersion[ExperimentalFlag.nonNullable]);
+ VersionAndPackageUri versionAndLibraryUri =
+ await languageVersionForUri(uri, options);
+ return (versionAndLibraryUri.version <
+ options.getExperimentEnabledVersionInLibrary(
+ ExperimentalFlag.nonNullable, versionAndLibraryUri.packageUri));
+}
+
+class VersionAndPackageUri {
+ final Version version;
+ final Uri packageUri;
+
+ VersionAndPackageUri(this.version, this.packageUri);
}
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 6682c79..1c158cd 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -353,15 +353,12 @@
/// the 'allowed_experiments.json' file for this library.
bool isExperimentEnabledInLibrary(
flags.ExperimentalFlag flag, Uri importUri) {
- return flags.isExperimentEnabledInLibrary(flag, importUri,
- experimentalFlags: _raw.experimentalFlags,
- allowedExperimentalFlags: _raw.allowedExperimentalFlagsForTesting);
+ return _raw.isExperimentEnabledInLibrary(flag, importUri);
}
- Version getExperimentEnabledVersion(flags.ExperimentalFlag flag) {
- return flags.getExperimentEnabledVersion(flag,
- experimentReleasedVersionForTesting:
- _raw.experimentReleasedVersionForTesting);
+ Version getExperimentEnabledVersionInLibrary(
+ flags.ExperimentalFlag flag, Uri importUri) {
+ return _raw.getExperimentEnabledVersionInLibrary(flag, importUri);
}
Component _validateNullSafetyMode(Component component) {
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 607bf99..4f7945b 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -327,6 +327,7 @@
_fieldEncoding.registerMembers(library, this, f);
}
+ /// Builds the core AST structures for this field as needed for the outline.
void build(SourceLibraryBuilder libraryBuilder) {
if (type != null) {
// notInstanceContext is set to true for extension fields as they
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 05c1bc4..fef6b53 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -149,6 +149,7 @@
@override
void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes) {}
+ /// Builds the core AST structures for this member as needed for the outline.
void buildMembers(
LibraryBuilder library, void Function(Member, BuiltMemberKind) f);
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 0bd7da5..7942b40 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -332,13 +332,12 @@
importUri.scheme != 'dart' || _packageUri == null,
"Package uri '$_packageUri' set on dart: library with import uri "
"'${importUri}'.");
- updateLibraryNNBDSettings();
}
bool _enableVarianceInLibrary;
bool _enableNonfunctionTypeAliasesInLibrary;
bool _enableNonNullableInLibrary;
- Version _enableNonNullableVersionCache;
+ Version _enableNonNullableVersionInLibrary;
bool _enableTripleShiftInLibrary;
bool _enableExtensionMethodsInLibrary;
@@ -360,8 +359,10 @@
loader.target.isExperimentEnabledInLibrary(
ExperimentalFlag.nonNullable, _packageUri ?? importUri);
- Version get _enableNonNullableVersion => _enableNonNullableVersionCache ??=
- loader.target.getExperimentEnabledVersion(ExperimentalFlag.nonNullable);
+ Version get enableNonNullableVersionInLibrary =>
+ _enableNonNullableVersionInLibrary ??= loader.target
+ .getExperimentEnabledVersionInLibrary(
+ ExperimentalFlag.nonNullable, _packageUri ?? importUri);
bool get enableTripleShiftInLibrary => _enableTripleShiftInLibrary ??=
loader.target.isExperimentEnabledInLibrary(
@@ -434,10 +435,30 @@
return type;
}
+ bool _isNonNullableByDefault;
+
@override
- bool get isNonNullableByDefault =>
+ bool get isNonNullableByDefault {
+ assert(
+ _isNonNullableByDefault == null ||
+ _isNonNullableByDefault == _computeIsNonNullableByDefault(),
+ "Unstable isNonNullableByDefault property, changed "
+ "from ${_isNonNullableByDefault} to "
+ "${_computeIsNonNullableByDefault()}");
+ return _ensureIsNonNullableByDefault();
+ }
+
+ bool _ensureIsNonNullableByDefault() {
+ if (_isNonNullableByDefault == null) {
+ _isNonNullableByDefault = _computeIsNonNullableByDefault();
+ updateLibraryNNBDSettings();
+ }
+ return _isNonNullableByDefault;
+ }
+
+ bool _computeIsNonNullableByDefault() =>
enableNonNullableInLibrary &&
- languageVersion.version >= _enableNonNullableVersion &&
+ languageVersion.version >= enableNonNullableVersionInLibrary &&
!isOptOutTest(library.importUri);
static bool isOptOutTest(Uri uri) {
@@ -480,6 +501,7 @@
}
}
_languageVersion.isFinal = true;
+ _ensureIsNonNullableByDefault();
}
@override
@@ -904,6 +926,7 @@
return true;
}
+ /// Builds the core AST structure of this library as needed for the outline.
Library build(LibraryBuilder coreLibrary, {bool modifyTarget}) {
assert(implementationBuilders.isEmpty);
canAddImplementationBuilders = true;
@@ -955,8 +978,6 @@
reference: referenceFrom?.reference));
}
- // TODO(CFE Team): Is this really needed in two places?
- updateLibraryNNBDSettings();
return library;
}
@@ -2552,6 +2573,7 @@
MetadataBuilder.buildAnnotations(library, metadata, this, null, null);
}
+ /// Builds the core AST structures for [declaration] needed for the outline.
void buildBuilder(Builder declaration, LibraryBuilder coreLibrary) {
String findDuplicateSuffix(Builder declaration) {
if (declaration.next != null) {
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 14803dd..50dcccf 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -251,7 +251,7 @@
configuration: new ScannerConfiguration(
enableTripleShift: library.enableTripleShiftInLibrary,
enableExtensionMethods: library.enableExtensionMethodsInLibrary,
- enableNonNullable: library.isNonNullableByDefault),
+ enableNonNullable: library.enableNonNullableInLibrary),
languageVersionChanged:
(Scanner scanner, LanguageVersionToken version) {
if (!suppressLexicalErrors) {
@@ -346,8 +346,7 @@
// libraries with no corresponding package config we generate a message
// per library.
Map<String, List<LibraryBuilder>> libraryByPackage = {};
- Version enableNonNullableVersion =
- target.getExperimentEnabledVersion(ExperimentalFlag.nonNullable);
+ Map<Package, Version> enableNonNullableVersionByPackage = {};
for (LibraryBuilder libraryBuilder in _strongOptOutLibraries) {
Package package =
target.uriTranslator.getPackage(libraryBuilder.importUri);
@@ -355,6 +354,11 @@
if (package != null &&
package.languageVersion != null &&
package.languageVersion is! InvalidLanguageVersion) {
+ Version enableNonNullableVersion =
+ enableNonNullableVersionByPackage[package] ??=
+ target.getExperimentEnabledVersionInLibrary(
+ ExperimentalFlag.nonNullable,
+ new Uri(scheme: 'package', path: package.name));
Version version = new Version(
package.languageVersion.major, package.languageVersion.minor);
if (version < enableNonNullableVersion) {
@@ -908,6 +912,7 @@
return handleHierarchyCycles(objectClass);
}
+ /// Builds the core AST structure needed for the outline of the component.
void buildComponent() {
builders.forEach((Uri uri, LibraryBuilder library) {
if (library.loader == this) {
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart b/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
index ba35905..0e6a737 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
@@ -14,7 +14,7 @@
import 'package:front_end/src/api_prototype/experimental_flags.dart';
import 'package:kernel/ast.dart'
- show AsyncMarker, Expression, FunctionNode, TreeNode, Version;
+ show AsyncMarker, Expression, FunctionNode, TreeNode;
import '../fasta_codes.dart';
@@ -90,13 +90,11 @@
void reportMissingNonNullableSupport(Token token) {
assert(!libraryBuilder.isNonNullableByDefault);
assert(token != null);
- Version enableNonNullableVersion = libraryBuilder.loader.target
- .getExperimentEnabledVersion(ExperimentalFlag.nonNullable);
if (libraryBuilder.enableNonNullableInLibrary) {
if (libraryBuilder.languageVersion.isExplicit) {
addProblem(
- templateNonNullableOptOutExplicit
- .withArguments(enableNonNullableVersion.toText()),
+ templateNonNullableOptOutExplicit.withArguments(
+ libraryBuilder.enableNonNullableVersionInLibrary.toText()),
token.charOffset,
token.charCount,
context: <LocatedMessage>[
@@ -107,17 +105,19 @@
]);
} else {
addProblem(
- templateNonNullableOptOutImplicit
- .withArguments(enableNonNullableVersion.toText()),
+ templateNonNullableOptOutImplicit.withArguments(
+ libraryBuilder.enableNonNullableVersionInLibrary.toText()),
token.charOffset,
token.charCount);
}
} else if (!libraryBuilder.loader.target
.isExperimentEnabledGlobally(ExperimentalFlag.nonNullable)) {
- if (libraryBuilder.languageVersion.version < enableNonNullableVersion) {
+ if (libraryBuilder.languageVersion.version <
+ libraryBuilder.enableNonNullableVersionInLibrary) {
addProblem(
templateExperimentNotEnabledNoFlagInvalidLanguageVersion
- .withArguments(enableNonNullableVersion.toText()),
+ .withArguments(
+ libraryBuilder.enableNonNullableVersionInLibrary.toText()),
token.offset,
noLength);
} else {
@@ -125,8 +125,8 @@
}
} else {
addProblem(
- templateExperimentNotEnabled.withArguments(
- 'non-nullable', enableNonNullableVersion.toText()),
+ templateExperimentNotEnabled.withArguments('non-nullable',
+ libraryBuilder.enableNonNullableVersionInLibrary.toText()),
token.offset,
noLength);
}
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index ebacbfc..57a4369 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -61,8 +61,9 @@
return _options.isExperimentEnabledInLibrary(flag, importUri);
}
- Version getExperimentEnabledVersion(ExperimentalFlag flag) {
- return _options.getExperimentEnabledVersion(flag);
+ Version getExperimentEnabledVersionInLibrary(
+ ExperimentalFlag flag, Uri importUri) {
+ return _options.getExperimentEnabledVersionInLibrary(flag, importUri);
}
bool isExperimentEnabledGlobally(ExperimentalFlag flag) {
diff --git a/pkg/front_end/test/enable_non_nullable/data/.dart_tool/package_config.json b/pkg/front_end/test/enable_non_nullable/data/.dart_tool/package_config.json
new file mode 100644
index 0000000..bc435fb
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/.dart_tool/package_config.json
@@ -0,0 +1,18 @@
+{
+ "configVersion": 2,
+ "packages": [
+ {
+ "name": "allowed_package",
+ "rootUri": "../allowed_package/",
+ "packageUri": "lib/",
+ "languageVersion": "2.9"
+ },
+ {
+ "name": "not_allowed_package",
+ "rootUri": "../not_allowed_package/",
+ "packageUri": "lib/",
+ "languageVersion": "2.9"
+ }
+
+ ]
+}
\ No newline at end of file
diff --git a/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/unversioned_lib.dart b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/unversioned_lib.dart
new file mode 100644
index 0000000..a08c72e
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/unversioned_lib.dart
@@ -0,0 +1,3 @@
+// Copyright (c) 2020, 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.
diff --git a/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_10_lib.dart b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_10_lib.dart
new file mode 100644
index 0000000..5f60217
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_10_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, 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.10
diff --git a/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_11_lib.dart b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_11_lib.dart
new file mode 100644
index 0000000..8de228b
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_11_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, 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.11
diff --git a/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_8_lib.dart b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_8_lib.dart
new file mode 100644
index 0000000..e7d43c5
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_8_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, 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.8
diff --git a/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_9_lib.dart b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_9_lib.dart
new file mode 100644
index 0000000..c2de893
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_9_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, 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
diff --git a/pkg/front_end/test/enable_non_nullable/data/main.dart b/pkg/front_end/test/enable_non_nullable/data/main.dart
new file mode 100644
index 0000000..cc333b0
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/main.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2020, 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.
+
+import 'package:allowed_package/unversioned_lib.dart';
+import 'package:allowed_package/versioned_2_8_lib.dart';
+import 'package:allowed_package/versioned_2_9_lib.dart';
+import 'package:allowed_package/versioned_2_10_lib.dart';
+import 'package:allowed_package/versioned_2_11_lib.dart';
+import 'package:not_allowed_package/unversioned_lib.dart';
+import 'package:not_allowed_package/versioned_2_8_lib.dart';
+import 'package:not_allowed_package/versioned_2_9_lib.dart';
+import 'package:not_allowed_package/versioned_2_10_lib.dart';
+import 'package:not_allowed_package/versioned_2_11_lib.dart';
+import 'unversioned_lib.dart';
+import 'versioned_2_8_lib.dart';
+import 'versioned_2_9_lib.dart';
+import 'versioned_2_10_lib.dart';
+import 'versioned_2_11_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/unversioned_lib.dart b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/unversioned_lib.dart
new file mode 100644
index 0000000..a08c72e
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/unversioned_lib.dart
@@ -0,0 +1,3 @@
+// Copyright (c) 2020, 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.
diff --git a/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_10_lib.dart b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_10_lib.dart
new file mode 100644
index 0000000..5f60217
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_10_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, 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.10
diff --git a/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_11_lib.dart b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_11_lib.dart
new file mode 100644
index 0000000..8de228b
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_11_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, 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.11
diff --git a/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_8_lib.dart b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_8_lib.dart
new file mode 100644
index 0000000..e7d43c5
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_8_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, 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.8
diff --git a/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_9_lib.dart b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_9_lib.dart
new file mode 100644
index 0000000..c2de893
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_9_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, 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
diff --git a/pkg/front_end/test/enable_non_nullable/data/unversioned_lib.dart b/pkg/front_end/test/enable_non_nullable/data/unversioned_lib.dart
new file mode 100644
index 0000000..a08c72e
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/unversioned_lib.dart
@@ -0,0 +1,3 @@
+// Copyright (c) 2020, 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.
diff --git a/pkg/front_end/test/enable_non_nullable/data/versioned_2_10_lib.dart b/pkg/front_end/test/enable_non_nullable/data/versioned_2_10_lib.dart
new file mode 100644
index 0000000..5f60217
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/versioned_2_10_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, 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.10
diff --git a/pkg/front_end/test/enable_non_nullable/data/versioned_2_11_lib.dart b/pkg/front_end/test/enable_non_nullable/data/versioned_2_11_lib.dart
new file mode 100644
index 0000000..8de228b
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/versioned_2_11_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, 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.11
diff --git a/pkg/front_end/test/enable_non_nullable/data/versioned_2_8_lib.dart b/pkg/front_end/test/enable_non_nullable/data/versioned_2_8_lib.dart
new file mode 100644
index 0000000..e7d43c5
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/versioned_2_8_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, 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.8
diff --git a/pkg/front_end/test/enable_non_nullable/data/versioned_2_9_lib.dart b/pkg/front_end/test/enable_non_nullable/data/versioned_2_9_lib.dart
new file mode 100644
index 0000000..c2de893
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/versioned_2_9_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, 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
diff --git a/pkg/front_end/test/enable_non_nullable/enable_non_nullable_test.dart b/pkg/front_end/test/enable_non_nullable/enable_non_nullable_test.dart
new file mode 100644
index 0000000..d6feb1d
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/enable_non_nullable_test.dart
@@ -0,0 +1,128 @@
+// 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.md file.
+
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+import 'package:front_end/src/api_prototype/compiler_options.dart';
+import 'package:front_end/src/api_prototype/experimental_flags.dart';
+import 'package:front_end/src/api_prototype/kernel_generator.dart';
+import 'package:front_end/src/api_prototype/language_version.dart';
+import 'package:front_end/src/compute_platform_binaries_location.dart';
+import 'package:kernel/ast.dart';
+
+/// The version used in this test as the experiment release version.
+const Version experimentReleaseVersion = const Version(2, 9);
+
+/// The version used in this test as the experiment enabled version.
+const Version experimentEnabledVersion = const Version(2, 10);
+
+main() async {
+ print('--------------------------------------------------------------------');
+ print('Test off-by-default with command-line flag');
+ print('--------------------------------------------------------------------');
+ await test(
+ enableNonNullableByDefault: false,
+ // When the flag is off by default, the experiment release version should
+ // be used as the opt-in criterion for all libraries.
+ versionImpliesOptIn: experimentReleaseVersion,
+ versionOptsInAllowed: experimentReleaseVersion);
+
+ print('--------------------------------------------------------------------');
+ print('Test on-by-default');
+ print('--------------------------------------------------------------------');
+ await test(
+ enableNonNullableByDefault: true,
+ // When the flag is on by default, the experiment release version should
+ // be used as the opt-in criterion only for libraries in allowed packages
+ // and the experiment enabled version should be used as the opt-in
+ // criterion for all other libraries.
+ versionImpliesOptIn: experimentEnabledVersion,
+ versionOptsInAllowed: experimentReleaseVersion);
+}
+
+test(
+ {bool enableNonNullableByDefault,
+ Version versionImpliesOptIn,
+ Version versionOptsInAllowed}) async {
+ CompilerOptions options = new CompilerOptions();
+ if (enableNonNullableByDefault) {
+ // Pretend non-nullable is on by default.
+ options.defaultExperimentFlagsForTesting = {
+ ExperimentalFlag.nonNullable: true
+ };
+ } else {
+ // Pretend non-nullable is off by default but enabled on command-line.
+ options
+ ..defaultExperimentFlagsForTesting = {ExperimentalFlag.nonNullable: false}
+ ..experimentalFlags = {ExperimentalFlag.nonNullable: true};
+ }
+
+ Uri sdkSummary = computePlatformBinariesLocation(forceBuildDir: true)
+ .resolve('vm_platform_strong.dill');
+ options
+ ..sdkSummary = sdkSummary
+ // Pretend current version is 2.11
+ ..currentSdkVersion = '2.11'
+ ..allowedExperimentalFlagsForTesting = new AllowedExperimentalFlags(
+ sdkDefaultExperiments:
+ defaultAllowedExperimentalFlags.sdkDefaultExperiments,
+ sdkLibraryExperiments:
+ defaultAllowedExperimentalFlags.sdkLibraryExperiments,
+ packageExperiments: {
+ ...defaultAllowedExperimentalFlags.packageExperiments,
+ 'allowed_package': {ExperimentalFlag.nonNullable}
+ })
+ ..experimentReleasedVersionForTesting = const {
+ // Pretend non-nullable is released in version 2.9.
+ ExperimentalFlag.nonNullable: experimentReleaseVersion
+ }
+ ..experimentEnabledVersionForTesting = const {
+ // Pretend non-nullable is enabled in version 2.10.
+ ExperimentalFlag.nonNullable: experimentEnabledVersion
+ };
+
+ Directory directory = new Directory.fromUri(
+ Uri.base.resolve('pkg/front_end/test/enable_non_nullable/data/'));
+ CompilerResult result = await kernelForProgramInternal(
+ directory.uri.resolve('main.dart'), options,
+ retainDataForTesting: true);
+ for (Library library in result.component.libraries) {
+ if (library.importUri.scheme != 'dart') {
+ bool usesLegacy =
+ await uriUsesLegacyLanguageVersion(library.fileUri, options);
+ VersionAndPackageUri versionAndPackageUri =
+ await languageVersionForUri(library.fileUri, options);
+ bool isNonNullableByDefault = library.isNonNullableByDefault;
+ print('${library.fileUri}:');
+ print(' version=${versionAndPackageUri.version}');
+ print(' (package) uri=${versionAndPackageUri.packageUri}');
+ print(' isNonNullableByDefault=${isNonNullableByDefault}');
+ print(' uriUsesLegacyLanguageVersion=${usesLegacy}');
+ Expect.equals(library.languageVersion, versionAndPackageUri.version,
+ "Language version mismatch for ${library.importUri}");
+ Expect.equals(
+ !usesLegacy,
+ isNonNullableByDefault,
+ "Unexpected null-safe state for ${library.importUri}:"
+ " isNonNullableByDefault=$isNonNullableByDefault,"
+ " uriUsesLegacyLanguageVersion=$usesLegacy. "
+ "Computed version=${versionAndPackageUri.version},"
+ " (package) uri=${versionAndPackageUri.packageUri}");
+ Expect.isTrue(
+ library.languageVersion < versionImpliesOptIn ||
+ library.isNonNullableByDefault,
+ "Expected library ${library.importUri} with version "
+ "${library.languageVersion} to be opted in.");
+ Expect.isTrue(
+ versionAndPackageUri.packageUri.scheme != 'package' ||
+ !versionAndPackageUri.packageUri.path
+ .startsWith('allowed_package') ||
+ library.languageVersion < versionOptsInAllowed ||
+ library.isNonNullableByDefault,
+ "Expected allowed library ${library.importUri} with version "
+ "${library.languageVersion} to be opted in.");
+ }
+ }
+}
diff --git a/pkg/front_end/test/language_versioning/language_versioning_test.dart b/pkg/front_end/test/language_versioning/language_versioning_test.dart
index 4146239..b44c90d 100644
--- a/pkg/front_end/test/language_versioning/language_versioning_test.dart
+++ b/pkg/front_end/test/language_versioning/language_versioning_test.dart
@@ -87,9 +87,11 @@
for (Library library in component.libraries) {
if (library.importUri.scheme == "dart") continue;
Version lvFile =
- await lv.languageVersionForUri(library.fileUri, stashedOptions);
+ (await lv.languageVersionForUri(library.fileUri, stashedOptions))
+ .version;
Version lvImportUri =
- await lv.languageVersionForUri(library.importUri, stashedOptions);
+ (await lv.languageVersionForUri(library.importUri, stashedOptions))
+ .version;
if ((lvFile != lvImportUri || lvFile != library.languageVersion)) {
throw """
Language version disagreement:
diff --git a/pkg/front_end/test/lint_test.status b/pkg/front_end/test/lint_test.status
index cc1e0e3..10f7b68 100644
--- a/pkg/front_end/test/lint_test.status
+++ b/pkg/front_end/test/lint_test.status
@@ -8,6 +8,7 @@
_fe_analyzer_shared/lib/src/scanner/string_scanner/ImportsTwice: Fail
_fe_analyzer_shared/lib/src/scanner/token_impl/ImportsTwice: Fail
_fe_analyzer_shared/lib/src/scanner/utf8_bytes_scanner/ImportsTwice: Fail
+front_end/lib/src/api_prototype/compiler_options/ImportsTwice: Fail
front_end/lib/src/api_prototype/compiler_options/Exports: Fail
front_end/lib/src/api_prototype/constant_evaluator/Exports: Fail
front_end/lib/src/api_prototype/front_end/Exports: Fail
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_bound_access.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_bound_access.dart.weak.expect
index 080ff9e..dec49a6 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_bound_access.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_bound_access.dart.weak.expect
@@ -13,7 +13,7 @@
class DynamicClass<T extends dynamic = dynamic, S extends self::DynamicClass::T* = dynamic> extends core::Object {
generic-covariant-impl field self::DynamicClass::T* field1;
generic-covariant-impl field self::DynamicClass::T* field2;
- constructor •(self::DynamicClass::T* field1, self::DynamicClass::T* field2) → self::DynamicClass<self::DynamicClass::T%, self::DynamicClass::S*>*
+ constructor •(self::DynamicClass::T* field1, self::DynamicClass::T* field2) → self::DynamicClass<self::DynamicClass::T*, self::DynamicClass::S*>*
: self::DynamicClass::field1 = field1, self::DynamicClass::field2 = field2, super core::Object::•()
;
method method() → dynamic
diff --git a/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/not_allowed_package/lib/versioned_2_9_lib.dart b/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/not_allowed_package/lib/versioned_2_9_lib.dart
index 43a931e..ff693f6 100644
--- a/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/not_allowed_package/lib/versioned_2_9_lib.dart
+++ b/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/not_allowed_package/lib/versioned_2_9_lib.dart
@@ -4,4 +4,4 @@
// @dart=2.9
-int? versioned_2_9_AllowedPackage; // ok
\ No newline at end of file
+int? versioned_2_9_AllowedPackage; // error
\ No newline at end of file
diff --git a/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/versioned_2_9_lib.dart b/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/versioned_2_9_lib.dart
index 6df385a..7a9a3ee 100644
--- a/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/versioned_2_9_lib.dart
+++ b/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/versioned_2_9_lib.dart
@@ -4,4 +4,4 @@
// @dart=2.9
-int? versioned_2_9_Library; // ok
\ No newline at end of file
+int? versioned_2_9_Library; // error
\ No newline at end of file
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 47f67ff..deda925 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -480,6 +480,7 @@
"exclude": [
"^pkg/analysis_server/lib/src/analysis_server\\.dart",
"test/analyser_ignored/",
+ "test/enable_non_nullable/data/",
"test/extensions/data/",
"test/id_testing/data/",
"test/language_versioning/data/",