c878108cc8
All non-pubspec changes generated by `dart format pkg/compiler`. Change-Id: Iadaa70974816d96ccb47813fe72d5a2bb83d6bda Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/400181 Reviewed-by: Nate Biggs <natebiggs@google.com> Commit-Queue: Mayank Patke <fishythefish@google.com>
456 lines
11 KiB
Dart
456 lines
11 KiB
Dart
// Copyright (c) 2015, 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:compiler/src/common/elements.dart';
|
|
import 'package:compiler/src/common/names.dart';
|
|
import 'package:compiler/src/compiler.dart';
|
|
import 'package:compiler/src/elements/entities.dart';
|
|
import 'package:compiler/src/js_backend/no_such_method_registry.dart';
|
|
import 'package:compiler/src/js_model/elements.dart';
|
|
import 'package:compiler/src/js_model/js_world.dart' show JClosedWorld;
|
|
import 'package:expect/async_helper.dart';
|
|
import 'package:expect/expect.dart';
|
|
import 'package:compiler/src/util/memory_compiler.dart';
|
|
|
|
class NoSuchMethodInfo {
|
|
final String className;
|
|
final String? superClassName;
|
|
final bool hasThrowingSyntax;
|
|
final bool hasForwardingSyntax;
|
|
final bool isThrowing;
|
|
final bool isDefault;
|
|
final bool isOther;
|
|
final bool isComplexNoReturn;
|
|
final bool isComplexReturn;
|
|
|
|
const NoSuchMethodInfo(
|
|
this.className, {
|
|
this.superClassName,
|
|
this.hasThrowingSyntax = false,
|
|
this.hasForwardingSyntax = false,
|
|
this.isThrowing = false,
|
|
this.isDefault = false,
|
|
this.isOther = false,
|
|
this.isComplexNoReturn = false,
|
|
this.isComplexReturn = false,
|
|
});
|
|
}
|
|
|
|
class NoSuchMethodTest {
|
|
final String code;
|
|
final List<NoSuchMethodInfo> methods;
|
|
final bool isNoSuchMethodUsed;
|
|
|
|
const NoSuchMethodTest(
|
|
this.code,
|
|
this.methods, {
|
|
this.isNoSuchMethodUsed = false,
|
|
});
|
|
}
|
|
|
|
const List<NoSuchMethodTest> TESTS = const <NoSuchMethodTest>[
|
|
const NoSuchMethodTest(
|
|
"""
|
|
abstract class I {
|
|
foo();
|
|
}
|
|
class A implements I {
|
|
noSuchMethod(x) => super.noSuchMethod(x);
|
|
}
|
|
main() {
|
|
print(new A().foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo('A', hasForwardingSyntax: true, isDefault: true),
|
|
],
|
|
),
|
|
const NoSuchMethodTest(
|
|
"""
|
|
abstract class I {
|
|
foo();
|
|
}
|
|
class A extends B implements I {
|
|
noSuchMethod(x) => super.noSuchMethod(x);
|
|
}
|
|
class B {}
|
|
main() {
|
|
print(new A().foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo('A', hasForwardingSyntax: true, isDefault: true),
|
|
],
|
|
),
|
|
const NoSuchMethodTest(
|
|
"""
|
|
abstract class I {
|
|
foo();
|
|
}
|
|
class A extends B implements I {
|
|
noSuchMethod(x) {
|
|
return super.noSuchMethod(x);
|
|
}
|
|
}
|
|
class B {}
|
|
main() {
|
|
print(new A().foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo('A', hasForwardingSyntax: true, isDefault: true),
|
|
],
|
|
),
|
|
const NoSuchMethodTest(
|
|
"""
|
|
abstract class I {
|
|
foo();
|
|
}
|
|
class A extends B implements I {
|
|
noSuchMethod(x) => super.noSuchMethod(x);
|
|
}
|
|
class B {
|
|
noSuchMethod(x) => super.noSuchMethod(x);
|
|
}
|
|
main() {
|
|
print(new A().foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo(
|
|
'A',
|
|
superClassName: 'B',
|
|
hasForwardingSyntax: true,
|
|
isDefault: true,
|
|
),
|
|
const NoSuchMethodInfo('B', hasForwardingSyntax: true, isDefault: true),
|
|
],
|
|
),
|
|
const NoSuchMethodTest(
|
|
"""
|
|
abstract class I {
|
|
foo();
|
|
}
|
|
class A extends B implements I {
|
|
noSuchMethod(x) => super.noSuchMethod(x);
|
|
}
|
|
class B {
|
|
noSuchMethod(x) => throw 'foo';
|
|
}
|
|
main() {
|
|
print(new A().foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo(
|
|
'A',
|
|
superClassName: 'B',
|
|
hasForwardingSyntax: true,
|
|
isThrowing: true,
|
|
),
|
|
const NoSuchMethodInfo('B', hasThrowingSyntax: true, isThrowing: true),
|
|
],
|
|
isNoSuchMethodUsed: true,
|
|
),
|
|
const NoSuchMethodTest(
|
|
"""
|
|
class A {
|
|
noSuchMethod(x) => 3;
|
|
}
|
|
main() {
|
|
print((new A() as dynamic).foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo('A', isOther: true, isComplexReturn: true),
|
|
],
|
|
isNoSuchMethodUsed: true,
|
|
),
|
|
const NoSuchMethodTest(
|
|
"""
|
|
abstract class I {
|
|
foo();
|
|
}
|
|
class A implements I {
|
|
noSuchMethod(x, [y]) => super.noSuchMethod(x);
|
|
}
|
|
main() {
|
|
print(new A().foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo('A', hasForwardingSyntax: true, isDefault: true),
|
|
],
|
|
),
|
|
const NoSuchMethodTest(
|
|
"""
|
|
abstract class I {
|
|
foo();
|
|
}
|
|
class A implements I {
|
|
noSuchMethod(x, [y]) => super.noSuchMethod(y);
|
|
}
|
|
main() {
|
|
print(new A().foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo('A', isOther: true, isComplexNoReturn: true),
|
|
],
|
|
isNoSuchMethodUsed: true,
|
|
),
|
|
const NoSuchMethodTest(
|
|
"""
|
|
class A {
|
|
noSuchMethod(x, [y]) => super.noSuchMethod(x) + y;
|
|
}
|
|
main() {
|
|
print((new A() as dynamic).foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo('A', isOther: true, isComplexNoReturn: true),
|
|
],
|
|
isNoSuchMethodUsed: true,
|
|
),
|
|
const NoSuchMethodTest(
|
|
"""
|
|
class A {
|
|
noSuchMethod(Invocation x) {
|
|
throw UnsupportedError('');
|
|
}
|
|
}
|
|
main() {
|
|
print((new A() as dynamic).foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo('A', hasThrowingSyntax: true, isThrowing: true),
|
|
],
|
|
isNoSuchMethodUsed: true,
|
|
),
|
|
const NoSuchMethodTest(
|
|
"""
|
|
class A {
|
|
noSuchMethod(Invocation x) {
|
|
print('foo');
|
|
throw 'foo';
|
|
}
|
|
}
|
|
main() {
|
|
print((new A() as dynamic).foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo('A', isOther: true, isComplexNoReturn: true),
|
|
],
|
|
isNoSuchMethodUsed: true,
|
|
),
|
|
const NoSuchMethodTest(
|
|
"""
|
|
class A {
|
|
noSuchMethod(Invocation x) {
|
|
return toString();
|
|
}
|
|
}
|
|
main() {
|
|
print((new A() as dynamic).foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo('A', isOther: true, isComplexReturn: true),
|
|
],
|
|
isNoSuchMethodUsed: true,
|
|
),
|
|
const NoSuchMethodTest(
|
|
"""
|
|
abstract class I {
|
|
foo();
|
|
}
|
|
class A implements I {
|
|
noSuchMethod(x) => super.noSuchMethod(x) as dynamic;
|
|
}
|
|
main() {
|
|
print(new A().foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo('A', hasForwardingSyntax: true, isDefault: true),
|
|
],
|
|
),
|
|
const NoSuchMethodTest(
|
|
"""
|
|
abstract class I {
|
|
foo();
|
|
}
|
|
class A implements I {
|
|
noSuchMethod(x) => super.noSuchMethod(x) as int;
|
|
}
|
|
main() {
|
|
print(new A().foo());
|
|
}
|
|
""",
|
|
const <NoSuchMethodInfo>[
|
|
const NoSuchMethodInfo('A', isOther: true, isComplexNoReturn: true),
|
|
],
|
|
isNoSuchMethodUsed: true,
|
|
),
|
|
];
|
|
|
|
main() {
|
|
runTests() async {
|
|
for (NoSuchMethodTest test in TESTS) {
|
|
print('---- testing -------------------------------------------------');
|
|
print(test.code);
|
|
CompilationResult result = await runCompiler(
|
|
memorySourceFiles: {'main.dart': test.code},
|
|
);
|
|
Expect.isTrue(result.isSuccess);
|
|
Compiler compiler = result.compiler!;
|
|
checkTest(compiler, test);
|
|
}
|
|
}
|
|
|
|
asyncTest(() async {
|
|
print('--test from kernel------------------------------------------------');
|
|
await runTests();
|
|
});
|
|
}
|
|
|
|
checkTest(Compiler compiler, NoSuchMethodTest test) {
|
|
ElementEnvironment frontendEnvironment =
|
|
compiler.frontendStrategy.elementEnvironment;
|
|
NoSuchMethodRegistry registry =
|
|
compiler.frontendStrategy.noSuchMethodRegistry;
|
|
var resolver = registry.internalResolverForTesting;
|
|
final ObjectNSM =
|
|
frontendEnvironment.lookupClassMember(
|
|
compiler.frontendStrategy.commonElements.objectClass,
|
|
Names.noSuchMethod_,
|
|
)
|
|
as FunctionEntity;
|
|
JClosedWorld backendClosedWorld = compiler.backendClosedWorldForTesting!;
|
|
ElementEnvironment backendEnvironment = backendClosedWorld.elementEnvironment;
|
|
NoSuchMethodData data = backendClosedWorld.noSuchMethodData;
|
|
|
|
// Test [NoSuchMethodResolver] results for each method.
|
|
for (NoSuchMethodInfo info in test.methods) {
|
|
ClassEntity? cls = frontendEnvironment.lookupClass(
|
|
frontendEnvironment.mainLibrary!,
|
|
info.className,
|
|
);
|
|
Expect.isNotNull(cls, "Class ${info.className} not found.");
|
|
final noSuchMethod =
|
|
frontendEnvironment.lookupClassMember(cls!, Names.noSuchMethod_)
|
|
as FunctionEntity?;
|
|
Expect.isNotNull(noSuchMethod, "noSuchMethod not found in $cls.");
|
|
|
|
if (info.superClassName == null) {
|
|
Expect.equals(ObjectNSM, resolver.getSuperNoSuchMethod(noSuchMethod!));
|
|
} else {
|
|
ClassEntity? superclass = frontendEnvironment.lookupClass(
|
|
frontendEnvironment.mainLibrary!,
|
|
info.superClassName!,
|
|
);
|
|
Expect.isNotNull(
|
|
superclass,
|
|
"Superclass ${info.superClassName} not found.",
|
|
);
|
|
final superNoSuchMethod =
|
|
frontendEnvironment.lookupClassMember(
|
|
superclass!,
|
|
Names.noSuchMethod_,
|
|
)
|
|
as FunctionEntity?;
|
|
Expect.isNotNull(
|
|
superNoSuchMethod,
|
|
"noSuchMethod not found in $superclass.",
|
|
);
|
|
Expect.equals(
|
|
superNoSuchMethod,
|
|
resolver.getSuperNoSuchMethod(noSuchMethod!),
|
|
"Unexpected super noSuchMethod for $noSuchMethod.",
|
|
);
|
|
}
|
|
|
|
Expect.equals(
|
|
info.hasForwardingSyntax,
|
|
resolver.hasForwardingSyntax(noSuchMethod as JFunction),
|
|
"Unexpected hasForwardSyntax result on $noSuchMethod.",
|
|
);
|
|
Expect.equals(
|
|
info.hasThrowingSyntax,
|
|
resolver.hasThrowingSyntax(noSuchMethod),
|
|
"Unexpected hasThrowingSyntax result on $noSuchMethod.",
|
|
);
|
|
}
|
|
|
|
// Test [NoSuchMethodRegistry] results for each method. These are based on
|
|
// the [NoSuchMethodResolver] results which are therefore tested for all
|
|
// methods first.
|
|
for (NoSuchMethodInfo info in test.methods) {
|
|
ClassEntity? frontendClass = frontendEnvironment.lookupClass(
|
|
frontendEnvironment.mainLibrary!,
|
|
info.className,
|
|
);
|
|
Expect.isNotNull(frontendClass, "Class ${info.className} not found.");
|
|
final frontendNoSuchMethod =
|
|
frontendEnvironment.lookupClassMember(
|
|
frontendClass!,
|
|
Names.noSuchMethod_,
|
|
)
|
|
as FunctionEntity?;
|
|
Expect.isNotNull(
|
|
frontendNoSuchMethod,
|
|
"noSuchMethod not found in $frontendClass.",
|
|
);
|
|
|
|
Expect.equals(
|
|
info.isDefault,
|
|
registry.defaultImpls.contains(frontendNoSuchMethod),
|
|
"Unexpected isDefault result on $frontendNoSuchMethod.",
|
|
);
|
|
Expect.equals(
|
|
info.isThrowing,
|
|
registry.throwingImpls.contains(frontendNoSuchMethod),
|
|
"Unexpected isThrowing result on $frontendNoSuchMethod.",
|
|
);
|
|
Expect.equals(
|
|
info.isOther,
|
|
registry.otherImpls.contains(frontendNoSuchMethod),
|
|
"Unexpected isOther result on $frontendNoSuchMethod.",
|
|
);
|
|
|
|
ClassEntity? backendClass = backendEnvironment.lookupClass(
|
|
backendEnvironment.mainLibrary!,
|
|
info.className,
|
|
);
|
|
Expect.isNotNull(backendClass, "Class ${info.className} not found.");
|
|
final backendNoSuchMethod =
|
|
backendEnvironment.lookupClassMember(backendClass!, Names.noSuchMethod_)
|
|
as FunctionEntity?;
|
|
Expect.isNotNull(
|
|
backendNoSuchMethod,
|
|
"noSuchMethod not found in $backendClass.",
|
|
);
|
|
|
|
Expect.equals(
|
|
info.isComplexNoReturn,
|
|
data.complexNoReturnImpls.contains(backendNoSuchMethod),
|
|
"Unexpected isComplexNoReturn result on $backendNoSuchMethod.",
|
|
);
|
|
Expect.equals(
|
|
info.isComplexReturn,
|
|
data.complexReturningImpls.contains(backendNoSuchMethod),
|
|
"Unexpected isComplexReturn result on $backendNoSuchMethod.",
|
|
);
|
|
}
|
|
|
|
Expect.equals(
|
|
test.isNoSuchMethodUsed,
|
|
backendClosedWorld.backendUsage.isNoSuchMethodUsed,
|
|
"Unexpected isNoSuchMethodUsed result.",
|
|
);
|
|
}
|