blob: dfde08eea0034229e26d71f2c4689fa29b0b002b [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_base.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(IsNonNullableTest);
defineReflectiveTests(IsNullableTest);
defineReflectiveTests(IsPotentiallyNonNullableTest);
defineReflectiveTests(IsPotentiallyNullableTest);
defineReflectiveTests(IsStrictlyNonNullableTest);
defineReflectiveTests(PromoteToNonNullTest);
});
}
@reflectiveTest
class IsNonNullableTest extends AbstractTypeSystemTest {
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));
}
test_functionClass() {
isNonNullable(functionNone);
isNotNonNullable(functionQuestion);
}
test_futureOr_noneArgument() {
isNonNullable(futureOrNone(intNone));
isNotNonNullable(futureOrQuestion(intNone));
}
test_futureOr_questionArgument() {
isNotNonNullable(futureOrNone(intQuestion));
isNotNonNullable(futureOrQuestion(intQuestion));
}
test_interface() {
isNonNullable(intNone);
isNotNonNullable(intQuestion);
}
test_interface_extensionType2() {
isNotNonNullable(
interfaceTypeNone(extensionType2('A', representationType: intNone)),
);
isNonNullable(
interfaceTypeNone(
extensionType2('A', representationType: intNone, interfaces: [intNone]),
),
);
}
test_invalidType() {
isNotNonNullable(invalidType);
}
test_never() {
isNonNullable(neverNone);
isNotNonNullable(neverQuestion);
}
test_null() {
isNotNonNullable(nullNone);
}
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_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_void() {
isNotNonNullable(voidNone);
}
}
@reflectiveTest
class IsNullableTest extends AbstractTypeSystemTest {
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));
}
test_functionClass() {
isNotNullable(functionNone);
isNullable(functionQuestion);
}
test_futureOr_noneArgument() {
isNotNullable(futureOrNone(intNone));
isNullable(futureOrQuestion(intNone));
}
test_futureOr_questionArgument() {
isNullable(futureOrNone(intQuestion));
isNullable(futureOrQuestion(intQuestion));
}
test_interface() {
isNotNullable(intNone);
isNullable(intQuestion);
}
test_interface_extensionType2() {
isNotNullable(
interfaceTypeNone(extensionType2('A', representationType: intNone)),
);
isNotNullable(
interfaceTypeNone(
extensionType2('A', representationType: intNone, interfaces: [intNone]),
),
);
isNullable(
interfaceTypeQuestion(
extensionType2('A', representationType: intNone, interfaces: [intNone]),
),
);
}
test_invalidType() {
isNullable(invalidType);
}
test_never() {
isNotNullable(neverNone);
isNullable(neverQuestion);
}
test_null() {
isNullable(nullNone);
}
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_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_void() {
isNullable(voidNone);
}
}
@reflectiveTest
class IsPotentiallyNonNullableTest extends AbstractTypeSystemTest {
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));
}
test_interface() {
isPotentiallyNonNullable(intNone);
isNotPotentiallyNonNullable(intQuestion);
}
test_interface_extensionType2() {
isPotentiallyNonNullable(
interfaceTypeNone(extensionType2('A', representationType: intNone)),
);
isPotentiallyNonNullable(
interfaceTypeNone(
extensionType2('A', representationType: intNone, interfaces: [intNone]),
),
);
}
test_invalidType() {
isNotPotentiallyNonNullable(invalidType);
}
test_never() {
isPotentiallyNonNullable(neverNone);
}
test_null() {
isNotPotentiallyNonNullable(nullNone);
}
test_void() {
isNotPotentiallyNonNullable(voidNone);
}
}
@reflectiveTest
class IsPotentiallyNullableTest extends AbstractTypeSystemTest {
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));
}
test_interface() {
isNotPotentiallyNullable(intNone);
isPotentiallyNullable(intQuestion);
}
test_interface_extensionType2() {
isPotentiallyNullable(
interfaceTypeQuestion(extensionType2('A', representationType: intNone)),
);
isPotentiallyNullable(
interfaceTypeNone(extensionType2('A', representationType: intNone)),
);
isNotPotentiallyNullable(
interfaceTypeNone(
extensionType2('A', representationType: intNone, interfaces: [intNone]),
),
);
}
test_invalidType() {
isPotentiallyNullable(invalidType);
}
test_never() {
isNotPotentiallyNullable(neverNone);
}
test_null() {
isPotentiallyNullable(nullNone);
}
test_void() {
isPotentiallyNullable(voidNone);
}
}
@reflectiveTest
class IsStrictlyNonNullableTest extends AbstractTypeSystemTest {
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));
}
test_functionClass() {
isStrictlyNonNullable(functionNone);
isNotStrictlyNonNullable(functionQuestion);
}
test_futureOr_noneArgument() {
isStrictlyNonNullable(futureOrNone(intNone));
isNotStrictlyNonNullable(futureOrQuestion(intNone));
}
test_futureOr_questionArgument() {
isNotStrictlyNonNullable(futureOrNone(intQuestion));
isNotStrictlyNonNullable(futureOrQuestion(intQuestion));
}
test_interface() {
isStrictlyNonNullable(intNone);
isNotStrictlyNonNullable(intQuestion);
}
test_interface_extensionType2() {
isNotStrictlyNonNullable(
interfaceTypeNone(extensionType2('A', representationType: intNone)),
);
isStrictlyNonNullable(
interfaceTypeNone(
extensionType2('A', representationType: intNone, interfaces: [intNone]),
),
);
}
test_invalidType() {
isNotStrictlyNonNullable(invalidType);
}
test_never() {
isStrictlyNonNullable(neverNone);
isNotStrictlyNonNullable(neverQuestion);
}
test_null() {
isNotStrictlyNonNullable(nullNone);
}
test_typeParameter_boundNone() {
var T = typeParameter('T', bound: intNone);
isStrictlyNonNullable(typeParameterTypeNone(T));
isNotStrictlyNonNullable(typeParameterTypeQuestion(T));
}
test_typeParameter_boundQuestion() {
var T = typeParameter('T', bound: intQuestion);
isNotStrictlyNonNullable(typeParameterTypeNone(T));
isNotStrictlyNonNullable(typeParameterTypeQuestion(T));
}
test_void() {
isNotStrictlyNonNullable(voidNone);
}
}
@reflectiveTest
class PromoteToNonNullTest extends AbstractTypeSystemTest {
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);
// NonNull(C<T1, ... , Tn>) = C<T1, ... , Tn>
_check(listQuestion(intQuestion), listNone(intQuestion));
}
test_interfaceType_function() {
_check(functionQuestion, functionNone);
}
test_invalidType() {
_check(invalidType, invalidType);
}
test_never() {
_check(neverNone, neverNone);
}
test_null() {
_check(nullNone, neverNone);
}
test_typeParameter_bound_dynamic() {
var element = typeParameter('T', bound: dynamicType);
_checkTypeParameter(
typeParameterTypeNone(element),
element: element,
promotedBound: null,
);
}
test_typeParameter_bound_invalidType() {
var element = typeParameter('T', bound: invalidType);
_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');
_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,
);
}
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,
);
}
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,
);
}
test_void() {
_check(voidNone, voidNone);
}
void _check(TypeImpl type, TypeImpl expected) {
var result = typeSystem.promoteToNonNull(type);
expect(result, expected);
}
void _checkTypeParameter(
TypeParameterTypeImpl type, {
required TypeParameterElement element,
required TypeImpl? promotedBound,
}) {
var actual = typeSystem.promoteToNonNull(type) as TypeParameterTypeImpl;
expect(actual.element3, same(element));
expect(actual.promotedBound, promotedBound);
expect(actual.nullabilitySuffix, NullabilitySuffix.none);
}
}