blob: 1bfb59594eb6c6ccea2a58180b967ffd21bc1399 [file] [log] [blame]
// 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 file.
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../../generated/type_system_test.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(IsNonNullableTest);
defineReflectiveTests(IsNullableTest);
defineReflectiveTests(IsPotentiallyNonNullableTest);
defineReflectiveTests(IsPotentiallyNullableTest);
defineReflectiveTests(IsStrictlyNonNullableTest);
defineReflectiveTests(PromoteToNonNullTest);
});
}
@reflectiveTest
class IsNonNullableTest extends AbstractTypeSystemNullSafetyTest {
void isNonNullable(DartType type) {
expect(typeSystem.isNonNullable(type), isTrue);
}
void isNotNonNullable(DartType type) {
expect(typeSystem.isNonNullable(type), isFalse);
}
test_dynamic() {
isNotNonNullable(dynamicType);
}
test_function() {
isNonNullable(
functionTypeNone(returnType: voidNone),
);
isNotNonNullable(
functionTypeQuestion(returnType: voidNone),
);
isNonNullable(
functionTypeStar(returnType: voidNone),
);
}
test_functionClass() {
isNonNullable(functionNone);
isNotNonNullable(functionQuestion);
isNonNullable(functionStar);
}
test_futureOr_noneArgument() {
isNonNullable(
futureOrNone(intNone),
);
isNotNonNullable(
futureOrQuestion(intNone),
);
isNonNullable(
futureOrStar(intNone),
);
}
test_futureOr_questionArgument() {
isNotNonNullable(
futureOrNone(intQuestion),
);
isNotNonNullable(
futureOrQuestion(intQuestion),
);
isNotNonNullable(
futureOrStar(intQuestion),
);
}
test_futureOr_starArgument() {
isNonNullable(
futureOrNone(intStar),
);
isNotNonNullable(
futureOrStar(intQuestion),
);
isNonNullable(
futureOrStar(intStar),
);
}
test_interface() {
isNonNullable(intNone);
isNotNonNullable(intQuestion);
isNonNullable(intStar);
}
test_never() {
isNonNullable(neverNone);
isNotNonNullable(neverQuestion);
isNonNullable(neverStar);
}
test_null() {
isNotNonNullable(nullStar);
}
test_typeParameter_boundNone() {
var T = typeParameter('T', bound: intNone);
isNonNullable(
typeParameterTypeNone(T),
);
isNotNonNullable(
typeParameterTypeQuestion(T),
);
}
test_typeParameter_boundQuestion() {
var T = typeParameter('T', bound: intQuestion);
isNotNonNullable(
typeParameterTypeNone(T),
);
isNotNonNullable(
typeParameterTypeQuestion(T),
);
}
test_typeParameter_boundStar() {
var T = typeParameter('T', bound: intStar);
isNonNullable(
typeParameterTypeStar(T),
);
}
test_typeParameter_promotedBoundNone() {
var T = typeParameter('T');
isNonNullable(
typeParameterTypeNone(T, promotedBound: intNone),
);
isNonNullable(
typeParameterTypeQuestion(T, promotedBound: intNone),
);
}
test_typeParameter_promotedBoundQuestion() {
var T = typeParameter('T');
isNotNonNullable(
typeParameterTypeNone(T, promotedBound: intQuestion),
);
isNotNonNullable(
typeParameterTypeQuestion(T, promotedBound: intQuestion),
);
}
test_typeParameter_promotedBoundStar() {
var T = typeParameter('T');
isNonNullable(
typeParameterTypeNone(T, promotedBound: intStar),
);
isNonNullable(
typeParameterTypeQuestion(T, promotedBound: intStar),
);
}
test_void() {
isNotNonNullable(voidNone);
}
}
@reflectiveTest
class IsNullableTest extends AbstractTypeSystemNullSafetyTest {
void isNotNullable(DartType type) {
expect(typeSystem.isNullable(type), isFalse);
}
void isNullable(DartType type) {
expect(typeSystem.isNullable(type), isTrue);
}
test_dynamic() {
isNullable(dynamicType);
}
test_function() {
isNotNullable(
functionTypeNone(returnType: voidNone),
);
isNullable(
functionTypeQuestion(returnType: voidNone),
);
isNotNullable(
functionTypeStar(returnType: voidNone),
);
}
test_functionClass() {
isNotNullable(functionNone);
isNullable(functionQuestion);
isNotNullable(functionStar);
}
test_futureOr_noneArgument() {
isNotNullable(
futureOrNone(intNone),
);
isNullable(
futureOrQuestion(intNone),
);
isNotNullable(
futureOrStar(intNone),
);
}
test_futureOr_questionArgument() {
isNullable(
futureOrNone(intQuestion),
);
isNullable(
futureOrQuestion(intQuestion),
);
isNullable(
futureOrStar(intQuestion),
);
}
test_futureOr_starArgument() {
isNotNullable(
futureOrNone(intStar),
);
isNullable(
futureOrQuestion(intStar),
);
isNotNullable(
futureOrStar(intStar),
);
}
test_interface() {
isNotNullable(intNone);
isNullable(intQuestion);
isNotNullable(intStar);
}
test_never() {
isNotNullable(neverNone);
isNullable(neverQuestion);
isNotNullable(neverStar);
}
test_null() {
isNullable(nullStar);
}
test_typeParameter_boundNone() {
var T = typeParameter('T', bound: intNone);
isNotNullable(
typeParameterTypeNone(T),
);
isNullable(
typeParameterTypeQuestion(T),
);
}
test_typeParameter_boundQuestion_none() {
var T = typeParameter('T', bound: intQuestion);
isNotNullable(
typeParameterTypeNone(T),
);
isNullable(
typeParameterTypeQuestion(T),
);
}
test_typeParameter_boundStar() {
var T = typeParameter('T', bound: intStar);
isNotNullable(
typeParameterTypeStar(T),
);
}
test_typeParameter_promotedBoundNone() {
var T = typeParameter('T');
isNotNullable(
typeParameterTypeNone(T, promotedBound: intNone),
);
isNotNullable(
typeParameterTypeQuestion(T, promotedBound: intNone),
);
}
test_typeParameter_promotedBoundQuestion() {
var T = typeParameter('T');
isNullable(
typeParameterTypeNone(T, promotedBound: intQuestion),
);
isNullable(
typeParameterTypeQuestion(T, promotedBound: intQuestion),
);
}
test_typeParameter_promotedBoundStar() {
var T = typeParameter('T');
isNotNullable(
typeParameterTypeNone(T, promotedBound: intStar),
);
isNotNullable(
typeParameterTypeQuestion(T, promotedBound: intStar),
);
}
test_void() {
isNullable(voidNone);
}
}
@reflectiveTest
class IsPotentiallyNonNullableTest extends AbstractTypeSystemNullSafetyTest {
void isNotPotentiallyNonNullable(DartType type) {
expect(typeSystem.isPotentiallyNonNullable(type), isFalse);
}
void isPotentiallyNonNullable(DartType type) {
expect(typeSystem.isPotentiallyNonNullable(type), isTrue);
}
test_dynamic() {
isNotPotentiallyNonNullable(dynamicType);
}
test_futureOr() {
isPotentiallyNonNullable(
futureOrNone(intNone),
);
isNotPotentiallyNonNullable(
futureOrNone(intQuestion),
);
isPotentiallyNonNullable(
futureOrNone(intStar),
);
}
test_interface() {
isPotentiallyNonNullable(intNone);
isNotPotentiallyNonNullable(intQuestion);
isPotentiallyNonNullable(intStar);
}
test_never() {
isPotentiallyNonNullable(neverNone);
}
test_null() {
isNotPotentiallyNonNullable(nullStar);
}
test_void() {
isNotPotentiallyNonNullable(voidNone);
}
}
@reflectiveTest
class IsPotentiallyNullableTest extends AbstractTypeSystemNullSafetyTest {
void isNotPotentiallyNullable(DartType type) {
expect(typeSystem.isPotentiallyNullable(type), isFalse);
}
void isPotentiallyNullable(DartType type) {
expect(typeSystem.isPotentiallyNullable(type), isTrue);
}
test_dynamic() {
isPotentiallyNullable(dynamicType);
}
test_futureOr() {
isNotPotentiallyNullable(
futureOrNone(intNone),
);
isPotentiallyNullable(
futureOrNone(intQuestion),
);
isNotPotentiallyNullable(
futureOrNone(intStar),
);
}
test_interface() {
isNotPotentiallyNullable(intNone);
isPotentiallyNullable(intQuestion);
isNotPotentiallyNullable(intStar);
}
test_never() {
isNotPotentiallyNullable(neverNone);
}
test_null() {
isPotentiallyNullable(nullStar);
}
test_void() {
isPotentiallyNullable(voidNone);
}
}
@reflectiveTest
class IsStrictlyNonNullableTest extends AbstractTypeSystemNullSafetyTest {
void isNotStrictlyNonNullable(DartType type) {
expect(typeSystem.isStrictlyNonNullable(type), isFalse);
}
void isStrictlyNonNullable(DartType type) {
expect(typeSystem.isStrictlyNonNullable(type), isTrue);
}
test_dynamic() {
isNotStrictlyNonNullable(dynamicType);
}
test_function() {
isStrictlyNonNullable(
functionTypeNone(returnType: voidNone),
);
isNotStrictlyNonNullable(
functionTypeQuestion(returnType: voidNone),
);
isNotStrictlyNonNullable(
functionTypeStar(returnType: voidNone),
);
}
test_functionClass() {
isStrictlyNonNullable(functionNone);
isNotStrictlyNonNullable(functionQuestion);
isNotStrictlyNonNullable(functionStar);
}
test_futureOr_noneArgument() {
isStrictlyNonNullable(
futureOrNone(intNone),
);
isNotStrictlyNonNullable(
futureOrQuestion(intNone),
);
isNotStrictlyNonNullable(
futureOrStar(intNone),
);
}
test_futureOr_questionArgument() {
isNotStrictlyNonNullable(
futureOrNone(intQuestion),
);
isNotStrictlyNonNullable(
futureOrQuestion(intQuestion),
);
isNotStrictlyNonNullable(
futureOrStar(intQuestion),
);
}
test_futureOr_starArgument() {
isNotStrictlyNonNullable(
futureOrNone(intStar),
);
isNotStrictlyNonNullable(
futureOrStar(intQuestion),
);
isNotStrictlyNonNullable(
futureOrStar(intStar),
);
}
test_interface() {
isStrictlyNonNullable(intNone);
isNotStrictlyNonNullable(intQuestion);
isNotStrictlyNonNullable(intStar);
}
test_never() {
isStrictlyNonNullable(neverNone);
isNotStrictlyNonNullable(neverQuestion);
isNotStrictlyNonNullable(neverStar);
}
test_null() {
isNotStrictlyNonNullable(nullNone);
isNotStrictlyNonNullable(nullQuestion);
isNotStrictlyNonNullable(nullStar);
}
test_typeParameter_boundNone() {
var T = typeParameter('T', bound: intNone);
isStrictlyNonNullable(
typeParameterTypeNone(T),
);
isNotStrictlyNonNullable(
typeParameterTypeQuestion(T),
);
isNotStrictlyNonNullable(
typeParameterTypeStar(T),
);
}
test_typeParameter_boundQuestion() {
var T = typeParameter('T', bound: intQuestion);
isNotStrictlyNonNullable(
typeParameterTypeNone(T),
);
isNotStrictlyNonNullable(
typeParameterTypeQuestion(T),
);
isNotStrictlyNonNullable(
typeParameterTypeStar(T),
);
}
test_typeParameter_boundStar() {
var T = typeParameter('T', bound: intStar);
isNotStrictlyNonNullable(
typeParameterTypeNone(T),
);
isNotStrictlyNonNullable(
typeParameterTypeQuestion(T),
);
isNotStrictlyNonNullable(
typeParameterTypeStar(T),
);
}
test_void() {
isNotStrictlyNonNullable(voidNone);
}
}
@reflectiveTest
class PromoteToNonNullTest extends AbstractTypeSystemNullSafetyTest {
test_dynamic() {
_check(dynamicType, dynamicType);
}
test_functionType() {
// NonNull(T0 Function(...)) = T0 Function(...)
_check(
functionTypeQuestion(returnType: voidNone),
functionTypeNone(returnType: voidNone),
);
}
test_futureOr_question() {
// NonNull(FutureOr<T>) = FutureOr<T>
_check(
futureOrQuestion(stringQuestion),
futureOrNone(stringQuestion),
);
}
test_interfaceType() {
_check(intNone, intNone);
_check(intQuestion, intNone);
_check(intStar, intNone);
// NonNull(C<T1, ... , Tn>) = C<T1, ... , Tn>
_check(
listQuestion(intQuestion),
listNone(intQuestion),
);
}
test_interfaceType_function() {
_check(functionQuestion, functionNone);
}
test_never() {
_check(neverNone, neverNone);
}
test_null() {
_check(nullStar, neverNone);
}
test_typeParameter_bound_dynamic() {
var element = typeParameter('T', bound: dynamicNone);
_checkTypeParameter(
typeParameterTypeNone(element),
element: element,
promotedBound: null,
);
}
test_typeParameter_bound_none() {
var element = typeParameter('T', bound: intNone);
_checkTypeParameter(
typeParameterTypeNone(element),
element: element,
promotedBound: null,
);
_checkTypeParameter(
typeParameterTypeQuestion(element),
element: element,
promotedBound: null,
);
}
test_typeParameter_bound_null() {
var element = typeParameter('T', bound: null);
_checkTypeParameter(
typeParameterTypeNone(element),
element: element,
promotedBound: objectNone,
);
}
test_typeParameter_bound_question() {
var element = typeParameter('T', bound: intQuestion);
_checkTypeParameter(
typeParameterTypeNone(element),
element: element,
promotedBound: intNone,
);
_checkTypeParameter(
typeParameterTypeQuestion(element),
element: element,
promotedBound: intNone,
);
_checkTypeParameter(
typeParameterTypeStar(element),
element: element,
promotedBound: intNone,
);
}
test_typeParameter_bound_star() {
var element = typeParameter('T', bound: intStar);
_checkTypeParameter(
typeParameterTypeNone(element),
element: element,
promotedBound: intNone,
);
}
test_typeParameter_promotedBound_none() {
var element = typeParameter('T', bound: numQuestion);
_checkTypeParameter(
promotedTypeParameterTypeNone(element, intNone),
element: element,
promotedBound: intNone,
);
_checkTypeParameter(
promotedTypeParameterTypeQuestion(element, intNone),
element: element,
promotedBound: intNone,
);
_checkTypeParameter(
promotedTypeParameterTypeStar(element, intNone),
element: element,
promotedBound: intNone,
);
}
test_typeParameter_promotedBound_question() {
var element = typeParameter('T', bound: numQuestion);
_checkTypeParameter(
promotedTypeParameterTypeNone(element, intQuestion),
element: element,
promotedBound: intNone,
);
_checkTypeParameter(
promotedTypeParameterTypeQuestion(element, intQuestion),
element: element,
promotedBound: intNone,
);
_checkTypeParameter(
promotedTypeParameterTypeStar(element, intQuestion),
element: element,
promotedBound: intNone,
);
}
test_typeParameter_promotedBound_star() {
var element = typeParameter('T', bound: numQuestion);
_checkTypeParameter(
promotedTypeParameterTypeNone(element, intStar),
element: element,
promotedBound: intNone,
);
_checkTypeParameter(
promotedTypeParameterTypeQuestion(element, intStar),
element: element,
promotedBound: intNone,
);
_checkTypeParameter(
promotedTypeParameterTypeStar(element, intStar),
element: element,
promotedBound: intNone,
);
}
test_void() {
_check(voidNone, voidNone);
}
void _check(DartType type, DartType expected) {
var result = typeSystem.promoteToNonNull(type);
expect(result, expected);
}
void _checkTypeParameter(
TypeParameterType type, {
required TypeParameterElement element,
required DartType? promotedBound,
}) {
var actual = typeSystem.promoteToNonNull(type) as TypeParameterTypeImpl;
expect(actual.element, same(element));
expect(actual.promotedBound, promotedBound);
expect(actual.nullabilitySuffix, NullabilitySuffix.none);
}
}