blob: 49c37fbab342897fb0949d93b210bb6b1f27926a [file] [log] [blame]
// Copyright (c) 2018, 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.
// @dart = 2.7
import 'package:expect/expect.dart';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/common_elements.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/ir/static_type.dart';
import 'package:compiler/src/js_backend/native_data.dart';
import 'package:compiler/src/universe/resolution_world_builder.dart';
import 'package:compiler/src/universe/world_builder.dart';
import '../helpers/memory_compiler.dart';
main() {
asyncTest(() async {
await runTest();
});
}
runTest() async {
String classes = '''
@JS()
library lib;
import 'package:js/js.dart';
class A {}
class A1 extends A {}
class A2 extends A1 {}
class B implements A {}
class B1 extends B {}
class C {}
class C0 {}
class C1 = C with A;
class C2 extends C1 {}
class C3 = C with C0, A;
class C4 = C with A, C0;
@JS()
class D {}
@JS()
class D1 extends D {}
''';
CommonElements commonElements;
NativeBasicData nativeBasicData;
ResolutionWorldBuilderImpl world;
List<ClassEntity> allClasses;
ClassEntity A;
ClassEntity A1;
ClassEntity A2;
ClassEntity B;
ClassEntity B1;
ClassEntity C;
ClassEntity C0;
ClassEntity C1;
ClassEntity C2;
ClassEntity C3;
ClassEntity C4;
ClassEntity D;
ClassEntity D1;
List<ClassRelation> allRelations = ClassRelation.values;
List<ClassRelation> notExact = [
ClassRelation.thisExpression,
ClassRelation.subtype
];
List<ClassRelation> subtype = [ClassRelation.subtype];
run(List<String> liveClasses) async {
String source = '''
$classes
main() {
${liveClasses.map((c) => ' new $c();').join('\n')}
}
''';
print('------------------------------------------------------------------');
print(source);
CompilationResult result =
await runCompiler(memorySourceFiles: {'main.dart': source});
Expect.isTrue(result.isSuccess);
Compiler compiler = result.compiler;
commonElements = compiler.frontendStrategy.commonElements;
ElementEnvironment elementEnvironment =
compiler.frontendStrategy.elementEnvironment;
nativeBasicData = compiler.frontendStrategy.nativeBasicData;
world = compiler.resolutionWorldBuilderForTesting;
ClassEntity findClass(String name) {
ClassEntity cls =
elementEnvironment.lookupClass(elementEnvironment.mainLibrary, name);
Expect.isNotNull(cls, 'Class $name not found.');
return cls;
}
allClasses = [
A = findClass('A'),
A1 = findClass('A1'),
A2 = findClass('A2'),
B = findClass('B'),
B1 = findClass('B1'),
C = findClass('C'),
C0 = findClass('C0'),
C1 = findClass('C1'),
C2 = findClass('C2'),
C3 = findClass('C3'),
C4 = findClass('C4'),
D = findClass('D'),
D1 = findClass('D1'),
];
}
void check(
Map<ClassEntity, Map<ClassEntity, List<ClassRelation>>> expectedResults) {
for (ClassEntity cls in allClasses) {
for (ClassEntity memberHoldingClass in allClasses) {
Map<ClassEntity, List<ClassRelation>> memberResults =
expectedResults[memberHoldingClass] ?? {};
for (ClassRelation relation in allRelations) {
List<ClassRelation> expectRelations = memberResults[cls];
bool expectedResult =
expectRelations != null && expectRelations.contains(relation);
StrongModeConstraint constraint = new StrongModeConstraint(
commonElements, nativeBasicData, cls, relation);
Expect.equals(
expectedResult,
world.isInheritedInClass(
memberHoldingClass, constraint.cls, constraint.relation),
"Unexpected results for member of $memberHoldingClass on a "
"receiver $constraint (cls=$cls, relation=$relation)");
}
}
}
}
await run([]);
check({});
await run(['A']);
check({
A: {A: allRelations},
});
await run(['A1']);
check({
A: {
A: notExact,
A1: allRelations,
},
A1: {
A: notExact,
A1: allRelations,
},
});
await run(['A', 'A1']);
check({
A: {
A: allRelations,
A1: allRelations,
},
A1: {
A: notExact,
A1: allRelations,
},
});
await run(['A2']);
check({
A: {
A: notExact,
A1: notExact,
A2: allRelations,
},
A1: {
A: notExact,
A1: notExact,
A2: allRelations,
},
A2: {
A: notExact,
A1: notExact,
A2: allRelations,
},
});
await run(['A', 'A2']);
check({
A: {
A: allRelations,
A1: notExact,
A2: allRelations,
},
A1: {
A: notExact,
A1: notExact,
A2: allRelations,
},
A2: {
A: notExact,
A1: notExact,
A2: allRelations,
},
});
await run(['A1', 'A2']);
check({
A: {
A: notExact,
A1: allRelations,
A2: allRelations,
},
A1: {
A: notExact,
A1: allRelations,
A2: allRelations,
},
A2: {
A: notExact,
A1: notExact,
A2: allRelations,
},
});
await run(['B']);
check({
B: {
A: subtype,
B: allRelations,
},
});
await run(['B1']);
check({
B: {
A: subtype,
B: notExact,
B1: allRelations,
},
B1: {
A: subtype,
B: notExact,
B1: allRelations,
},
});
await run(['A', 'A2', 'B']);
check({
A: {
A: allRelations,
A1: notExact,
A2: allRelations,
},
A1: {
A: notExact,
A1: notExact,
A2: allRelations,
},
A2: {
A: notExact,
A1: notExact,
A2: allRelations,
},
B: {A: subtype, B: allRelations},
});
await run(['C']);
check({
C: {
C: allRelations,
},
});
await run(['C1']);
check({
A: {
A: notExact,
C: notExact,
C1: allRelations,
},
C: {
A: notExact,
C: notExact,
C1: allRelations,
},
C1: {
A: notExact,
C: notExact,
C1: allRelations,
},
});
await run(['C2']);
check({
A: {
A: notExact,
C: notExact,
C1: notExact,
C2: allRelations,
},
C: {
A: notExact,
C: notExact,
C1: notExact,
C2: allRelations,
},
C1: {
A: notExact,
C: notExact,
C1: notExact,
C2: allRelations,
},
C2: {
A: notExact,
C: notExact,
C1: notExact,
C2: allRelations,
},
});
await run(['C3']);
check({
A: {
A: notExact,
C: notExact,
C0: notExact,
C3: allRelations,
},
C: {
A: notExact,
C: notExact,
C0: notExact,
C3: allRelations,
},
C0: {
A: notExact,
C: notExact,
C0: notExact,
C3: allRelations,
},
C3: {
A: notExact,
C: notExact,
C0: notExact,
C3: allRelations,
},
});
await run(['C4']);
check({
A: {
A: notExact,
C: notExact,
C0: notExact,
C4: allRelations,
},
C: {
A: notExact,
C: notExact,
C0: notExact,
C4: allRelations,
},
C0: {
A: notExact,
C: notExact,
C0: notExact,
C4: allRelations,
},
C4: {
A: notExact,
C: notExact,
C0: notExact,
C4: allRelations,
},
});
await run(['A2', 'C1']);
check({
A: {
A: notExact,
A1: notExact,
A2: allRelations,
C: notExact,
C1: allRelations,
},
A1: {
A: notExact,
A1: notExact,
A2: allRelations,
},
A2: {
A: notExact,
A1: notExact,
A2: allRelations,
},
C: {
A: notExact,
C: notExact,
C1: allRelations,
},
C1: {
A: notExact,
C: notExact,
C1: allRelations,
},
});
await run(['D']);
check({
D: {
D: allRelations,
D1: allRelations,
},
});
await run(['D1']);
check({
D: {
D: allRelations,
D1: allRelations,
},
D1: {
D: allRelations,
D1: allRelations,
},
});
}