blob: 5077871a778223f7a47c6806bd3764e030708d99 [file] [log] [blame]
// Copyright (c) 2015, 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.
// Tests related to the [TypeSystem] class.
library engine.type_system_test;
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/testing/element_factory.dart';
import 'package:analyzer/src/generated/testing/test_type_provider.dart';
import 'package:unittest/unittest.dart';
import '../reflective_tests.dart';
main() {
groupSep = ' | ';
runReflectiveTests(TypeSystemTest);
}
@reflectiveTest
class TypeSystemTest {
TypeProvider typeProvider;
TypeSystem typeSystem;
FunctionType simpleFunctionType;
DartType get bottomType => typeProvider.bottomType;
InterfaceType get doubleType => typeProvider.doubleType;
DartType get dynamicType => typeProvider.dynamicType;
InterfaceType get functionType => typeProvider.functionType;
InterfaceType get intType => typeProvider.intType;
InterfaceType get listType => typeProvider.listType;
InterfaceType get numType => typeProvider.numType;
InterfaceType get objectType => typeProvider.objectType;
InterfaceType get stringType => typeProvider.stringType;
DartType get voidType => VoidTypeImpl.instance;
void setUp() {
typeProvider = new TestTypeProvider();
typeSystem = new TypeSystemImpl(typeProvider);
FunctionTypeAliasElementImpl typeAlias =
ElementFactory.functionTypeAliasElement('A');
typeAlias.parameters = [];
typeAlias.returnType = voidType;
simpleFunctionType = typeAlias.type;
}
void test_getLeastUpperBound_bottom_function() {
_checkLeastUpperBound(bottomType, simpleFunctionType, simpleFunctionType);
}
void test_getLeastUpperBound_bottom_interface() {
DartType interfaceType = ElementFactory.classElement2('A', []).type;
_checkLeastUpperBound(bottomType, interfaceType, interfaceType);
}
void test_getLeastUpperBound_bottom_typeParam() {
DartType typeParam = ElementFactory.typeParameterElement('T').type;
_checkLeastUpperBound(bottomType, typeParam, typeParam);
}
void test_getLeastUpperBound_directInterfaceCase() {
//
// class A
// class B implements A
// class C implements B
//
ClassElementImpl classA = ElementFactory.classElement2("A");
ClassElementImpl classB = ElementFactory.classElement2("B");
ClassElementImpl classC = ElementFactory.classElement2("C");
InterfaceType typeA = classA.type;
InterfaceType typeB = classB.type;
InterfaceType typeC = classC.type;
classB.interfaces = <InterfaceType>[typeA];
classC.interfaces = <InterfaceType>[typeB];
_checkLeastUpperBound(typeB, typeC, typeB);
}
void test_getLeastUpperBound_directSubclassCase() {
//
// class A
// class B extends A
// class C extends B
//
ClassElementImpl classA = ElementFactory.classElement2("A");
ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
InterfaceType typeB = classB.type;
InterfaceType typeC = classC.type;
_checkLeastUpperBound(typeB, typeC, typeB);
}
void test_getLeastUpperBound_dynamic_bottom() {
_checkLeastUpperBound(dynamicType, bottomType, dynamicType);
}
void test_getLeastUpperBound_dynamic_function() {
_checkLeastUpperBound(dynamicType, simpleFunctionType, dynamicType);
}
void test_getLeastUpperBound_dynamic_interface() {
DartType interfaceType = ElementFactory.classElement2('A', []).type;
_checkLeastUpperBound(dynamicType, interfaceType, dynamicType);
}
void test_getLeastUpperBound_dynamic_typeParam() {
DartType typeParam = ElementFactory.typeParameterElement('T').type;
_checkLeastUpperBound(dynamicType, typeParam, dynamicType);
}
void test_getLeastUpperBound_dynamic_void() {
_checkLeastUpperBound(dynamicType, voidType, dynamicType);
}
void test_getLeastUpperBound_interface_function() {
DartType interfaceType = ElementFactory.classElement2('A', []).type;
_checkLeastUpperBound(interfaceType, simpleFunctionType, objectType);
}
void test_getLeastUpperBound_mixinCase() {
//
// class A
// class B extends A
// class C extends A
// class D extends B with M, N, O, P
//
ClassElement classA = ElementFactory.classElement2("A");
ClassElement classB = ElementFactory.classElement("B", classA.type);
ClassElement classC = ElementFactory.classElement("C", classA.type);
ClassElementImpl classD = ElementFactory.classElement("D", classB.type);
InterfaceType typeA = classA.type;
InterfaceType typeC = classC.type;
InterfaceType typeD = classD.type;
classD.mixins = <InterfaceType>[
ElementFactory.classElement2("M").type,
ElementFactory.classElement2("N").type,
ElementFactory.classElement2("O").type,
ElementFactory.classElement2("P").type
];
_checkLeastUpperBound(typeD, typeC, typeA);
}
void test_getLeastUpperBound_object() {
ClassElementImpl classA = ElementFactory.classElement2("A");
ClassElementImpl classB = ElementFactory.classElement2("B");
InterfaceType typeA = classA.type;
InterfaceType typeB = classB.type;
DartType typeObject = typeA.element.supertype;
// assert that object does not have a super type
expect((typeObject.element as ClassElement).supertype, isNull);
// assert that both A and B have the same super type of Object
expect(typeB.element.supertype, typeObject);
// finally, assert that the only least upper bound of A and B is Object
_checkLeastUpperBound(typeA, typeB, typeObject);
}
void test_getLeastUpperBound_self() {
DartType typeParam = ElementFactory.typeParameterElement('T').type;
DartType interfaceType = ElementFactory.classElement2('A', []).type;
expect(
typeSystem.getLeastUpperBound(dynamicType, dynamicType), dynamicType);
expect(typeSystem.getLeastUpperBound(voidType, voidType), voidType);
expect(typeSystem.getLeastUpperBound(bottomType, bottomType), bottomType);
expect(typeSystem.getLeastUpperBound(typeParam, typeParam), typeParam);
expect(typeSystem.getLeastUpperBound(interfaceType, interfaceType),
interfaceType);
expect(
typeSystem.getLeastUpperBound(simpleFunctionType, simpleFunctionType),
simpleFunctionType);
}
void test_getLeastUpperBound_sharedSuperclass1() {
ClassElementImpl classA = ElementFactory.classElement2("A");
ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
InterfaceType typeA = classA.type;
InterfaceType typeB = classB.type;
InterfaceType typeC = classC.type;
_checkLeastUpperBound(typeB, typeC, typeA);
}
void test_getLeastUpperBound_sharedSuperclass2() {
ClassElementImpl classA = ElementFactory.classElement2("A");
ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
ClassElementImpl classD = ElementFactory.classElement("D", classC.type);
InterfaceType typeA = classA.type;
InterfaceType typeB = classB.type;
InterfaceType typeD = classD.type;
_checkLeastUpperBound(typeB, typeD, typeA);
}
void test_getLeastUpperBound_sharedSuperclass3() {
ClassElementImpl classA = ElementFactory.classElement2("A");
ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
ClassElementImpl classD = ElementFactory.classElement("D", classB.type);
InterfaceType typeB = classB.type;
InterfaceType typeC = classC.type;
InterfaceType typeD = classD.type;
_checkLeastUpperBound(typeC, typeD, typeB);
}
void test_getLeastUpperBound_sharedSuperclass4() {
ClassElement classA = ElementFactory.classElement2("A");
ClassElement classA2 = ElementFactory.classElement2("A2");
ClassElement classA3 = ElementFactory.classElement2("A3");
ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
InterfaceType typeA = classA.type;
InterfaceType typeA2 = classA2.type;
InterfaceType typeA3 = classA3.type;
InterfaceType typeB = classB.type;
InterfaceType typeC = classC.type;
classB.interfaces = <InterfaceType>[typeA2];
classC.interfaces = <InterfaceType>[typeA3];
_checkLeastUpperBound(typeB, typeC, typeA);
}
void test_getLeastUpperBound_sharedSuperinterface1() {
ClassElementImpl classA = ElementFactory.classElement2("A");
ClassElementImpl classB = ElementFactory.classElement2("B");
ClassElementImpl classC = ElementFactory.classElement2("C");
InterfaceType typeA = classA.type;
InterfaceType typeB = classB.type;
InterfaceType typeC = classC.type;
classB.interfaces = <InterfaceType>[typeA];
classC.interfaces = <InterfaceType>[typeA];
_checkLeastUpperBound(typeB, typeC, typeA);
}
void test_getLeastUpperBound_sharedSuperinterface2() {
ClassElementImpl classA = ElementFactory.classElement2("A");
ClassElementImpl classB = ElementFactory.classElement2("B");
ClassElementImpl classC = ElementFactory.classElement2("C");
ClassElementImpl classD = ElementFactory.classElement2("D");
InterfaceType typeA = classA.type;
InterfaceType typeB = classB.type;
InterfaceType typeC = classC.type;
InterfaceType typeD = classD.type;
classB.interfaces = <InterfaceType>[typeA];
classC.interfaces = <InterfaceType>[typeA];
classD.interfaces = <InterfaceType>[typeC];
_checkLeastUpperBound(typeB, typeD, typeA);
}
void test_getLeastUpperBound_sharedSuperinterface3() {
ClassElementImpl classA = ElementFactory.classElement2("A");
ClassElementImpl classB = ElementFactory.classElement2("B");
ClassElementImpl classC = ElementFactory.classElement2("C");
ClassElementImpl classD = ElementFactory.classElement2("D");
InterfaceType typeA = classA.type;
InterfaceType typeB = classB.type;
InterfaceType typeC = classC.type;
InterfaceType typeD = classD.type;
classB.interfaces = <InterfaceType>[typeA];
classC.interfaces = <InterfaceType>[typeB];
classD.interfaces = <InterfaceType>[typeB];
_checkLeastUpperBound(typeC, typeD, typeB);
}
void test_getLeastUpperBound_sharedSuperinterface4() {
ClassElement classA = ElementFactory.classElement2("A");
ClassElement classA2 = ElementFactory.classElement2("A2");
ClassElement classA3 = ElementFactory.classElement2("A3");
ClassElementImpl classB = ElementFactory.classElement2("B");
ClassElementImpl classC = ElementFactory.classElement2("C");
InterfaceType typeA = classA.type;
InterfaceType typeA2 = classA2.type;
InterfaceType typeA3 = classA3.type;
InterfaceType typeB = classB.type;
InterfaceType typeC = classC.type;
classB.interfaces = <InterfaceType>[typeA, typeA2];
classC.interfaces = <InterfaceType>[typeA, typeA3];
_checkLeastUpperBound(typeB, typeC, typeA);
}
void test_getLeastUpperBound_twoComparables() {
_checkLeastUpperBound(stringType, numType, objectType);
}
void test_getLeastUpperBound_typeParam_function_bounded() {
DartType typeA = ElementFactory.classElement('A', functionType).type;
TypeParameterElementImpl typeParamElement =
ElementFactory.typeParameterElement('T');
typeParamElement.bound = typeA;
DartType typeParam = typeParamElement.type;
_checkLeastUpperBound(typeParam, simpleFunctionType, functionType);
}
void test_getLeastUpperBound_typeParam_function_noBound() {
DartType typeParam = ElementFactory.typeParameterElement('T').type;
_checkLeastUpperBound(typeParam, simpleFunctionType, objectType);
}
void test_getLeastUpperBound_typeParam_interface_bounded() {
DartType typeA = ElementFactory.classElement2('A', []).type;
DartType typeB = ElementFactory.classElement('B', typeA).type;
DartType typeC = ElementFactory.classElement('C', typeA).type;
TypeParameterElementImpl typeParamElement =
ElementFactory.typeParameterElement('T');
typeParamElement.bound = typeB;
DartType typeParam = typeParamElement.type;
_checkLeastUpperBound(typeParam, typeC, typeA);
}
void test_getLeastUpperBound_typeParam_interface_noBound() {
DartType typeParam = ElementFactory.typeParameterElement('T').type;
DartType interfaceType = ElementFactory.classElement2('A', []).type;
_checkLeastUpperBound(typeParam, interfaceType, objectType);
}
void test_getLeastUpperBound_typeParameters_different() {
//
// class List<int>
// class List<double>
//
InterfaceType listOfIntType = listType.substitute4(<DartType>[intType]);
InterfaceType listOfDoubleType =
listType.substitute4(<DartType>[doubleType]);
_checkLeastUpperBound(listOfIntType, listOfDoubleType, objectType);
}
void test_getLeastUpperBound_typeParameters_same() {
//
// List<int>
// List<int>
//
InterfaceType listOfIntType = listType.substitute4(<DartType>[intType]);
expect(typeSystem.getLeastUpperBound(listOfIntType, listOfIntType),
listOfIntType);
}
void test_getLeastUpperBound_void_bottom() {
_checkLeastUpperBound(voidType, bottomType, voidType);
}
void test_getLeastUpperBound_void_function() {
_checkLeastUpperBound(voidType, simpleFunctionType, voidType);
}
void test_getLeastUpperBound_void_interface() {
DartType interfaceType = ElementFactory.classElement2('A', []).type;
_checkLeastUpperBound(voidType, interfaceType, voidType);
}
void test_getLeastUpperBound_void_typeParam() {
DartType typeParam = ElementFactory.typeParameterElement('T').type;
_checkLeastUpperBound(voidType, typeParam, voidType);
}
void _checkLeastUpperBound(
DartType type1, DartType type2, DartType expectedResult) {
expect(typeSystem.getLeastUpperBound(type1, type2), expectedResult);
}
}