Simplify class_hierarchy_test: Move tests of getLegacyLeastUpperBound to own file
Change-Id: Iff64676644f17c32dea2b01e0c25e92af1f63774
Reviewed-on: https://dart-review.googlesource.com/c/93024
Commit-Queue: Peter von der Ahé <ahe@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/test/fasta/types/legacy_upper_bound_test.dart b/pkg/front_end/test/fasta/types/legacy_upper_bound_test.dart
new file mode 100644
index 0000000..24b04d2
--- /dev/null
+++ b/pkg/front_end/test/fasta/types/legacy_upper_bound_test.dart
@@ -0,0 +1,292 @@
+// 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:expect/matchers_lite.dart";
+
+import "package:kernel/ast.dart";
+import "package:kernel/class_hierarchy.dart";
+import "package:kernel/core_types.dart";
+import "package:kernel/testing/mock_sdk_component.dart";
+import "package:kernel/text/ast_to_text.dart";
+import "package:kernel/type_algebra.dart";
+
+main() {
+ new LegacyUpperBoundTest().test_getLegacyLeastUpperBound_expansive();
+
+ new LegacyUpperBoundTest().test_getLegacyLeastUpperBound_generic();
+
+ new LegacyUpperBoundTest().test_getLegacyLeastUpperBound_nonGeneric();
+}
+
+class LegacyUpperBoundTest {
+ final Component component = createMockSdkComponent();
+
+ CoreTypes coreTypes;
+
+ final Library library =
+ new Library(Uri.parse('org-dartlang:///test.dart'), name: 'test');
+
+ ClassHierarchy _hierarchy;
+
+ LegacyUpperBoundTest() {
+ coreTypes = new CoreTypes(component);
+ library.parent = component;
+ component.libraries.add(library);
+ }
+
+ Class get objectClass => coreTypes.objectClass;
+
+ Supertype get objectSuper => coreTypes.objectClass.asThisSupertype;
+
+ ClassHierarchy get hierarchy {
+ return _hierarchy ??= createClassHierarchy(component);
+ }
+
+ Class addClass(Class c) {
+ if (_hierarchy != null) {
+ fail('The classs hierarchy has already been created.');
+ }
+ library.addClass(c);
+ return c;
+ }
+
+ /// Assert that the test [library] has the [expectedText] presentation.
+ /// The presentation is close, but not identical to the normal Kernel one.
+ void _assertTestLibraryText(String expectedText) {
+ _assertLibraryText(library, expectedText);
+ }
+
+ void _assertLibraryText(Library lib, String expectedText) {
+ StringBuffer sb = new StringBuffer();
+ Printer printer = new Printer(sb);
+ printer.writeLibraryFile(lib);
+
+ String actualText = sb.toString();
+
+ // Clean up the text a bit.
+ const oftenUsedPrefix = '''
+library test;
+import self as self;
+import "dart:core" as core;
+
+''';
+ if (actualText.startsWith(oftenUsedPrefix)) {
+ actualText = actualText.substring(oftenUsedPrefix.length);
+ }
+ actualText = actualText.replaceAll('{\n}', '{}');
+ actualText = actualText.replaceAll(' extends core::Object', '');
+
+ if (actualText != expectedText) {
+ print('-------- Actual --------');
+ print(actualText + '------------------------');
+ }
+
+ expect(actualText, expectedText);
+ }
+
+ ClassHierarchy createClassHierarchy(Component component) {
+ return new ClassHierarchy(component);
+ }
+
+ /// 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) : <Supertype>[];
+ 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()));
+ }
+
+ /// Copy of the tests/language/least_upper_bound_expansive_test.dart test.
+ void test_getLegacyLeastUpperBound_expansive() {
+ var int = coreTypes.intClass.rawType;
+ var string = coreTypes.stringClass.rawType;
+
+ // class N<T> {}
+ var NT = new TypeParameter('T', objectClass.rawType);
+ var N = addClass(
+ new Class(name: 'N', typeParameters: [NT], supertype: objectSuper));
+
+ // class C1<T> extends N<N<C1<T>>> {}
+ Class C1;
+ {
+ var T = new TypeParameter('T', objectClass.rawType);
+ C1 = addClass(
+ new Class(name: 'C1', typeParameters: [T], supertype: objectSuper));
+ DartType C1_T = Substitution.fromMap({T: new TypeParameterType(T)})
+ .substituteType(C1.thisType);
+ DartType N_C1_T =
+ Substitution.fromMap({NT: C1_T}).substituteType(N.thisType);
+ Supertype N_N_C1_T = Substitution.fromMap({NT: N_C1_T})
+ .substituteSupertype(N.asThisSupertype);
+ C1.supertype = N_N_C1_T;
+ }
+
+ // class C2<T> extends N<N<C2<N<C2<T>>>>> {}
+ Class C2;
+ {
+ var T = new TypeParameter('T', objectClass.rawType);
+ C2 = addClass(
+ new Class(name: 'C2', typeParameters: [T], supertype: objectSuper));
+ DartType C2_T = Substitution.fromMap({T: new TypeParameterType(T)})
+ .substituteType(C2.thisType);
+ DartType N_C2_T =
+ Substitution.fromMap({NT: C2_T}).substituteType(N.thisType);
+ DartType C2_N_C2_T =
+ Substitution.fromMap({T: N_C2_T}).substituteType(C2.thisType);
+ DartType N_C2_N_C2_T =
+ Substitution.fromMap({NT: C2_N_C2_T}).substituteType(N.thisType);
+ Supertype N_N_C2_N_C2_T = Substitution.fromMap({NT: N_C2_N_C2_T})
+ .substituteSupertype(N.asThisSupertype);
+ C2.supertype = N_N_C2_N_C2_T;
+ }
+
+ _assertTestLibraryText('''
+class N<T> {}
+class C1<T> extends self::N<self::N<self::C1<self::C1::T>>> {}
+class C2<T> extends self::N<self::N<self::C2<self::N<self::C2<self::C2::T>>>>> {}
+''');
+
+ // The least upper bound of C1<int> and N<C1<String>> is Object since the
+ // supertypes are
+ // {C1<int>, N<N<C1<int>>>, Object} for C1<int> and
+ // {N<C1<String>>, Object} for N<C1<String>> and
+ // Object is the most specific type in the intersection of the supertypes.
+ expect(
+ hierarchy.getLegacyLeastUpperBound(
+ new InterfaceType(C1, [int]),
+ new InterfaceType(N, [
+ new InterfaceType(C1, [string])
+ ])),
+ objectClass.thisType);
+
+ // The least upper bound of C2<int> and N<C2<String>> is Object since the
+ // supertypes are
+ // {C2<int>, N<N<C2<N<C2<int>>>>>, Object} for C2<int> and
+ // {N<C2<String>>, Object} for N<C2<String>> and
+ // Object is the most specific type in the intersection of the supertypes.
+ expect(
+ hierarchy.getLegacyLeastUpperBound(
+ new InterfaceType(C2, [int]),
+ new InterfaceType(N, [
+ new InterfaceType(C2, [string])
+ ])),
+ objectClass.thisType);
+ }
+
+ void test_getLegacyLeastUpperBound_generic() {
+ var int = coreTypes.intClass.rawType;
+ var double = coreTypes.doubleClass.rawType;
+ var bool = coreTypes.boolClass.rawType;
+
+ 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])
+ ]);
+
+ _assertTestLibraryText('''
+class A {}
+class B<T> implements self::A {}
+class C<U> implements self::A {}
+class D<T, U> implements self::B<self::D::T>, self::C<self::D::U> {}
+class E implements self::D<core::int, core::double> {}
+class F implements self::D<core::int, core::bool> {}
+''');
+
+ expect(
+ hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
+ new InterfaceType(d, [int, double])),
+ new InterfaceType(d, [int, double]));
+ expect(
+ hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
+ new InterfaceType(d, [int, bool])),
+ new InterfaceType(b, [int]));
+ expect(
+ hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
+ new InterfaceType(d, [bool, double])),
+ new InterfaceType(c, [double]));
+ expect(
+ hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
+ new InterfaceType(d, [bool, int])),
+ a.rawType);
+ expect(hierarchy.getLegacyLeastUpperBound(e.rawType, f.rawType),
+ new InterfaceType(b, [int]));
+ }
+
+ void test_getLegacyLeastUpperBound_nonGeneric() {
+ 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]);
+
+ _assertTestLibraryText('''
+class A {}
+class B {}
+class C implements self::A {}
+class D implements self::A {}
+class E implements self::A {}
+class F implements self::C, self::D {}
+class G implements self::C, self::D {}
+class H implements self::C, self::D, self::E {}
+class I implements self::C, self::D, self::E {}
+''');
+
+ expect(hierarchy.getLegacyLeastUpperBound(a.rawType, b.rawType),
+ objectClass.rawType);
+ expect(hierarchy.getLegacyLeastUpperBound(a.rawType, objectClass.rawType),
+ objectClass.rawType);
+ expect(hierarchy.getLegacyLeastUpperBound(objectClass.rawType, b.rawType),
+ objectClass.rawType);
+ expect(hierarchy.getLegacyLeastUpperBound(c.rawType, d.rawType), a.rawType);
+ expect(hierarchy.getLegacyLeastUpperBound(c.rawType, a.rawType), a.rawType);
+ expect(hierarchy.getLegacyLeastUpperBound(a.rawType, d.rawType), a.rawType);
+ expect(hierarchy.getLegacyLeastUpperBound(f.rawType, g.rawType), a.rawType);
+ expect(hierarchy.getLegacyLeastUpperBound(h.rawType, i.rawType), a.rawType);
+ }
+}
diff --git a/pkg/kernel/test/class_hierarchy_test.dart b/pkg/kernel/test/class_hierarchy_test.dart
index c98017a..c195192 100644
--- a/pkg/kernel/test/class_hierarchy_test.dart
+++ b/pkg/kernel/test/class_hierarchy_test.dart
@@ -9,7 +9,6 @@
import "package:kernel/core_types.dart";
import "package:kernel/testing/mock_sdk_component.dart";
import "package:kernel/text/ast_to_text.dart";
-import "package:kernel/type_algebra.dart";
main() {
new ClosedWorldClassHierarchyTest().test_applyTreeChanges();
@@ -53,13 +52,6 @@
new ClosedWorldClassHierarchyTest()
.test_getClassAsInstanceOf_notGeneric_with();
- new ClosedWorldClassHierarchyTest().test_getLegacyLeastUpperBound_expansive();
-
- new ClosedWorldClassHierarchyTest().test_getLegacyLeastUpperBound_generic();
-
- new ClosedWorldClassHierarchyTest()
- .test_getLegacyLeastUpperBound_nonGeneric();
-
new ClosedWorldClassHierarchyTest().test_getDeclaredMembers();
new ClosedWorldClassHierarchyTest().test_getDispatchTarget();
@@ -330,15 +322,6 @@
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()));
- }
-
Procedure newEmptyGetter(String name,
{DartType returnType: const DynamicType(), bool isAbstract: false}) {
var body =
@@ -704,175 +687,6 @@
expect(hierarchy.getClassAsInstanceOf(z, a), null);
}
- /// Copy of the tests/language/least_upper_bound_expansive_test.dart test.
- void test_getLegacyLeastUpperBound_expansive() {
- var int = coreTypes.intClass.rawType;
- var string = coreTypes.stringClass.rawType;
-
- // class N<T> {}
- var NT = new TypeParameter('T', objectClass.rawType);
- var N = addClass(
- new Class(name: 'N', typeParameters: [NT], supertype: objectSuper));
-
- // class C1<T> extends N<N<C1<T>>> {}
- Class C1;
- {
- var T = new TypeParameter('T', objectClass.rawType);
- C1 = addClass(
- new Class(name: 'C1', typeParameters: [T], supertype: objectSuper));
- DartType C1_T = Substitution.fromMap({T: new TypeParameterType(T)})
- .substituteType(C1.thisType);
- DartType N_C1_T =
- Substitution.fromMap({NT: C1_T}).substituteType(N.thisType);
- Supertype N_N_C1_T = Substitution.fromMap({NT: N_C1_T})
- .substituteSupertype(N.asThisSupertype);
- C1.supertype = N_N_C1_T;
- }
-
- // class C2<T> extends N<N<C2<N<C2<T>>>>> {}
- Class C2;
- {
- var T = new TypeParameter('T', objectClass.rawType);
- C2 = addClass(
- new Class(name: 'C2', typeParameters: [T], supertype: objectSuper));
- DartType C2_T = Substitution.fromMap({T: new TypeParameterType(T)})
- .substituteType(C2.thisType);
- DartType N_C2_T =
- Substitution.fromMap({NT: C2_T}).substituteType(N.thisType);
- DartType C2_N_C2_T =
- Substitution.fromMap({T: N_C2_T}).substituteType(C2.thisType);
- DartType N_C2_N_C2_T =
- Substitution.fromMap({NT: C2_N_C2_T}).substituteType(N.thisType);
- Supertype N_N_C2_N_C2_T = Substitution.fromMap({NT: N_C2_N_C2_T})
- .substituteSupertype(N.asThisSupertype);
- C2.supertype = N_N_C2_N_C2_T;
- }
-
- _assertTestLibraryText('''
-class N<T> {}
-class C1<T> extends self::N<self::N<self::C1<self::C1::T>>> {}
-class C2<T> extends self::N<self::N<self::C2<self::N<self::C2<self::C2::T>>>>> {}
-''');
-
- // The least upper bound of C1<int> and N<C1<String>> is Object since the
- // supertypes are
- // {C1<int>, N<N<C1<int>>>, Object} for C1<int> and
- // {N<C1<String>>, Object} for N<C1<String>> and
- // Object is the most specific type in the intersection of the supertypes.
- expect(
- hierarchy.getLegacyLeastUpperBound(
- new InterfaceType(C1, [int]),
- new InterfaceType(N, [
- new InterfaceType(C1, [string])
- ])),
- objectClass.thisType);
-
- // The least upper bound of C2<int> and N<C2<String>> is Object since the
- // supertypes are
- // {C2<int>, N<N<C2<N<C2<int>>>>>, Object} for C2<int> and
- // {N<C2<String>>, Object} for N<C2<String>> and
- // Object is the most specific type in the intersection of the supertypes.
- expect(
- hierarchy.getLegacyLeastUpperBound(
- new InterfaceType(C2, [int]),
- new InterfaceType(N, [
- new InterfaceType(C2, [string])
- ])),
- objectClass.thisType);
- }
-
- void test_getLegacyLeastUpperBound_generic() {
- var int = coreTypes.intClass.rawType;
- var double = coreTypes.doubleClass.rawType;
- var bool = coreTypes.boolClass.rawType;
-
- 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])
- ]);
-
- _assertTestLibraryText('''
-class A {}
-class B<T> implements self::A {}
-class C<U> implements self::A {}
-class D<T, U> implements self::B<self::D::T>, self::C<self::D::U> {}
-class E implements self::D<core::int, core::double> {}
-class F implements self::D<core::int, core::bool> {}
-''');
-
- expect(
- hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
- new InterfaceType(d, [int, double])),
- new InterfaceType(d, [int, double]));
- expect(
- hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
- new InterfaceType(d, [int, bool])),
- new InterfaceType(b, [int]));
- expect(
- hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
- new InterfaceType(d, [bool, double])),
- new InterfaceType(c, [double]));
- expect(
- hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
- new InterfaceType(d, [bool, int])),
- a.rawType);
- expect(hierarchy.getLegacyLeastUpperBound(e.rawType, f.rawType),
- new InterfaceType(b, [int]));
- }
-
- void test_getLegacyLeastUpperBound_nonGeneric() {
- 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]);
-
- _assertTestLibraryText('''
-class A {}
-class B {}
-class C implements self::A {}
-class D implements self::A {}
-class E implements self::A {}
-class F implements self::C, self::D {}
-class G implements self::C, self::D {}
-class H implements self::C, self::D, self::E {}
-class I implements self::C, self::D, self::E {}
-''');
-
- expect(hierarchy.getLegacyLeastUpperBound(a.rawType, b.rawType),
- objectClass.rawType);
- expect(hierarchy.getLegacyLeastUpperBound(a.rawType, objectClass.rawType),
- objectClass.rawType);
- expect(hierarchy.getLegacyLeastUpperBound(objectClass.rawType, b.rawType),
- objectClass.rawType);
- expect(hierarchy.getLegacyLeastUpperBound(c.rawType, d.rawType), a.rawType);
- expect(hierarchy.getLegacyLeastUpperBound(c.rawType, a.rawType), a.rawType);
- expect(hierarchy.getLegacyLeastUpperBound(a.rawType, d.rawType), a.rawType);
- expect(hierarchy.getLegacyLeastUpperBound(f.rawType, g.rawType), a.rawType);
- expect(hierarchy.getLegacyLeastUpperBound(h.rawType, i.rawType), a.rawType);
- }
-
void test_getDeclaredMembers() {
var method = newEmptyMethod('method');
var getter = newEmptyGetter('getter');