Use a non-null index for all features, even expired ones.
This ensures that the FeatureSet object can track the presence or
absence of expired features.
Change-Id: Ie6e213993792b8c3d6cf84ef01c464c16c274b85
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99920
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
index 8a5f2f1..a9207abe 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
@@ -68,7 +68,7 @@
'Non Nullable');
static const control_flow_collections = const ExperimentalFeature(
- null,
+ 2,
EnableString.control_flow_collections,
IsEnabledByDefault.control_flow_collections,
IsExpired.control_flow_collections,
@@ -76,7 +76,7 @@
firstSupportedVersion: '2.2.2');
static const spread_collections = const ExperimentalFeature(
- null,
+ 3,
EnableString.spread_collections,
IsEnabledByDefault.spread_collections,
IsExpired.spread_collections,
@@ -84,7 +84,7 @@
firstSupportedVersion: '2.2.2');
static const set_literals = const ExperimentalFeature(
- null,
+ 4,
EnableString.set_literals,
IsEnabledByDefault.set_literals,
IsExpired.set_literals,
@@ -92,21 +92,21 @@
firstSupportedVersion: '2.2.0');
static const triple_shift = const ExperimentalFeature(
- 2,
+ 5,
EnableString.triple_shift,
IsEnabledByDefault.triple_shift,
IsExpired.triple_shift,
'Triple-shift operator');
static const bogus_disabled = const ExperimentalFeature(
- null,
+ 6,
EnableString.bogus_disabled,
IsEnabledByDefault.bogus_disabled,
IsExpired.bogus_disabled,
null);
static const bogus_enabled = const ExperimentalFeature(
- null,
+ 7,
EnableString.bogus_enabled,
IsEnabledByDefault.bogus_enabled,
IsExpired.bogus_enabled,
@@ -145,7 +145,12 @@
: _enableFlags = <bool>[
constant_update_2018 ?? IsEnabledByDefault.constant_update_2018,
non_nullable ?? IsEnabledByDefault.non_nullable,
+ true, // control-flow-collections
+ true, // spread-collections
+ true, // set-literals
triple_shift ?? IsEnabledByDefault.triple_shift,
+ false, // bogus-disabled
+ true, // bogus-enabled
];
/// Computes a set of features for use in a unit test. Computes the set of
@@ -169,17 +174,19 @@
ExperimentStatus._(this._enableFlags);
- /// Hardcoded state for the expired flag "bogus_disabled"
- bool get bogus_disabled => false;
+ /// Current state for the flag "bogus_disabled"
+ bool get bogus_disabled => isEnabled(ExperimentalFeatures.bogus_disabled);
- /// Hardcoded state for the expired flag "bogus_enabled"
- bool get bogus_enabled => true;
+ /// Current state for the flag "bogus_enabled"
+ bool get bogus_enabled => isEnabled(ExperimentalFeatures.bogus_enabled);
/// Current state for the flag "constant-update-2018"
- bool get constant_update_2018 => _enableFlags[0];
+ bool get constant_update_2018 =>
+ isEnabled(ExperimentalFeatures.constant_update_2018);
/// Current state for the flag "control_flow_collections"
- bool get control_flow_collections => true;
+ bool get control_flow_collections =>
+ isEnabled(ExperimentalFeatures.control_flow_collections);
@override
int get hashCode {
@@ -191,16 +198,17 @@
}
/// Current state for the flag "non-nullable"
- bool get non_nullable => _enableFlags[1];
+ bool get non_nullable => isEnabled(ExperimentalFeatures.non_nullable);
/// Current state for the flag "set-literals"
- bool get set_literals => true;
+ bool get set_literals => isEnabled(ExperimentalFeatures.set_literals);
/// Current state for the flag "spread_collections"
- bool get spread_collections => true;
+ bool get spread_collections =>
+ isEnabled(ExperimentalFeatures.spread_collections);
/// Current state for the flag "triple_shift"
- bool get triple_shift => _enableFlags[2];
+ bool get triple_shift => isEnabled(ExperimentalFeatures.triple_shift);
@override
operator ==(Object other) {
@@ -215,9 +223,7 @@
}
/// Queries whether the given [feature] is enabled or disabled.
- bool isEnabled(ExperimentalFeature feature) => feature.isExpired
- ? feature.isEnabledByDefault
- : _enableFlags[feature.index];
+ bool isEnabled(ExperimentalFeature feature) => _enableFlags[feature.index];
@override
FeatureSet restrictToVersion(Version version) =>
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments_impl.dart b/pkg/analyzer/lib/src/dart/analysis/experiments_impl.dart
index 9def415..ebf565c 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments_impl.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments_impl.dart
@@ -19,14 +19,9 @@
/// unrecognized flags are ignored, conflicting flags are resolved in favor of
/// the flag appearing last.
List<bool> decodeFlags(List<String> flags) {
- var decodedFlags = <bool>[];
+ var decodedFlags = List<bool>.filled(_knownFeatures.length, false);
for (var feature in _knownFeatures.values) {
- if (feature.isExpired) continue;
- var index = feature.index;
- while (decodedFlags.length <= index) {
- decodedFlags.add(false);
- }
- decodedFlags[index] = feature.isEnabledByDefault;
+ decodedFlags[feature.index] = feature.isEnabledByDefault;
}
for (var entry in _flagStringsToMap(flags).entries) {
decodedFlags[entry.key] = entry.value;
@@ -46,11 +41,6 @@
flags = restrictEnableFlagsToVersion(flags, Version.parse(sdkVersion));
}
for (ExperimentalFeature feature in additionalFeatures) {
- if (feature.isExpired) {
- // At the moment we can't enable features in the "expired" state.
- // TODO(paulberry): fix this by including such features in enable flags.
- continue;
- }
flags[feature.index] = true;
}
return flags;
@@ -93,11 +83,6 @@
List<bool> restrictEnableFlagsToVersion(List<bool> flags, Version version) {
flags = List.from(flags);
for (var feature in _knownFeatures.values) {
- if (feature.isExpired) {
- // At the moment we can't disable features in the "expired" state.
- // TODO(paulberry): fix this by including such features in enable flags.
- continue;
- }
if (!feature.isEnabledByDefault ||
feature.firstSupportedVersion > version) {
flags[feature.index] = false;
@@ -251,9 +236,6 @@
/// Index of the flag in the private data structure maintained by
/// [ExperimentStatus].
///
- /// For expired features, the index should be null, since no enable/disable
- /// state needs to be stored.
- ///
/// This index should not be relied upon to be stable over time. For instance
/// it should not be used to serialize the state of experiments to long term
/// storage if there is any expectation of compatibility between analyzer
@@ -279,7 +261,7 @@
this.isEnabledByDefault, this.isExpired, this.documentation,
{String firstSupportedVersion})
: _firstSupportedVersion = firstSupportedVersion,
- assert(isExpired ? index == null : index != null),
+ assert(index != null),
assert(isEnabledByDefault
? firstSupportedVersion != null
: firstSupportedVersion == null);
diff --git a/pkg/analyzer/test/src/dart/analysis/experiments_test.dart b/pkg/analyzer/test/src/dart/analysis/experiments_test.dart
index cb8ba93..740c46f 100644
--- a/pkg/analyzer/test/src/dart/analysis/experiments_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/experiments_test.dart
@@ -80,28 +80,28 @@
test_fromStrings_illegal_use_of_expired_flag_disable() {
// Expired flags are ignored even if they would fail validation.
- knownFeatures['a'] = ExperimentalFeature(null, 'a', true, true, 'a',
+ knownFeatures['a'] = ExperimentalFeature(0, 'a', true, true, 'a',
firstSupportedVersion: '1.0.0');
- expect(getFlags(fromStrings(['no-a'])), []);
+ expect(getFlags(fromStrings(['no-a'])), [true]);
}
test_fromStrings_illegal_use_of_expired_flag_enable() {
// Expired flags are ignored even if they would fail validation.
- knownFeatures['a'] = ExperimentalFeature(null, 'a', false, true, 'a');
- expect(getFlags(fromStrings(['a'])), []);
+ knownFeatures['a'] = ExperimentalFeature(0, 'a', false, true, 'a');
+ expect(getFlags(fromStrings(['a'])), [false]);
}
test_fromStrings_unnecessary_use_of_expired_flag_disable() {
// Expired flags are ignored.
- knownFeatures['a'] = ExperimentalFeature(null, 'a', false, true, 'a');
- expect(getFlags(fromStrings(['no-a'])), []);
+ knownFeatures['a'] = ExperimentalFeature(0, 'a', false, true, 'a');
+ expect(getFlags(fromStrings(['no-a'])), [false]);
}
test_fromStrings_unnecessary_use_of_expired_flag_enable() {
// Expired flags are ignored.
- knownFeatures['a'] = ExperimentalFeature(null, 'a', true, true, 'a',
+ knownFeatures['a'] = ExperimentalFeature(0, 'a', true, true, 'a',
firstSupportedVersion: '1.0.0');
- expect(getFlags(fromStrings(['a'])), []);
+ expect(getFlags(fromStrings(['a'])), [true]);
}
test_fromStrings_unrecognized_flag() {
@@ -178,7 +178,7 @@
}
test_validateFlags_illegal_use_of_expired_flag_disable() {
- knownFeatures['a'] = ExperimentalFeature(null, 'a', true, true, 'a',
+ knownFeatures['a'] = ExperimentalFeature(0, 'a', true, true, 'a',
firstSupportedVersion: '1.0.0');
var validationResult = getValidationResult(['no-a']);
expect(validationResult, hasLength(1));
@@ -190,7 +190,7 @@
}
test_validateFlags_illegal_use_of_expired_flag_enable() {
- knownFeatures['a'] = ExperimentalFeature(null, 'a', false, true, 'a');
+ knownFeatures['a'] = ExperimentalFeature(0, 'a', false, true, 'a');
var validationResult = getValidationResult(['a']);
expect(validationResult, hasLength(1));
var error = validationResult[0] as IllegalUseOfExpiredFlag;
@@ -201,7 +201,7 @@
}
test_validateFlags_unnecessary_use_of_expired_flag_disable() {
- knownFeatures['a'] = ExperimentalFeature(null, 'a', false, true, 'a');
+ knownFeatures['a'] = ExperimentalFeature(0, 'a', false, true, 'a');
var validationResult = getValidationResult(['no-a']);
expect(validationResult, hasLength(1));
var error = validationResult[0] as UnnecessaryUseOfExpiredFlag;
@@ -212,7 +212,7 @@
}
test_validateFlags_unnecessary_use_of_expired_flag_enable() {
- knownFeatures['a'] = ExperimentalFeature(null, 'a', true, true, 'a',
+ knownFeatures['a'] = ExperimentalFeature(0, 'a', true, true, 'a',
firstSupportedVersion: '1.0.0');
var validationResult = getValidationResult(['a']);
expect(validationResult, hasLength(1));