20faaa5d94
Change-Id: Ib18f554c1076f27a3f7c0df5a36410da41a1f467 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/148784 Reviewed-by: Paul Berry <paulberry@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
112 lines
3.9 KiB
Dart
112 lines
3.9 KiB
Dart
// 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/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/js_model/js_strategy.dart';
|
|
import 'package:compiler/src/js/js.dart' as js;
|
|
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<T> {
|
|
final field;
|
|
|
|
@pragma('dart2js:noInline')
|
|
factory A.fact(t) => new A(t);
|
|
|
|
@pragma('dart2js:noInline')
|
|
A(t) : field = t is T;
|
|
}
|
|
|
|
// A call to A.fact.
|
|
@pragma('dart2js:noInline')
|
|
callAfact() => new A<int>.fact(0).runtimeType;
|
|
|
|
main() {
|
|
callAfact();
|
|
}
|
|
''';
|
|
|
|
main() {
|
|
asyncTest(() async {
|
|
CompilationResult result =
|
|
await runCompiler(memorySourceFiles: {'main.dart': code});
|
|
Expect.isTrue(result.isSuccess);
|
|
Compiler compiler = result.compiler;
|
|
JsBackendStrategy backendStrategy = compiler.backendStrategy;
|
|
JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
|
|
RuntimeTypesNeed rtiNeed = closedWorld.rtiNeed;
|
|
ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
|
|
ProgramLookup programLookup = new ProgramLookup(backendStrategy);
|
|
|
|
js.Name getName(String name) {
|
|
return backendStrategy.namerForTesting
|
|
.globalPropertyNameForMember(lookupMember(elementEnvironment, name));
|
|
}
|
|
|
|
void checkParameters(String name,
|
|
{int expectedParameterCount, bool needsTypeArguments}) {
|
|
FunctionEntity function = lookupMember(elementEnvironment, name);
|
|
|
|
Expect.equals(
|
|
needsTypeArguments,
|
|
rtiNeed.methodNeedsTypeArguments(function),
|
|
"Unexpected type argument need for $function.");
|
|
Method method = programLookup.getMethod(function);
|
|
Expect.isNotNull(method, "No method found for $function");
|
|
|
|
js.Fun fun = method.code;
|
|
Expect.equals(expectedParameterCount, fun.params.length,
|
|
"Unexpected parameter count on $function: ${js.nodeToString(fun)}");
|
|
}
|
|
|
|
// The declarations should have type parameters only when needed.
|
|
checkParameters('A.fact',
|
|
expectedParameterCount: 2, needsTypeArguments: false);
|
|
checkParameters('A.', expectedParameterCount: 2, needsTypeArguments: false);
|
|
|
|
checkArguments(String name, String targetName,
|
|
{int expectedTypeArguments}) {
|
|
FunctionEntity function = lookupMember(elementEnvironment, name);
|
|
Method method = programLookup.getMethod(function);
|
|
|
|
js.Fun fun = method.code;
|
|
|
|
js.Name selector = getName(targetName);
|
|
bool callFound = false;
|
|
forEachNode(fun, onCall: (js.Call node) {
|
|
js.Expression target = js.undefer(node.target);
|
|
if (target is js.PropertyAccess) {
|
|
js.Node targetSelector = js.undefer(target.selector);
|
|
if (targetSelector is js.Name && targetSelector.key == selector.key) {
|
|
callFound = true;
|
|
Expect.equals(
|
|
expectedTypeArguments,
|
|
node.arguments.length,
|
|
"Unexpected argument count in $function call to $targetName: "
|
|
"${js.nodeToString(fun)}");
|
|
}
|
|
}
|
|
});
|
|
Expect.isTrue(
|
|
callFound,
|
|
"No call to $targetName in $function found: "
|
|
"${js.nodeToString(fun)}");
|
|
}
|
|
|
|
// The declarations should have type parameters only when needed by the
|
|
// selector.
|
|
checkArguments('callAfact', 'A.fact', expectedTypeArguments: 2);
|
|
});
|
|
}
|