| Index: tests/compiler/dart2js/equivalence/id_equivalence_test.dart
|
| diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_test.dart b/tests/compiler/dart2js/equivalence/id_equivalence_test.dart
|
| index ac63757b0710e0832246e14d1ddbd698be849830..a2b183ca0e92b4b27d599181b69e2631387cce01 100644
|
| --- a/tests/compiler/dart2js/equivalence/id_equivalence_test.dart
|
| +++ b/tests/compiler/dart2js/equivalence/id_equivalence_test.dart
|
| @@ -4,11 +4,15 @@
|
|
|
| import 'dart:io';
|
| import 'package:async_helper/async_helper.dart';
|
| +import 'package:compiler/src/common.dart';
|
| import 'package:compiler/src/compiler.dart';
|
| -import 'package:compiler/src/commandline_options.dart';
|
| +import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
|
| import 'package:compiler/src/elements/elements.dart';
|
| import 'package:compiler/src/elements/entities.dart';
|
| -import 'package:compiler/src/kernel/kernel.dart';
|
| +import 'package:compiler/src/kernel/element_map.dart';
|
| +import 'package:compiler/src/kernel/kernel_backend_strategy.dart';
|
| +import 'package:compiler/src/resolution/access_semantics.dart';
|
| +import 'package:compiler/src/resolution/send_structure.dart';
|
| import 'package:compiler/src/tree/nodes.dart' as ast;
|
| import 'package:expect/expect.dart';
|
| import 'package:kernel/ast.dart' as ir;
|
| @@ -16,6 +20,7 @@ import '../equivalence/id_equivalence.dart';
|
| import '../equivalence/id_equivalence_helper.dart';
|
|
|
| const List<String> dataDirectories = const <String>[
|
| + '../closure/data',
|
| '../inference/data',
|
| ];
|
|
|
| @@ -27,57 +32,148 @@ main() {
|
| print('Checking ${entity.uri}');
|
| String annotatedCode =
|
| await new File.fromUri(entity.uri).readAsString();
|
| - await checkCode(annotatedCode, checkMemberEquivalence,
|
| - options: [Flags.useKernel]);
|
| + IdData data1 = await computeData(
|
| + annotatedCode, computeAstMemberData, compileFromSource);
|
| + IdData data2 = await computeData(
|
| + annotatedCode, computeIrMemberData, compileFromDill);
|
| + data1.actualMap.forEach((Id id, String value1) {
|
| + String value2 = data2.actualMap[id];
|
| + if (value1 != value2) {
|
| + reportHere(data1.compiler.reporter, data1.sourceSpanMap[id],
|
| + '$id: from source:${value1},from dill:${value2}');
|
| + }
|
| + Expect.equals(value1, value2, 'Value mismatch for $id');
|
| + });
|
| + data2.actualMap.forEach((Id id, String value2) {
|
| + String value1 = data1.actualMap[id];
|
| + if (value1 != value2) {
|
| + reportHere(data2.compiler.reporter, data2.sourceSpanMap[id],
|
| + '$id: from source:${value1},from dill:${value2}');
|
| + }
|
| + Expect.equals(value1, value2, 'Value mismatch for $id');
|
| + });
|
| }
|
| }
|
| });
|
| }
|
|
|
| -/// Check that the ids in [expectedMap] map to equivalent nodes/elements in
|
| -/// the AST and kernel IR.
|
| -void checkMemberEquivalence(
|
| - Compiler compiler, Map<Id, String> expectedMap, MemberEntity _member) {
|
| +/// Compute a descriptive mapping of the [Id]s in [_member] as a
|
| +/// [MemberElement].
|
| +///
|
| +/// Fills [actualMap] with the data and [sourceSpanMap] with the source spans
|
| +/// for the data origin.
|
| +void computeAstMemberData(Compiler compiler, MemberEntity _member,
|
| + Map<Id, String> actualMap, Map<Id, SourceSpan> sourceSpanMap) {
|
| MemberElement member = _member;
|
| ResolvedAst resolvedAst = member.resolvedAst;
|
| if (resolvedAst.kind != ResolvedAstKind.PARSED) return;
|
| - Map<Id, ast.Node> astMap = <Id, ast.Node>{};
|
| - Map<Id, Element> elementMap = <Id, Element>{};
|
| - AstIdFinder astFinder = new AstIdFinder(resolvedAst.elements);
|
| - for (Id id in expectedMap.keys.toList()) {
|
| - var result = astFinder.find(resolvedAst.node, id);
|
| - if (result is ast.Node) {
|
| - astMap[id] = result;
|
| - } else if (result is AstElement) {
|
| - elementMap[id] = result;
|
| + new ResolvedAstComputer(
|
| + compiler.reporter, actualMap, sourceSpanMap, resolvedAst)
|
| + .run();
|
| +}
|
| +
|
| +/// Mixin used for0computing a descriptive mapping of the [Id]s in a member.
|
| +class ComputerMixin {
|
| + String computeMemberName(String className, String memberName) {
|
| + if (className != null) {
|
| + return 'member:$className.$memberName';
|
| }
|
| + return 'member:$memberName';
|
| + }
|
| +
|
| + String computeLocalName(String localName) {
|
| + return 'local:$localName';
|
| + }
|
| +
|
| + String computeDynamicGetName(String propertyName) {
|
| + return 'dynamic-get:$propertyName';
|
| + }
|
| +
|
| + String computeDynamicInvokeName(String propertyName) {
|
| + return 'dynamic-invoke:$propertyName';
|
| }
|
| +}
|
|
|
| - Kernel kernel = compiler.backend.kernelTask.kernel;
|
| - Map<Id, ir.Node> irMap = <Id, ir.Node>{};
|
| - ir.Node node = kernel.elementToIr(member);
|
| - IrIdFinder irFinder = new IrIdFinder();
|
| - for (Id id in expectedMap.keys.toList()) {
|
| - ir.Node result = irFinder.find(node, id);
|
| - if (result != null) {
|
| - irMap[id] = result;
|
| +/// AST visitor for computing a descriptive mapping of the [Id]s in a member.
|
| +class ResolvedAstComputer extends AbstractResolvedAstComputer
|
| + with ComputerMixin {
|
| + ResolvedAstComputer(DiagnosticReporter reporter, Map<Id, String> actualMap,
|
| + Map<Id, SourceSpan> spannableMap, ResolvedAst resolvedAst)
|
| + : super(reporter, actualMap, spannableMap, resolvedAst);
|
| +
|
| + @override
|
| + String computeNodeValue(ast.Node node, AstElement element) {
|
| + if (element != null && element.isLocal) {
|
| + return computeLocalName(element.name);
|
| }
|
| + if (node is ast.Send) {
|
| + dynamic sendStructure = elements.getSendStructure(node);
|
| + if (sendStructure == null) return null;
|
| +
|
| + String getDynamicName() {
|
| + switch (sendStructure.semantics.kind) {
|
| + case AccessKind.DYNAMIC_PROPERTY:
|
| + DynamicAccess access = sendStructure.semantics;
|
| + return access.name.text;
|
| + default:
|
| + return null;
|
| + }
|
| + }
|
| +
|
| + switch (sendStructure.kind) {
|
| + case SendStructureKind.GET:
|
| + String dynamicName = getDynamicName();
|
| + if (dynamicName != null) return computeDynamicGetName(dynamicName);
|
| + break;
|
| + case SendStructureKind.INVOKE:
|
| + String dynamicName = getDynamicName();
|
| + if (dynamicName != null) return computeDynamicInvokeName(dynamicName);
|
| + break;
|
| + default:
|
| + }
|
| + }
|
| + return '<unknown:$node>';
|
| }
|
|
|
| - elementMap.forEach((Id id, _element) {
|
| - AstElement element = _element;
|
| - ir.Node irNode = irMap[id];
|
| - Expect.equals(kernel.elementToIr(element), irNode,
|
| - "Element mismatch on $id = $element");
|
| - expectedMap.remove(id);
|
| - irMap.remove(id);
|
| - });
|
| - astMap.forEach((Id id, ast.Node astNode) {
|
| - ir.Node irNode = irMap[id];
|
| - Expect.equals(
|
| - kernel.nodeToAst[irNode], astNode, "Node mismatch on $id = $astNode");
|
| - expectedMap.remove(id);
|
| - irMap.remove(id);
|
| - });
|
| - Expect.isTrue(irMap.isEmpty, "Extra IR ids: $irMap");
|
| + @override
|
| + String computeElementValue(AstElement element) {
|
| + return computeMemberName(element.enclosingClass?.name, element.name);
|
| + }
|
| +}
|
| +
|
| +/// Compute a descriptive mapping of the [Id]s in [member] as a kernel based
|
| +/// member.
|
| +///
|
| +/// Fills [actualMap] with the data and [sourceSpanMap] with the source spans
|
| +/// for the data origin.
|
| +void computeIrMemberData(Compiler compiler, MemberEntity member,
|
| + Map<Id, String> actualMap, Map<Id, Spannable> spannableMap) {
|
| + KernelBackendStrategy backendStrategy = compiler.backendStrategy;
|
| + KernelToElementMap elementMap = backendStrategy.elementMap;
|
| + new IrComputer(actualMap, spannableMap).run(elementMap.getMemberNode(member));
|
| +}
|
| +
|
| +/// IR visitor for computing a descriptive mapping of the [Id]s in a member.
|
| +class IrComputer extends AbstractIrComputer with ComputerMixin {
|
| + IrComputer(Map<Id, String> actualMap, Map<Id, SourceSpan> spannableMap)
|
| + : super(actualMap, spannableMap);
|
| +
|
| + @override
|
| + String computeNodeValue(ir.TreeNode node) {
|
| + if (node is ir.VariableDeclaration) {
|
| + return computeLocalName(node.name);
|
| + } else if (node is ir.FunctionDeclaration) {
|
| + return computeLocalName(node.variable.name);
|
| + } else if (node is ir.MethodInvocation) {
|
| + return computeDynamicInvokeName(node.name.name);
|
| + } else if (node is ir.PropertyGet) {
|
| + return computeDynamicGetName(node.name.name);
|
| + }
|
| + return '<unknown:$node>';
|
| + }
|
| +
|
| + @override
|
| + String computeMemberValue(ir.Member member) {
|
| + return computeMemberName(member.enclosingClass?.name, member.name.name);
|
| + }
|
| }
|
|
|