blob: e993dc6dcc7bd23fe9465bfe99030ebe6c5740e4 [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:async_helper/async_helper.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/common_elements.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/js_backend/runtime_types_resolution.dart';
import 'package:compiler/src/js_emitter/model.dart';
import 'package:compiler/src/world.dart';
import 'package:expect/expect.dart';
import '../helpers/program_lookup.dart';
import '../helpers/memory_compiler.dart';
const String code = '''
class A {}
class B<T> {}
class C<T> implements B<T> {}
class D<T> implements B<int> {}
class E<T> extends B<T> {}
class F<T> extends B<List<T>>{}
class G {
call() {}
}
class H implements G {
call() {}
}
class I<T> {
call(T t) {}
}
main() {
new A();
new C();
new D();
new E();
new F();
new H();
new I();
method<int>();
}
method<T>() {
local1() {}
local2(T t) {}
local3<S>(S s) {}
local1();
local2(null);
local3(null);
}
''';
const Map<String, List<String>> expectedIsChecksMap =
const <String, List<String>>{
'A': const <String>[],
'B': const <String>[],
'C': const <String>[r'$isB'],
// TODO(sigmund): change these tests to check that the new rti medatada
// includes the information we need to check the equivalent of D.$asB and
// F.$asB
'D': const <String>[r'$isB'],
'E': const <String>[],
'F': const <String>[],
'G': const <String>[],
'H': const <String>[r'$isG'],
'I': const <String>[],
'method_local1': const <String>[r'$signature'],
'method_local2': const <String>[r'$signature'],
'method_local3': const <String>[r'$signature'],
};
main() {
runTest() async {
CompilationResult result = await runCompiler(
memorySourceFiles: {'main.dart': code},
options: [Flags.disableRtiOptimization, Flags.disableInlining]);
Expect.isTrue(result.isSuccess);
Compiler compiler = result.compiler;
JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
JElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
RuntimeTypesNeed rtiNeed = closedWorld.rtiNeed;
ProgramLookup programLookup = new ProgramLookup(compiler.backendStrategy);
List<ClassEntity> closures = <ClassEntity>[];
void processMember(MemberEntity element) {
if (element is FunctionEntity) {
Expect.isTrue(rtiNeed.methodNeedsTypeArguments(element),
"Expected $element to need type arguments.");
Expect.isTrue(rtiNeed.methodNeedsSignature(element),
"Expected $element to need signature.");
elementEnvironment.forEachNestedClosure(element,
(FunctionEntity local) {
closures.add(local.enclosingClass);
});
}
}
void processClass(ClassEntity element) {
Expect.equals(elementEnvironment.isGenericClass(element),
closedWorld.rtiNeed.classNeedsTypeArguments(element));
elementEnvironment.forEachConstructor(element, processMember);
elementEnvironment.forEachLocalClassMember(element, processMember);
List<String> expectedIsChecks = expectedIsChecksMap[element.name];
if (!expectedIsChecks.isEmpty) {
Class cls = programLookup.getClass(element);
List<String> isChecks = cls.isChecks.map((m) => m.name.key).toList();
if (cls.functionTypeIndex != null) {
isChecks.add(r'$signature');
}
Expect.setEquals(
expectedIsChecks,
isChecks,
"Unexpected is checks for $element: "
"Expected $expectedIsChecks, actual $isChecks.");
}
}
LibraryEntity library = elementEnvironment.mainLibrary;
elementEnvironment.forEachClass(library, processClass);
elementEnvironment.forEachLibraryMember(library, processMember);
closures.forEach(processClass);
}
asyncTest(() async {
print('--test from kernel------------------------------------------------');
await runTest();
});
}