blob: 27fe4bbe5680fcd68c61980873e6c67b089b4953 [file] [log] [blame]
// Copyright (c) 2013, 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.
library mixin_typevariable_test;
import 'package:expect/expect.dart';
import "package:async_helper/async_helper.dart";
import 'type_test_helper.dart';
import 'package:compiler/src/dart_types.dart';
import "package:compiler/src/elements/elements.dart"
show Element, ClassElement;
void main() {
testMixinSupertypes();
testNonTrivialSubstitutions();
}
void testMixinSupertypes() {
asyncTest(() => TypeEnvironment.create(r"""
class S<S_T> {}
class M1<M1_T> {}
class M2<M2_T> {}
class M3<M3_T> {}
class C1<C1_T> extends S<C1_T> with M1<C1_T>, M2<C1_T>, M3<C1_T> {}
class C2<C2_T> = S<C2_T> with M1<C2_T>, M2<C2_T>, M3<C2_T>;
""", expectNoWarningsOrErrors: true).then((env) {
ClassElement Object = env.getElement('Object');
ClassElement S = env.getElement('S');
ClassElement M1 = env.getElement('M1');
ClassElement M2 = env.getElement('M2');
ClassElement M3 = env.getElement('M3');
ClassElement C1 = env.getElement('C1');
ClassElement C2 = env.getElement('C2');
ClassElement C1_S_M1_M2_M3 = C1.superclass;
ClassElement C1_S_M1_M2 = C1_S_M1_M2_M3.superclass;
ClassElement C1_S_M1 = C1_S_M1_M2.superclass;
ClassElement C2_S_M1_M2 = C2.superclass;
ClassElement C2_S_M1 = C2_S_M1_M2.superclass;
void testSupertypes(ClassElement element) {
if (element != Object) {
Expect.isTrue(element.typeVariables.length == 1);
Expect.equals(element,
element.typeVariables.first.element.enclosingElement);
}
for (InterfaceType supertype in element.allSupertypesAndSelf.types) {
if (!supertype.typeArguments.isEmpty) {
Expect.listEquals(element.typeVariables, supertype.typeArguments,
"Type argument mismatch on supertype $supertype of $element.");
} else {
Expect.equals(Object, supertype.element);
}
}
}
testSupertypes(Object);
testSupertypes(S);
testSupertypes(M1);
testSupertypes(M2);
testSupertypes(C1_S_M1);
testSupertypes(C1_S_M1_M2);
testSupertypes(C1_S_M1_M2_M3);
testSupertypes(C1);
testSupertypes(C2_S_M1);
testSupertypes(C2_S_M1_M2);
testSupertypes(C2);
}));
}
void testNonTrivialSubstitutions() {
asyncTest(() => TypeEnvironment.create(r"""
class _ {}
class A<A_T> {}
class B<B_T, B_S> {}
class C1<C1_T> extends A with B {}
class C2<C2_T> = A with B;
class D1<D1_T> extends A<D1_T> with B<D1_T, A<D1_T>> {}
class D2<D2_T> = A<D2_T> with B<D2_T, A<D2_T>>;
class E1<E1_T> extends A<_> with B<_, A<_>> {}
class E2<E2_T> = A<_> with B<_, A<_>>;
class F1<F1_T> extends A<_> with B<_, B<F1_T, _>> {}
class F2<F2_T> = A<_> with B<_, B<F2_T, _>>;
""", expectNoWarningsOrErrors: true).then((env) {
DartType _dynamic = env['dynamic'];
DartType _ = env['_'];
ClassElement Object = env.getElement('Object');
ClassElement A = env.getElement('A');
ClassElement B = env.getElement('B');
ClassElement C1 = env.getElement('C1');
ClassElement C2 = env.getElement('C2');
ClassElement D1 = env.getElement('D1');
ClassElement D2 = env.getElement('D2');
ClassElement E1 = env.getElement('E1');
ClassElement E2 = env.getElement('E2');
ClassElement F1 = env.getElement('F1');
ClassElement F2 = env.getElement('F2');
ClassElement C1_A_B = C1.superclass;
ClassElement D1_A_B = D1.superclass;
ClassElement E1_A_B = E1.superclass;
ClassElement F1_A_B = F1.superclass;
void testSupertypes(ClassElement element,
Map<ClassElement, List<DartType>> typeArguments) {
if (element != Object) {
Expect.isTrue(element.typeVariables.length == 1);
Expect.equals(element,
element.typeVariables.first.element.enclosingElement);
}
for (InterfaceType supertype in element.allSupertypesAndSelf.types) {
if (typeArguments.containsKey(supertype.element)) {
Expect.listEquals(typeArguments[supertype.element],
supertype.typeArguments,
"Type argument mismatch on supertype $supertype of $element.");
} else if (!supertype.typeArguments.isEmpty) {
Expect.listEquals(element.typeVariables, supertype.typeArguments,
"Type argument mismatch on supertype $supertype of $element.");
} else {
Expect.equals(Object, supertype.element);
}
}
}
testSupertypes(C1, {A: [_dynamic], B: [_dynamic, _dynamic]});
testSupertypes(C1.superclass, {A: [_dynamic], B: [_dynamic, _dynamic]});
testSupertypes(C2, {A: [_dynamic], B: [_dynamic, _dynamic]});
DartType D1_T = D1.typeVariables.first;
testSupertypes(D1, {A: [D1_T], B: [D1_T, instantiate(A, [D1_T])]});
DartType D1_superclass_T = D1.superclass.typeVariables.first;
testSupertypes(D1.superclass,
{A: [D1_superclass_T],
B: [D1_superclass_T, instantiate(A, [D1_superclass_T])]});
DartType D2_T = D2.typeVariables.first;
testSupertypes(D2, {A: [D2_T], B: [D2_T, instantiate(A, [D2_T])]});
testSupertypes(E1, {A: [_], B: [_, instantiate(A, [_])]});
testSupertypes(E1.superclass, {A: [_], B: [_, instantiate(A, [_])]});
testSupertypes(E2, {A: [_], B: [_, instantiate(A, [_])]});
DartType F1_T = F1.typeVariables.first;
testSupertypes(F1, {A: [_], B: [_, instantiate(B, [F1_T, _])]});
DartType F1_superclass_T = F1.superclass.typeVariables.first;
testSupertypes(F1.superclass, {A: [_], B: [_, instantiate(B, [F1_superclass_T, _])]});
DartType F2_T = F2.typeVariables.first;
testSupertypes(F2, {A: [_], B: [_, instantiate(B, [F2_T, _])]});
}));
}