Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Unified Diff: pkg/kernel/test/class_hierarchy_test.dart

Issue 2912173002: Start adding unit tests for ClassHierarchy. (Closed)
Patch Set: Rollback inlining JUnit and a tweak for TODO. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/kernel/pubspec.yaml ('k') | pkg/kernel/test/lub_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/kernel/test/class_hierarchy_test.dart
diff --git a/pkg/kernel/test/class_hierarchy_test.dart b/pkg/kernel/test/class_hierarchy_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e9b0fdc768beb9be197e29f18f9cb68d8de8ffe7
--- /dev/null
+++ b/pkg/kernel/test/class_hierarchy_test.dart
@@ -0,0 +1,657 @@
+// Copyright (c) 2017, 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:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/testing/mock_sdk_program.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ClosedWorldClassHierarchyTest);
+ });
+}
+
+@reflectiveTest
+class ClosedWorldClassHierarchyTest extends _ClassHierarchyTest {
+ ClassHierarchy createClassHierarchy(Program program) {
+ return new ClosedWorldClassHierarchy(program);
+ }
+}
+
+abstract class _ClassHierarchyTest {
+ Program program;
+ CoreTypes coreTypes;
+
+ /// The test library.
+ Library library;
+
+ ClassHierarchy _hierarchy;
+
+ /// Return the new or existing instance of [ClassHierarchy].
+ ClassHierarchy get hierarchy {
+ return _hierarchy ??= createClassHierarchy(program);
+ }
+
+ Class get objectClass => coreTypes.objectClass;
+
+ Supertype get objectSuper => coreTypes.objectClass.asThisSupertype;
+
+ Class addClass(Class c) {
+ if (_hierarchy != null) {
+ fail('The classs hierarchy has already been created.');
+ }
+ library.addClass(c);
+ return c;
+ }
+
+ /// Add a new generic class with the given [name] and [typeParameterNames].
+ /// The [TypeParameterType]s corresponding to [typeParameterNames] are
+ /// passed to optional [extends_] and [implements_] callbacks.
+ Class addGenericClass(String name, List<String> typeParameterNames,
+ {Supertype extends_(List<DartType> typeParameterTypes),
+ List<Supertype> implements_(List<DartType> typeParameterTypes)}) {
+ var typeParameters = typeParameterNames
+ .map((name) => new TypeParameter(name, objectClass.rawType))
+ .toList();
+ var typeParameterTypes = typeParameters
+ .map((parameter) => new TypeParameterType(parameter))
+ .toList();
+ var supertype =
+ extends_ != null ? extends_(typeParameterTypes) : objectSuper;
+ var implementedTypes =
+ implements_ != null ? implements_(typeParameterTypes) : [];
+ return addClass(new Class(
+ name: name,
+ typeParameters: typeParameters,
+ supertype: supertype,
+ implementedTypes: implementedTypes));
+ }
+
+ /// Add a new class with the given [name] that extends `Object` and
+ /// [implements_] the given classes.
+ Class addImplementsClass(String name, List<Class> implements_) {
+ return addClass(new Class(
+ name: name,
+ supertype: objectSuper,
+ implementedTypes: implements_.map((c) => c.asThisSupertype).toList()));
+ }
+
+ ClassHierarchy createClassHierarchy(Program program);
+
+ Procedure newEmptyMethod(String name, {bool abstract: false}) {
+ var body = abstract ? null : new Block([]);
+ return new Procedure(
+ new Name(name), ProcedureKind.Method, new FunctionNode(body));
+ }
+
+ Procedure newEmptySetter(String name) {
+ return new Procedure(
+ new Name(name),
+ ProcedureKind.Setter,
+ new FunctionNode(new Block([]),
+ positionalParameters: [new VariableDeclaration('_')]));
+ }
+
+ void setUp() {
+ // Start with mock SDK libraries.
+ program = createMockSdkProgram();
+ coreTypes = new CoreTypes(program);
+
+ // Add the test library.
+ library = new Library(Uri.parse('org-dartlang:///test.dart'), name: 'test');
+ library.parent = program;
+ program.libraries.add(library);
+ }
+
+ void test_forEachOverridePair_overrideSupertype() {
+ // Create the class hierarchy:
+ //
+ // abstract class A extends Object {
+ // foo() {}
+ // bar() {}
+ // }
+ // class B extends A {
+ // foo() {}
+ // }
+ // class C extends B {
+ // bar() {}
+ // }
+ var aFoo = newEmptyMethod('foo');
+ var aBar = newEmptyMethod('bar');
+ var bFoo = newEmptyMethod('foo');
+ var cBar = newEmptyMethod('bar');
+ var a = addClass(
+ new Class(name: 'A', supertype: objectSuper, procedures: [aFoo, aBar]));
+ var b = addClass(
+ new Class(name: 'B', supertype: a.asThisSupertype, procedures: [bFoo]));
+ var c = addClass(
+ new Class(name: 'C', supertype: b.asThisSupertype, procedures: [cBar]));
+
+ _assertOverridePairs(b, ['test::B::foo overrides test::A::foo']);
+ _assertOverridePairs(c, ['test::C::bar overrides test::A::bar']);
+ }
+
+ void test_getClassAsInstanceOf_generic_extends() {
+ // Create the class hierarchy:
+ //
+ // class A<T, U> extends Object {}
+ // class B<T> extends A<T, bool> {}
+ // class C extends B<int> {}
+ var int = coreTypes.intClass.rawType;
+ var bool = coreTypes.boolClass.rawType;
+
+ var a = addGenericClass('A', ['T', 'U']);
+
+ var bT = new TypeParameter('T', objectClass.rawType);
+ var bTT = new TypeParameterType(bT);
+ var b = addClass(new Class(
+ name: 'B',
+ typeParameters: [bT],
+ supertype: new Supertype(a, [bTT, bool])));
+
+ var c = addClass(new Class(name: 'C', supertype: new Supertype(b, [int])));
+
+ expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper);
+ expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype);
+ expect(hierarchy.getClassAsInstanceOf(b, a), new Supertype(a, [bTT, bool]));
+ expect(hierarchy.getClassAsInstanceOf(c, b), new Supertype(b, [int]));
+ expect(hierarchy.getClassAsInstanceOf(c, a), new Supertype(a, [int, bool]));
+ }
+
+ void test_getClassAsInstanceOf_generic_implements() {
+ // Create the class hierarchy:
+ //
+ // class A<T, U> extends Object {}
+ // class B<T> extends Object implements A<T, bool> {}
+ // class C extends Object implements B<int> {}
+ var int = coreTypes.intClass.rawType;
+ var bool = coreTypes.boolClass.rawType;
+
+ var a = addGenericClass('A', ['T', 'U']);
+
+ var bT = new TypeParameter('T', objectClass.rawType);
+ var bTT = new TypeParameterType(bT);
+ var b = addClass(new Class(
+ name: 'B',
+ typeParameters: [bT],
+ supertype: objectSuper,
+ implementedTypes: [
+ new Supertype(a, [bTT, bool])
+ ]));
+
+ var c = addClass(
+ new Class(name: 'C', supertype: objectSuper, implementedTypes: [
+ new Supertype(b, [int])
+ ]));
+
+ expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper);
+ expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype);
+ expect(hierarchy.getClassAsInstanceOf(b, a), new Supertype(a, [bTT, bool]));
+ expect(hierarchy.getClassAsInstanceOf(c, b), new Supertype(b, [int]));
+ expect(hierarchy.getClassAsInstanceOf(c, a), new Supertype(a, [int, bool]));
+ }
+
+ void test_getClassAsInstanceOf_generic_with() {
+ // Create the class hierarchy:
+ //
+ // class A<T, U> extends Object {}
+ // class B<T> extends Object with A<T, bool> {}
+ // class C extends Object with B<int> {}
+ var int = coreTypes.intClass.rawType;
+ var bool = coreTypes.boolClass.rawType;
+
+ var a = addGenericClass('A', ['T', 'U']);
+
+ var bT = new TypeParameter('T', objectClass.rawType);
+ var bTT = new TypeParameterType(bT);
+ var b = addClass(new Class(
+ name: 'B',
+ typeParameters: [bT],
+ supertype: objectSuper,
+ mixedInType: new Supertype(a, [bTT, bool])));
+
+ var c = addClass(new Class(
+ name: 'C',
+ supertype: objectSuper,
+ mixedInType: new Supertype(b, [int])));
+
+ expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper);
+ expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype);
+ expect(hierarchy.getClassAsInstanceOf(b, a), new Supertype(a, [bTT, bool]));
+ expect(hierarchy.getClassAsInstanceOf(c, b), new Supertype(b, [int]));
+ expect(hierarchy.getClassAsInstanceOf(c, a), new Supertype(a, [int, bool]));
+ }
+
+ void test_getClassAsInstanceOf_notGeneric_extends() {
+ // Create the class hierarchy:
+ //
+ // class A extends Object {}
+ // class B extends A {}
+ // class C extends B {}
+ // class Z extends Object {}
+ var a = addClass(new Class(name: 'A', supertype: objectSuper));
+ var b = addClass(new Class(name: 'B', supertype: a.asThisSupertype));
+ var c = addClass(new Class(name: 'C', supertype: b.asThisSupertype));
+ var z = addClass(new Class(name: 'Z', supertype: objectSuper));
+
+ expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper);
+ expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype);
+ expect(hierarchy.getClassAsInstanceOf(b, a), a.asThisSupertype);
+ expect(hierarchy.getClassAsInstanceOf(c, a), a.asThisSupertype);
+ expect(hierarchy.getClassAsInstanceOf(c, b), b.asThisSupertype);
+ expect(hierarchy.getClassAsInstanceOf(z, a), null);
+ expect(hierarchy.getClassAsInstanceOf(z, objectClass), objectSuper);
+ }
+
+ void test_getClassAsInstanceOf_notGeneric_implements() {
+ // Create the class hierarchy:
+ //
+ // class A extends Object {}
+ // class B extends Object {}
+ // class C extends Object implements A {}
+ // class D extends Object implements C {}
+ // class E extends A implements B {}
+ // class Z extends Object {}
+ var a = addClass(new Class(name: 'A', supertype: objectSuper));
+ var b = addClass(new Class(name: 'B', supertype: objectSuper));
+ var c = addClass(new Class(
+ name: 'C',
+ supertype: objectSuper,
+ implementedTypes: [a.asThisSupertype]));
+ var d = addClass(new Class(
+ name: 'D',
+ supertype: objectSuper,
+ implementedTypes: [c.asThisSupertype]));
+ var e = addClass(new Class(
+ name: 'D',
+ supertype: a.asThisSupertype,
+ implementedTypes: [b.asThisSupertype]));
+ var z = addClass(new Class(name: 'Z', supertype: objectSuper));
+
+ expect(hierarchy.getClassAsInstanceOf(c, a), a.asThisSupertype);
+ expect(hierarchy.getClassAsInstanceOf(d, a), a.asThisSupertype);
+ expect(hierarchy.getClassAsInstanceOf(d, c), c.asThisSupertype);
+ expect(hierarchy.getClassAsInstanceOf(e, a), a.asThisSupertype);
+ expect(hierarchy.getClassAsInstanceOf(e, b), b.asThisSupertype);
+ expect(hierarchy.getClassAsInstanceOf(z, a), null);
+ }
+
+ void test_getClassAsInstanceOf_notGeneric_with() {
+ // Create the class hierarchy:
+ //
+ // class A extends Object {}
+ // class B extends Object with A {}
+ // class Z extends Object {}
+ var a = addClass(new Class(name: 'A', supertype: objectSuper));
+ var b = addClass(new Class(
+ name: 'B', supertype: objectSuper, mixedInType: a.asThisSupertype));
+ var z = addClass(new Class(name: 'Z', supertype: objectSuper));
+
+ expect(hierarchy.getClassAsInstanceOf(b, objectClass), objectSuper);
+ expect(hierarchy.getClassAsInstanceOf(b, a), a.asThisSupertype);
+ expect(hierarchy.getClassAsInstanceOf(z, a), null);
+ }
+
+ void test_getClassDepth() {
+ var base = addClass(new Class(name: 'base', supertype: objectSuper));
+ var extends_ =
+ addClass(new Class(name: 'extends_', supertype: base.asThisSupertype));
+ var with_ = addClass(new Class(
+ name: 'with_',
+ supertype: objectSuper,
+ mixedInType: base.asThisSupertype));
+ var implements_ = addClass(new Class(
+ name: 'implements_',
+ supertype: objectSuper,
+ implementedTypes: [base.asThisSupertype]));
+
+ expect(hierarchy.getClassDepth(objectClass), 0);
+ expect(hierarchy.getClassDepth(base), 1);
+ expect(hierarchy.getClassDepth(extends_), 2);
+ expect(hierarchy.getClassDepth(with_), 2);
+ expect(hierarchy.getClassDepth(implements_), 2);
+ }
+
+ void test_getClassicLeastUpperBound_generic() {
+ var int = coreTypes.intClass.rawType;
+ var double = coreTypes.doubleClass.rawType;
+ var bool = coreTypes.boolClass.rawType;
+
+ // Create the class hierarchy:
+ //
+ // Object
+ // |
+ // A
+ // / \
+ // B<T> C<U>
+ // \ /
+ // D<T,U>
+ // / \
+ // E F
+ //
+ // Where E implements D<int, double> and F implements D<int, bool>.
+ var a = addGenericClass('A', []);
+ var b =
+ addGenericClass('B', ['T'], implements_: (_) => [a.asThisSupertype]);
+ var c =
+ addGenericClass('C', ['U'], implements_: (_) => [a.asThisSupertype]);
+ var d = addGenericClass('D', ['T', 'U'], implements_: (typeParameterTypes) {
+ var t = typeParameterTypes[0];
+ var u = typeParameterTypes[1];
+ return [
+ new Supertype(b, [t]),
+ new Supertype(c, [u])
+ ];
+ });
+ var e = addGenericClass('E', [],
+ implements_: (_) => [
+ new Supertype(d, [int, double])
+ ]);
+ var f = addGenericClass('F', [],
+ implements_: (_) => [
+ new Supertype(d, [int, bool])
+ ]);
+
+ expect(
+ hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]),
+ new InterfaceType(d, [int, double])),
+ new InterfaceType(d, [int, double]));
+ expect(
+ hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]),
+ new InterfaceType(d, [int, bool])),
+ new InterfaceType(b, [int]));
+ expect(
+ hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]),
+ new InterfaceType(d, [bool, double])),
+ new InterfaceType(c, [double]));
+ expect(
+ hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]),
+ new InterfaceType(d, [bool, int])),
+ a.rawType);
+ expect(hierarchy.getClassicLeastUpperBound(e.rawType, f.rawType),
+ new InterfaceType(b, [int]));
+ }
+
+ void test_getClassicLeastUpperBound_nonGeneric() {
+ // Create the class hierarchy:
+ //
+ // Object
+ // / \
+ // A B
+ // /|\
+ // C D E
+ // |X|/
+ // FG HI
+ //
+ // (F and G both implement (C, D); H and I both implement (C, D, E).
+ var a = addImplementsClass('A', []);
+ var b = addImplementsClass('B', []);
+ var c = addImplementsClass('C', [a]);
+ var d = addImplementsClass('D', [a]);
+ var e = addImplementsClass('E', [a]);
+ var f = addImplementsClass('F', [c, d]);
+ var g = addImplementsClass('G', [c, d]);
+ var h = addImplementsClass('H', [c, d, e]);
+ var i = addImplementsClass('I', [c, d, e]);
+ var hierarchy = new ClassHierarchy(program);
+
+ expect(hierarchy.getClassicLeastUpperBound(a.rawType, b.rawType),
+ objectClass.rawType);
+ expect(hierarchy.getClassicLeastUpperBound(a.rawType, objectClass.rawType),
+ objectClass.rawType);
+ expect(hierarchy.getClassicLeastUpperBound(objectClass.rawType, b.rawType),
+ objectClass.rawType);
+ expect(
+ hierarchy.getClassicLeastUpperBound(c.rawType, d.rawType), a.rawType);
+ expect(
+ hierarchy.getClassicLeastUpperBound(c.rawType, a.rawType), a.rawType);
+ expect(
+ hierarchy.getClassicLeastUpperBound(a.rawType, d.rawType), a.rawType);
+ expect(
+ hierarchy.getClassicLeastUpperBound(f.rawType, g.rawType), a.rawType);
+ expect(
+ hierarchy.getClassicLeastUpperBound(h.rawType, i.rawType), a.rawType);
+ }
+
+ void test_getDispatchTarget() {
+ // Create the class hierarchy:
+ //
+ // class A extends Object {
+ // aMethod() {}
+ // void set aSetter(_) {}
+ // }
+ // class B extends A {
+ // bMethod() {}
+ // void set bSetter(_) {}
+ // }
+ // class C extends B {}
+ var aMethod = newEmptyMethod('aMethod');
+ var aSetter = newEmptySetter('aSetter');
+ var bMethod = newEmptyMethod('bMethod');
+ var bSetter = newEmptySetter('bSetter');
+ var a = addClass(new Class(
+ name: 'A', supertype: objectSuper, procedures: [aMethod, aSetter]));
+ var b = addClass(new Class(
+ name: 'B',
+ supertype: a.asThisSupertype,
+ procedures: [bMethod, bSetter]));
+ var c = addClass(new Class(name: 'C', supertype: b.asThisSupertype));
+
+ var aMethodName = new Name('aMethod');
+ var aSetterName = new Name('aSetter');
+ var bMethodName = new Name('bMethod');
+ var bSetterName = new Name('bSetter');
+ expect(hierarchy.getDispatchTarget(a, aMethodName), aMethod);
+ expect(hierarchy.getDispatchTarget(a, bMethodName), isNull);
+ expect(hierarchy.getDispatchTarget(a, aSetterName, setter: true), aSetter);
+ expect(hierarchy.getDispatchTarget(a, bSetterName, setter: true), isNull);
+ expect(hierarchy.getDispatchTarget(b, aMethodName), aMethod);
+ expect(hierarchy.getDispatchTarget(b, bMethodName), bMethod);
+ expect(hierarchy.getDispatchTarget(b, aSetterName, setter: true), aSetter);
+ expect(hierarchy.getDispatchTarget(b, bSetterName, setter: true), bSetter);
+ expect(hierarchy.getDispatchTarget(c, aMethodName), aMethod);
+ expect(hierarchy.getDispatchTarget(c, bMethodName), bMethod);
+ expect(hierarchy.getDispatchTarget(c, aSetterName, setter: true), aSetter);
+ expect(hierarchy.getDispatchTarget(c, bSetterName, setter: true), bSetter);
+ }
+
+ void test_getDispatchTarget_abstract() {
+ // Create the class hierarchy:
+ //
+ // abstract class A extends Object {
+ // aMethodAbstract();
+ // aMethodConcrete() {}
+ // }
+ // abstract class B extends A {
+ // aMethodConcrete();
+ // bMethodAbstract();
+ // bMethodConcrete() {}
+ // }
+ // class C extends B {}
+ var aMethodConcrete = newEmptyMethod('aMethodConcrete');
+ var bMethodConcrete = newEmptyMethod('aMethodConcrete');
+ var a = addClass(new Class(name: 'A', supertype: objectSuper, procedures: [
+ newEmptyMethod('aMethodAbstract', abstract: true),
+ aMethodConcrete
+ ]));
+ var b = addClass(
+ new Class(name: 'B', supertype: a.asThisSupertype, procedures: [
+ newEmptyMethod('aMethodConcrete', abstract: true),
+ newEmptyMethod('bMethodAbstract', abstract: true),
+ bMethodConcrete
+ ]));
+ addClass(new Class(name: 'C', supertype: b.asThisSupertype));
+
+ expect(hierarchy.getDispatchTarget(a, new Name('aMethodConcrete')),
+ aMethodConcrete);
+ // TODO(scheglov): The next two commented statements verify the behavior
+ // documented as "If the class is abstract, abstract members are ignored and
+ // the dispatch is resolved if the class was not abstract.". Unfortunately
+ // the implementation does not follow the documentation. We need to fix
+ // either documentation, or implementation.
+// expect(hierarchy.getDispatchTarget(c, new Name('aMethodConcrete')),
+// aMethodConcrete);
+// expect(hierarchy.getDispatchTarget(b, new Name('aMethodConcrete')),
+// aMethodConcrete);
+ }
+
+ void test_getInterfaceMember_extends() {
+ // Create the class hierarchy:
+ //
+ // class A extends Object {
+ // aMethod() {}
+ // void set aSetter(_) {}
+ // }
+ // class B extends A {
+ // bMethod() {}
+ // void set bSetter(_) {}
+ // }
+ // class C extends B {}
+ var aMethod = newEmptyMethod('aMethod');
+ var aSetter = newEmptySetter('aSetter');
+ var bMethod = newEmptyMethod('bMethod');
+ var bSetter = newEmptySetter('bSetter');
+ var a = addClass(new Class(
+ name: 'A', supertype: objectSuper, procedures: [aMethod, aSetter]));
+ var b = addClass(new Class(
+ name: 'B',
+ supertype: a.asThisSupertype,
+ procedures: [bMethod, bSetter]));
+ var c = addClass(new Class(name: 'C', supertype: b.asThisSupertype));
+
+ var aMethodName = new Name('aMethod');
+ var aSetterName = new Name('aSetter');
+ var bMethodName = new Name('bMethod');
+ var bSetterName = new Name('bSetter');
+ expect(hierarchy.getInterfaceMember(a, aMethodName), aMethod);
+ expect(hierarchy.getInterfaceMember(a, bMethodName), isNull);
+ expect(hierarchy.getInterfaceMember(a, aSetterName, setter: true), aSetter);
+ expect(hierarchy.getInterfaceMember(a, bSetterName, setter: true), isNull);
+ expect(hierarchy.getInterfaceMember(b, aMethodName), aMethod);
+ expect(hierarchy.getInterfaceMember(b, bMethodName), bMethod);
+ expect(hierarchy.getInterfaceMember(b, aSetterName, setter: true), aSetter);
+ expect(hierarchy.getInterfaceMember(b, bSetterName, setter: true), bSetter);
+ expect(hierarchy.getInterfaceMember(c, aMethodName), aMethod);
+ expect(hierarchy.getInterfaceMember(c, bMethodName), bMethod);
+ expect(hierarchy.getInterfaceMember(c, aSetterName, setter: true), aSetter);
+ expect(hierarchy.getInterfaceMember(c, bSetterName, setter: true), bSetter);
+ }
+
+ void test_getInterfaceMember_implements() {
+ // Create the class hierarchy:
+ //
+ // class A extends Object {
+ // aMethod() {}
+ // void set aSetter(_) {}
+ // }
+ // class B extends Object implements A {
+ // bMethod() {}
+ // void set bSetter(_) {}
+ // }
+ // class C extends Object implements B {}
+ var aMethod = newEmptyMethod('aMethod');
+ var aSetter = newEmptySetter('aSetter');
+ var bMethod = newEmptyMethod('bMethod');
+ var bSetter = newEmptySetter('bSetter');
+ var a = addClass(new Class(
+ name: 'A', supertype: objectSuper, procedures: [aMethod, aSetter]));
+ var b = addClass(new Class(
+ name: 'B',
+ supertype: objectSuper,
+ implementedTypes: [a.asThisSupertype],
+ procedures: [bMethod, bSetter]));
+ var c = addClass(new Class(
+ name: 'C',
+ supertype: objectSuper,
+ implementedTypes: [b.asThisSupertype]));
+
+ var aMethodName = new Name('aMethod');
+ var aSetterName = new Name('aSetter');
+ var bMethodName = new Name('bMethod');
+ var bSetterName = new Name('bSetter');
+ expect(hierarchy.getInterfaceMember(a, aMethodName), aMethod);
+ expect(hierarchy.getInterfaceMember(a, bMethodName), isNull);
+ expect(hierarchy.getInterfaceMember(a, aSetterName, setter: true), aSetter);
+ expect(hierarchy.getInterfaceMember(a, bSetterName, setter: true), isNull);
+ expect(hierarchy.getInterfaceMember(b, aMethodName), aMethod);
+ expect(hierarchy.getInterfaceMember(b, bMethodName), bMethod);
+ expect(hierarchy.getInterfaceMember(b, aSetterName, setter: true), aSetter);
+ expect(hierarchy.getInterfaceMember(b, bSetterName, setter: true), bSetter);
+ expect(hierarchy.getInterfaceMember(c, aMethodName), aMethod);
+ expect(hierarchy.getInterfaceMember(c, bMethodName), bMethod);
+ expect(hierarchy.getInterfaceMember(c, aSetterName, setter: true), aSetter);
+ expect(hierarchy.getInterfaceMember(c, bSetterName, setter: true), bSetter);
+ }
+
+ void test_getRankedSuperclasses() {
+ // Create the class hierarchy:
+ //
+ // Object
+ // |
+ // A
+ // / \
+ // B C
+ // | |
+ // | D
+ // \ /
+ // E
+ var a = addImplementsClass('A', []);
+ var b = addImplementsClass('B', [a]);
+ var c = addImplementsClass('C', [a]);
+ var d = addImplementsClass('D', [c]);
+ var e = addImplementsClass('E', [b, d]);
+
+ expect(hierarchy.getRankedSuperclasses(a), [a, objectClass]);
+ expect(hierarchy.getRankedSuperclasses(b), [b, a, objectClass]);
+ expect(hierarchy.getRankedSuperclasses(c), [c, a, objectClass]);
+ expect(hierarchy.getRankedSuperclasses(d), [d, c, a, objectClass]);
+ if (hierarchy.getClassIndex(b) < hierarchy.getClassIndex(c)) {
+ expect(hierarchy.getRankedSuperclasses(e), [e, d, b, c, a, objectClass]);
+ } else {
+ expect(hierarchy.getRankedSuperclasses(e), [e, d, c, b, a, objectClass]);
+ }
+ }
+
+ void test_getTypeAsInstanceOf_generic_extends() {
+ // Create the class hierarchy:
+ //
+ // class A<T, U> extends Object {}
+ // class B<T> extends A<T, bool> {}
+ var int = coreTypes.intClass.rawType;
+ var bool = coreTypes.boolClass.rawType;
+
+ var a = addGenericClass('A', ['T', 'U']);
+
+ var bT = new TypeParameter('T', objectClass.rawType);
+ var bTT = new TypeParameterType(bT);
+ var b = addClass(new Class(
+ name: 'B',
+ typeParameters: [bT],
+ supertype: new Supertype(a, [bTT, bool])));
+
+ var b_int = new InterfaceType(b, [int]);
+ expect(hierarchy.getTypeAsInstanceOf(b_int, a),
+ new InterfaceType(a, [int, bool]));
+ expect(hierarchy.getTypeAsInstanceOf(b_int, objectClass),
+ new InterfaceType(objectClass));
+ }
+
+ void test_rootClass() {
+ addClass(new Class(name: 'A', supertype: objectSuper));
+ expect(hierarchy.rootClass, objectClass);
+ }
+
+ void _assertOverridePairs(Class class_, List<String> expected) {
+ List<String> overrideDescriptions = [];
+ hierarchy.forEachOverridePair(class_,
+ (Member declaredMember, Member interfaceMember, bool isSetter) {
+ var desc = '$declaredMember overrides $interfaceMember';
+ overrideDescriptions.add(desc);
+ });
+ expect(overrideDescriptions, unorderedEquals(expected));
+ }
+}
« no previous file with comments | « pkg/kernel/pubspec.yaml ('k') | pkg/kernel/test/lub_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698