blob: 25a310aae95bb4b18f95dd3a2e06945cb3367456 [file] [log] [blame]
// 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';
main() {
Library makeTestLibrary(Program program) {
var library = new Library(Uri.parse('org-dartlang:///test.dart'))
..parent = program;
program.libraries.add(library);
return library;
}
test('depth', () {
var program = createMockSdkProgram();
var coreTypes = new CoreTypes(program);
var defaultSuper = coreTypes.objectClass.asThisSupertype;
var library = makeTestLibrary(program);
Class addClass(Class c) {
library.addClass(c);
return c;
}
var base = addClass(new Class(name: 'base', supertype: defaultSuper));
var extends_ =
addClass(new Class(name: 'extends_', supertype: base.asThisSupertype));
var with_ = addClass(new Class(
name: 'with_',
supertype: defaultSuper,
mixedInType: base.asThisSupertype));
var implements_ = addClass(new Class(
name: 'implements_',
supertype: defaultSuper,
implementedTypes: [base.asThisSupertype]));
var hierarchy = new ClassHierarchy(program);
expect(hierarchy.getClassDepth(coreTypes.objectClass), 0);
expect(hierarchy.getClassDepth(base), 1);
expect(hierarchy.getClassDepth(extends_), 2);
expect(hierarchy.getClassDepth(with_), 2);
expect(hierarchy.getClassDepth(implements_), 2);
});
test('ranked_superclasses', () {
var program = createMockSdkProgram();
var coreTypes = new CoreTypes(program);
var defaultSuper = coreTypes.objectClass.asThisSupertype;
var library = makeTestLibrary(program);
Class addClass(String name, List<Class> implements_) {
var c = new Class(
name: name,
supertype: defaultSuper,
implementedTypes: implements_.map((c) => c.asThisSupertype).toList());
library.addClass(c);
return c;
}
// Create the class hierarchy:
//
// Object
// |
// A
// / \
// B C
// | |
// | D
// \ /
// E
var a = addClass('A', []);
var b = addClass('B', [a]);
var c = addClass('C', [a]);
var d = addClass('D', [c]);
var e = addClass('E', [b, d]);
var hierarchy = new ClassHierarchy(program);
expect(hierarchy.getRankedSuperclasses(a), [a, coreTypes.objectClass]);
expect(hierarchy.getRankedSuperclasses(b), [b, a, coreTypes.objectClass]);
expect(hierarchy.getRankedSuperclasses(c), [c, a, coreTypes.objectClass]);
expect(
hierarchy.getRankedSuperclasses(d), [d, c, a, coreTypes.objectClass]);
if (hierarchy.getClassIndex(b) < hierarchy.getClassIndex(c)) {
expect(hierarchy.getRankedSuperclasses(e),
[e, d, b, c, a, coreTypes.objectClass]);
} else {
expect(hierarchy.getRankedSuperclasses(e),
[e, d, c, b, a, coreTypes.objectClass]);
}
});
test('least_upper_bound_non_generic', () {
var program = createMockSdkProgram();
var coreTypes = new CoreTypes(program);
var defaultSuper = coreTypes.objectClass.asThisSupertype;
var library = makeTestLibrary(program);
Class addClass(String name, List<Class> implements_) {
var c = new Class(
name: name,
supertype: defaultSuper,
implementedTypes: implements_.map((c) => c.asThisSupertype).toList());
library.addClass(c);
return c;
}
// 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 = addClass('A', []);
var b = addClass('B', []);
var c = addClass('C', [a]);
var d = addClass('D', [a]);
var e = addClass('E', [a]);
var f = addClass('F', [c, d]);
var g = addClass('G', [c, d]);
var h = addClass('H', [c, d, e]);
var i = addClass('I', [c, d, e]);
var hierarchy = new ClassHierarchy(program);
expect(hierarchy.getClassicLeastUpperBound(a.rawType, b.rawType),
coreTypes.objectClass.rawType);
expect(
hierarchy.getClassicLeastUpperBound(
a.rawType, coreTypes.objectClass.rawType),
coreTypes.objectClass.rawType);
expect(
hierarchy.getClassicLeastUpperBound(
coreTypes.objectClass.rawType, b.rawType),
coreTypes.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);
});
test('least_upper_bound_non_generic', () {
var program = createMockSdkProgram();
var coreTypes = new CoreTypes(program);
var defaultSuper = coreTypes.objectClass.asThisSupertype;
var library = makeTestLibrary(program);
var int = coreTypes.intClass.rawType;
var double = coreTypes.doubleClass.rawType;
var bool = coreTypes.boolClass.rawType;
Class addClass(String name, List<String> typeParameterNames,
List<Supertype> implements_(List<DartType> typeParameterTypes)) {
var typeParameters = typeParameterNames
.map((name) => new TypeParameter(name, coreTypes.objectClass.rawType))
.toList();
var typeParameterTypes = typeParameters
.map((parameter) => new TypeParameterType(parameter))
.toList();
var c = new Class(
name: name,
typeParameters: typeParameters,
supertype: defaultSuper,
implementedTypes: implements_(typeParameterTypes));
library.addClass(c);
return c;
}
// 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 = addClass('A', [], (_) => []);
var b = addClass('B', ['T'], (_) => [a.asThisSupertype]);
var c = addClass('C', ['U'], (_) => [a.asThisSupertype]);
var d = addClass('D', ['T', 'U'], (typeParameterTypes) {
var t = typeParameterTypes[0];
var u = typeParameterTypes[1];
return [
new Supertype(b, [t]),
new Supertype(c, [u])
];
});
var e = addClass(
'E',
[],
(_) => [
new Supertype(d, [int, double])
]);
var f = addClass(
'F',
[],
(_) => [
new Supertype(d, [int, bool])
]);
var hierarchy = new ClassHierarchy(program);
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]));
});
}