Skip to content

Commit b8c058f

Browse files
authored
Respect allowed experiments list, via Analyzer's APIs. (#2269)
Respect allowed experiments list, via Analyzer's APIs. Analyzer's LibraryElement.isNonNullableByDefault has already taken allowed experiments into account. Additionally, rewrite all code and comments which refer to "NNBD" to instead refer to "Null safety".
1 parent 5e0f16d commit b8c058f

File tree

5 files changed

+41
-89
lines changed

5 files changed

+41
-89
lines changed

lib/src/element_type.dart

+8-7
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@ abstract class ElementType extends Privacy {
7979

8080
/// Return a dartdoc nullability suffix for this type.
8181
String get nullabilitySuffix {
82-
if (library.isNNBD && !type.isVoid && !type.isBottom) {
83-
/// If a legacy type appears inside the public interface of a
84-
/// NNBD library, we pretend it is nullable for the purpose of
82+
if (library.isNullSafety && !type.isVoid && !type.isBottom) {
83+
/// If a legacy type appears inside the public interface of a Null
84+
/// safety library, we pretend it is nullable for the purpose of
8585
/// documentation (since star-types are not supposed to be public).
8686
if (type.nullabilitySuffix == NullabilitySuffix.question ||
8787
type.nullabilitySuffix == NullabilitySuffix.star) {
@@ -406,11 +406,12 @@ abstract class CallableElementTypeMixin implements ParameterizedElementType {
406406
/// Return the [TypeParameterType] with the legacy nullability for the given
407407
/// type parameter [element].
408408
///
409-
/// TODO(scheglov) This method is a work around that fact that DartDoc
409+
/// TODO(scheglov): This method is a work around that fact that DartDoc
410410
/// currently represents both type formals and uses of them as actual types,
411-
/// as [TypeParameterType]s. This was not perfect, but worked before NNBD.
412-
/// With NNBD types have nullability suffixes, but type formals should not.
413-
/// Eventually we should separate models for type formals and types.
411+
/// as [TypeParameterType]s. This was not perfect, but worked before Null
412+
/// safety. With Null safety, types have nullability suffixes, but type
413+
/// formals should not. Eventually we should separate models for type formals
414+
/// and types.
414415
static TypeParameterType _legacyTypeParameterType(
415416
TypeParameterElement element,
416417
) {

lib/src/model/feature_set.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ mixin FeatureSet {
1616
Iterable<LanguageFeature> get displayedLanguageFeatures sync* {
1717
// TODO(jcollins-g): Implement mixed-mode handling and the tagging of
1818
// legacy interfaces.
19-
if (isNNBD) {
19+
if (isNullSafety) {
2020
yield LanguageFeature(
2121
'Null safety', packageGraph.rendererFactory.featureRenderer);
2222
}
@@ -26,5 +26,5 @@ mixin FeatureSet {
2626

2727
// TODO(jcollins-g): This is an approximation and not strictly true for
2828
// inheritance/reexports.
29-
bool get isNNBD => library.isNNBD;
29+
bool get isNullSafety => library.isNullSafety;
3030
}

lib/src/model/library.dart

+7-10
Original file line numberDiff line numberDiff line change
@@ -108,17 +108,14 @@ class Library extends ModelElement with Categorization, TopLevelContainer {
108108
List<String> _allOriginalModelElementNames;
109109

110110
/// Return true if this library is in a package configured to be treated as
111-
/// as non-nullable by default and is itself NNBD.
112-
// TODO(jcollins-g): packageMeta.allowsNNBD may be redundant after package
113-
// allow list support is published in analyzer
114-
bool get _allowsNNBD =>
115-
element.isNonNullableByDefault && packageMeta.allowsNNBD;
116-
117-
/// Return true if this library should be documented as non-nullable.
118-
/// A library may be NNBD but not documented that way.
111+
/// as using Null safety and itself uses Null safety.
112+
bool get _allowsNullSafety => element.isNonNullableByDefault;
113+
114+
/// Return true if this library should be documented as using Null safety.
115+
/// A library may use Null safety but not documented that way.
119116
@override
120-
bool get isNNBD =>
121-
config.enableExperiment.contains('non-nullable') && _allowsNNBD;
117+
bool get isNullSafety =>
118+
config.enableExperiment.contains('non-nullable') && _allowsNullSafety;
122119

123120
bool get isInSdk => element.isInSdk;
124121

lib/src/package_meta.dart

-47
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import 'dart:io';
1010
import 'package:analyzer/dart/element/element.dart';
1111
import 'package:dartdoc/dartdoc.dart';
1212
import 'package:path/path.dart' as path;
13-
import 'package:pub_semver/pub_semver.dart';
1413
import 'package:yaml/yaml.dart';
1514

1615
import 'logging.dart';
@@ -107,14 +106,6 @@ abstract class PackageMeta {
107106

108107
String get homepage;
109108

110-
/// If true, libraries in this package can be be read as non-nullable by
111-
/// default. Whether they will be will be documented that way will depend
112-
/// on the experiment flag.
113-
///
114-
/// A package property, as this depends in part on the pubspec version
115-
/// constraint and/or the package allow list.
116-
bool get allowsNNBD;
117-
118109
FileContents getReadmeContents();
119110

120111
FileContents getLicenseContents();
@@ -281,7 +272,6 @@ class _FilePackageMeta extends PubPackageMeta {
281272
FileContents _license;
282273
FileContents _changelog;
283274
Map<dynamic, dynamic> _pubspec;
284-
Map<dynamic, dynamic> _analysisOptions;
285275

286276
_FilePackageMeta(Directory dir) : super(dir) {
287277
var f = File(path.join(dir.path, 'pubspec.yaml'));
@@ -290,12 +280,6 @@ class _FilePackageMeta extends PubPackageMeta {
290280
} else {
291281
_pubspec = {};
292282
}
293-
f = File(path.join(dir.path, 'analysis_options.yaml'));
294-
if (f.existsSync()) {
295-
_analysisOptions = loadYaml(f.readAsStringSync());
296-
} else {
297-
_analysisOptions = {};
298-
}
299283
}
300284

301285
bool _setHostedAt = false;
@@ -376,29 +360,6 @@ class _FilePackageMeta extends PubPackageMeta {
376360
@override
377361
String get homepage => _pubspec['homepage'];
378362

379-
/// This is a magic range that triggers detection of [allowsNNBD].
380-
static final _nullableRange =
381-
VersionConstraint.parse('>=2.9.0-dev.0 <2.10.0') as VersionRange;
382-
383-
@override
384-
bool get allowsNNBD {
385-
// TODO(jcollins-g): override/add to with allow list once that exists
386-
var sdkConstraint;
387-
if (_pubspec?.containsKey('sdk') ?? false) {
388-
// TODO(jcollins-g): VersionConstraint.parse returns [VersionRange]s right
389-
// now, but the interface doesn't guarantee that.
390-
sdkConstraint = VersionConstraint.parse(_pubspec['sdk']) as VersionRange;
391-
}
392-
if (sdkConstraint == _nullableRange &&
393-
(_analysisOptions['analyzer']?.containsKey('enable-experiment') ??
394-
false) &&
395-
_analysisOptions['analyzer']['enable-experiment']
396-
.contains('non-nullable')) {
397-
return true;
398-
}
399-
return false;
400-
}
401-
402363
@override
403364
bool get requiresFlutter =>
404365
_pubspec['environment']?.containsKey('flutter') == true ||
@@ -462,14 +423,6 @@ class _SdkMeta extends PubPackageMeta {
462423
sdkReadmePath = path.join(dir.path, 'lib', 'api_readme.md');
463424
}
464425

465-
/// 2.9.0-9.0.dev is the first unforked SDK, and therefore the first version
466-
/// of the SDK it makes sense to allow NNBD documentation for.
467-
static final _sdkNullableRange = VersionConstraint.parse('>=2.9.0-9.0.dev');
468-
469-
@override
470-
// TODO(jcollins-g): There should be a better way to determine this.
471-
bool get allowsNNBD => _sdkNullableRange.allows(Version.parse(version));
472-
473426
@override
474427
String get hostedAt => null;
475428

test/model_special_cases_test.dart

+24-23
Original file line numberDiff line numberDiff line change
@@ -30,42 +30,43 @@ void main() {
3030
exit(1);
3131
}
3232

33-
// This doesn't have the `max` because NNBD is supposed to work after this
34-
// version, and if the `max` is placed here we'll silently pass 2.10 stable
35-
// if we haven't figured out how to switch on NNBD outside of `dev` builds
36-
// as specified in #2148.
37-
final _nnbdExperimentAllowed =
33+
// This doesn't have the `max` because Null safety is supposed to work after
34+
// this version, and if the `max` is placed here we'll silently pass 2.10
35+
// stable if we haven't figured out how to switch on Null safety outside of
36+
// dev builds as specified in #2148.
37+
final _nullSafetyExperimentAllowed =
3838
VersionRange(min: Version.parse('2.9.0-9.0.dev'), includeMin: true);
3939

40-
// Experimental features not yet enabled by default. Move tests out of this block
41-
// when the feature is enabled by default.
40+
// Experimental features not yet enabled by default. Move tests out of this
41+
// block when the feature is enabled by default.
4242
group('Experiments', () {
4343
Library lateFinalWithoutInitializer,
44-
nnbdClassMemberDeclarations,
45-
optOutOfNnbd,
44+
nullSafetyClassMemberDeclarations,
45+
optOutOfNullSafety,
4646
nullableElements;
4747
Class b;
4848

4949
setUpAll(() async {
5050
lateFinalWithoutInitializer = (await utils.testPackageGraphExperiments)
5151
.libraries
5252
.firstWhere((lib) => lib.name == 'late_final_without_initializer');
53-
nnbdClassMemberDeclarations = (await utils.testPackageGraphExperiments)
53+
nullSafetyClassMemberDeclarations = (await utils
54+
.testPackageGraphExperiments)
5455
.libraries
5556
.firstWhere((lib) => lib.name == 'nnbd_class_member_declarations');
56-
optOutOfNnbd = (await utils.testPackageGraphExperiments)
57+
optOutOfNullSafety = (await utils.testPackageGraphExperiments)
5758
.libraries
5859
.firstWhere((lib) => lib.name == 'opt_out_of_nnbd');
5960
nullableElements = (await utils.testPackageGraphExperiments)
6061
.libraries
6162
.firstWhere((lib) => lib.name == 'nullable_elements');
62-
b = nnbdClassMemberDeclarations.allClasses
63+
b = nullSafetyClassMemberDeclarations.allClasses
6364
.firstWhere((c) => c.name == 'B');
6465
});
6566

66-
test('isNNBD is set correctly for libraries', () {
67-
expect(lateFinalWithoutInitializer.isNNBD, isTrue);
68-
expect(optOutOfNnbd.isNNBD, isFalse);
67+
test('isNullSafety is set correctly for libraries', () {
68+
expect(lateFinalWithoutInitializer.isNullSafety, isTrue);
69+
expect(optOutOfNullSafety.isNullSafety, isFalse);
6970
});
7071

7172
test('method parameters with required', () {
@@ -118,8 +119,8 @@ void main() {
118119
var cField = c.instanceFields.firstWhere((f) => f.name == 'cField');
119120
var dField = c.instanceFields.firstWhere((f) => f.name == 'dField');
120121

121-
// If nnbd isn't enabled, fields named 'late' come back from the analyzer
122-
// instead of setting up 'isLate'.
122+
// If Null safety isn't enabled, fields named 'late' come back from the
123+
// analyzer instead of setting up 'isLate'.
123124
expect(c.instanceFields.any((f) => f.name == 'late'), isFalse);
124125

125126
expect(a.modelType.returnType.name, equals('dynamic'));
@@ -147,10 +148,10 @@ void main() {
147148
expect(initializeMe.features, contains('late'));
148149
});
149150

150-
test('Opt out of NNBD', () {
151-
var notOptedIn = optOutOfNnbd.publicProperties
151+
test('Opt out of Null safety', () {
152+
var notOptedIn = optOutOfNullSafety.publicProperties
152153
.firstWhere((v) => v.name == 'notOptedIn');
153-
expect(notOptedIn.isNNBD, isFalse);
154+
expect(notOptedIn.isNullSafety, isFalse);
154155
expect(notOptedIn.modelType.nullabilitySuffix, isEmpty);
155156
});
156157

@@ -161,7 +162,7 @@ void main() {
161162
.firstWhere((f) => f.name == 'aComplexType');
162163
var aComplexSetterOnlyType = complexNullableMembers.allFields
163164
.firstWhere((f) => f.name == 'aComplexSetterOnlyType');
164-
expect(complexNullableMembers.isNNBD, isTrue);
165+
expect(complexNullableMembers.isNullSafety, isTrue);
165166
expect(
166167
complexNullableMembers.nameWithGenerics,
167168
equals(
@@ -186,7 +187,7 @@ void main() {
186187
.firstWhere((f) => f.name == 'methodWithNullables');
187188
var operatorStar = nullableMembers.publicInstanceOperators
188189
.firstWhere((f) => f.name == 'operator *');
189-
expect(nullableMembers.isNNBD, isTrue);
190+
expect(nullableMembers.isNullSafety, isTrue);
190191
expect(
191192
nullableField.linkedReturnType,
192193
equals(
@@ -206,7 +207,7 @@ void main() {
206207
'<span class="parameter" id="*-param-nullableOther"><span class="type-annotation"><a href="%%__HTMLBASE_dartdoc_internal__%%nullable_elements/NullableMembers-class.html">NullableMembers</a>?</span> <span class="parameter-name">nullableOther</span></span><wbr>'));
207208
});
208209
},
209-
skip: (!_nnbdExperimentAllowed.allows(_platformVersion) &&
210+
skip: (!_nullSafetyExperimentAllowed.allows(_platformVersion) &&
210211
!_platformVersionString.contains('edge')));
211212

212213
group('HTML Injection when allowed', () {

0 commit comments

Comments
 (0)