Tests for isNullable() and isNonNullable() and type parameters.
R=brianwilkerson@google.com
Change-Id: I120363de7067be8665995bbe2353f29240c9b961
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106601
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/dart/element/type_system.dart b/pkg/analyzer/lib/dart/element/type_system.dart
index df6cbe8..7906724 100644
--- a/pkg/analyzer/lib/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/dart/element/type_system.dart
@@ -94,7 +94,7 @@
@experimental
bool isPotentiallyNonNullable(DartType type);
- /// Return `true` if the [type] is not a potentially nullable type.
+ /// Return `true` if the [type] is a potentially nullable type.
///
/// We say that a type `T` is potentially nullable if `T` is not non-nullable.
/// Note that this is different from saying that `T` is nullable. For example,
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 4e222f6..53d06e1 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -2107,9 +2107,13 @@
return false;
} else if (type.isDartAsyncFutureOr) {
isNonNullable((type as InterfaceType).typeArguments[0]);
+ } else if ((type as TypeImpl).nullabilitySuffix ==
+ NullabilitySuffix.question) {
+ return false;
+ } else if (type is TypeParameterType) {
+ return isNonNullable(type.bound);
}
- return (type as TypeImpl).nullabilitySuffix != NullabilitySuffix.question &&
- (type is TypeParameterType ? isNonNullable(type.bound) : true);
+ return true;
}
@override
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index c3df650..511ce30 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -22,6 +22,7 @@
import 'package:analyzer/src/generated/testing/element_factory.dart';
import 'package:analyzer/src/generated/testing/test_type_provider.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:meta/meta.dart';
import 'package:path/path.dart' show toUri;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -2459,8 +2460,10 @@
class TypeSystemTest extends AbstractTypeSystemTest {
DartType get futureOrWithNoneType =>
typeProvider.futureOrType.instantiate([noneType]);
+
DartType get futureOrWithQuestionType =>
typeProvider.futureOrType.instantiate([questionType]);
+
DartType get futureOrWithStarType =>
typeProvider.futureOrType.instantiate([starType]);
@@ -2505,6 +2508,51 @@
expect(typeSystem.isNonNullable(starType), true);
}
+ test_isNonNullable_typeParameter_noneBound_none() {
+ expect(
+ typeSystem.isNonNullable(
+ typeParameterTypeNone(bound: noneType),
+ ),
+ true,
+ );
+ }
+
+ test_isNonNullable_typeParameter_noneBound_question() {
+ expect(
+ typeSystem.isNonNullable(
+ typeParameterTypeQuestion(bound: noneType),
+ ),
+ false,
+ );
+ }
+
+ test_isNonNullable_typeParameter_questionBound_none() {
+ expect(
+ typeSystem.isNonNullable(
+ typeParameterTypeNone(bound: questionType),
+ ),
+ false,
+ );
+ }
+
+ test_isNonNullable_typeParameter_questionBound_question() {
+ expect(
+ typeSystem.isNonNullable(
+ typeParameterTypeQuestion(bound: questionType),
+ ),
+ false,
+ );
+ }
+
+ test_isNonNullable_typeParameter_starBound_star() {
+ expect(
+ typeSystem.isNonNullable(
+ typeParameterTypeStar(bound: starType),
+ ),
+ true,
+ );
+ }
+
test_isNonNullable_void() {
expect(typeSystem.isNonNullable(voidType), false);
}
@@ -2541,6 +2589,51 @@
expect(typeSystem.isNullable(starType), true);
}
+ test_isNullable_typeParameter_noneBound_none() {
+ expect(
+ typeSystem.isNullable(
+ typeParameterTypeNone(bound: noneType),
+ ),
+ false,
+ );
+ }
+
+ test_isNullable_typeParameter_noneBound_question() {
+ expect(
+ typeSystem.isNullable(
+ typeParameterTypeQuestion(bound: noneType),
+ ),
+ true,
+ );
+ }
+
+ test_isNullable_typeParameter_questionBound_none() {
+ expect(
+ typeSystem.isNullable(
+ typeParameterTypeNone(bound: questionType),
+ ),
+ false,
+ );
+ }
+
+ test_isNullable_typeParameter_questionBound_question() {
+ expect(
+ typeSystem.isNullable(
+ typeParameterTypeQuestion(bound: questionType),
+ ),
+ true,
+ );
+ }
+
+ test_isNullable_typeParameter_starBound_star() {
+ expect(
+ typeSystem.isNullable(
+ typeParameterTypeStar(bound: starType),
+ ),
+ true,
+ );
+ }
+
test_isNullable_void() {
expect(typeSystem.isNullable(voidType), true);
}
@@ -2617,4 +2710,28 @@
test_isPotentiallyNullable_void() {
expect(typeSystem.isPotentiallyNullable(voidType), true);
}
+
+ DartType typeParameterTypeNone({@required DartType bound}) {
+ expect(bound, isNotNull);
+ var element = TypeParameterElementImpl.synthetic('T');
+ element.bound = bound;
+ return TypeParameterTypeImpl(element,
+ nullabilitySuffix: NullabilitySuffix.none);
+ }
+
+ DartType typeParameterTypeQuestion({@required DartType bound}) {
+ expect(bound, isNotNull);
+ var element = TypeParameterElementImpl.synthetic('T');
+ element.bound = bound;
+ return TypeParameterTypeImpl(element,
+ nullabilitySuffix: NullabilitySuffix.question);
+ }
+
+ DartType typeParameterTypeStar({@required DartType bound}) {
+ expect(bound, isNotNull);
+ var element = TypeParameterElementImpl.synthetic('T');
+ element.bound = bound;
+ return TypeParameterTypeImpl(element,
+ nullabilitySuffix: NullabilitySuffix.star);
+ }
}