OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'dart:io'; | 5 import 'dart:io'; |
6 import 'package:async_helper/async_helper.dart'; | 6 import 'package:async_helper/async_helper.dart'; |
| 7 import 'package:compiler/src/common.dart'; |
7 import 'package:compiler/src/compiler.dart'; | 8 import 'package:compiler/src/compiler.dart'; |
8 import 'package:compiler/src/commandline_options.dart'; | 9 import 'package:compiler/src/diagnostics/diagnostic_listener.dart'; |
9 import 'package:compiler/src/elements/elements.dart'; | 10 import 'package:compiler/src/elements/elements.dart'; |
10 import 'package:compiler/src/elements/entities.dart'; | 11 import 'package:compiler/src/elements/entities.dart'; |
11 import 'package:compiler/src/kernel/kernel.dart'; | 12 import 'package:compiler/src/kernel/element_map.dart'; |
| 13 import 'package:compiler/src/kernel/kernel_backend_strategy.dart'; |
| 14 import 'package:compiler/src/resolution/access_semantics.dart'; |
| 15 import 'package:compiler/src/resolution/send_structure.dart'; |
12 import 'package:compiler/src/tree/nodes.dart' as ast; | 16 import 'package:compiler/src/tree/nodes.dart' as ast; |
13 import 'package:expect/expect.dart'; | 17 import 'package:expect/expect.dart'; |
14 import 'package:kernel/ast.dart' as ir; | 18 import 'package:kernel/ast.dart' as ir; |
15 import '../equivalence/id_equivalence.dart'; | 19 import '../equivalence/id_equivalence.dart'; |
16 import '../equivalence/id_equivalence_helper.dart'; | 20 import '../equivalence/id_equivalence_helper.dart'; |
17 | 21 |
18 const List<String> dataDirectories = const <String>[ | 22 const List<String> dataDirectories = const <String>[ |
| 23 '../closure/data', |
19 '../inference/data', | 24 '../inference/data', |
20 ]; | 25 ]; |
21 | 26 |
22 main() { | 27 main() { |
23 asyncTest(() async { | 28 asyncTest(() async { |
24 for (String path in dataDirectories) { | 29 for (String path in dataDirectories) { |
25 Directory dataDir = new Directory.fromUri(Platform.script.resolve(path)); | 30 Directory dataDir = new Directory.fromUri(Platform.script.resolve(path)); |
26 await for (FileSystemEntity entity in dataDir.list()) { | 31 await for (FileSystemEntity entity in dataDir.list()) { |
27 print('Checking ${entity.uri}'); | 32 print('Checking ${entity.uri}'); |
28 String annotatedCode = | 33 String annotatedCode = |
29 await new File.fromUri(entity.uri).readAsString(); | 34 await new File.fromUri(entity.uri).readAsString(); |
30 await checkCode(annotatedCode, checkMemberEquivalence, | 35 IdData data1 = await computeData( |
31 options: [Flags.useKernel]); | 36 annotatedCode, computeAstMemberData, compileFromSource); |
| 37 IdData data2 = await computeData( |
| 38 annotatedCode, computeIrMemberData, compileFromDill); |
| 39 data1.actualMap.forEach((Id id, String value1) { |
| 40 String value2 = data2.actualMap[id]; |
| 41 if (value1 != value2) { |
| 42 reportHere(data1.compiler.reporter, data1.sourceSpanMap[id], |
| 43 '$id: from source:${value1},from dill:${value2}'); |
| 44 } |
| 45 Expect.equals(value1, value2, 'Value mismatch for $id'); |
| 46 }); |
| 47 data2.actualMap.forEach((Id id, String value2) { |
| 48 String value1 = data1.actualMap[id]; |
| 49 if (value1 != value2) { |
| 50 reportHere(data2.compiler.reporter, data2.sourceSpanMap[id], |
| 51 '$id: from source:${value1},from dill:${value2}'); |
| 52 } |
| 53 Expect.equals(value1, value2, 'Value mismatch for $id'); |
| 54 }); |
32 } | 55 } |
33 } | 56 } |
34 }); | 57 }); |
35 } | 58 } |
36 | 59 |
37 /// Check that the ids in [expectedMap] map to equivalent nodes/elements in | 60 /// Compute a descriptive mapping of the [Id]s in [_member] as a |
38 /// the AST and kernel IR. | 61 /// [MemberElement]. |
39 void checkMemberEquivalence( | 62 /// |
40 Compiler compiler, Map<Id, String> expectedMap, MemberEntity _member) { | 63 /// Fills [actualMap] with the data and [sourceSpanMap] with the source spans |
| 64 /// for the data origin. |
| 65 void computeAstMemberData(Compiler compiler, MemberEntity _member, |
| 66 Map<Id, String> actualMap, Map<Id, SourceSpan> sourceSpanMap) { |
41 MemberElement member = _member; | 67 MemberElement member = _member; |
42 ResolvedAst resolvedAst = member.resolvedAst; | 68 ResolvedAst resolvedAst = member.resolvedAst; |
43 if (resolvedAst.kind != ResolvedAstKind.PARSED) return; | 69 if (resolvedAst.kind != ResolvedAstKind.PARSED) return; |
44 Map<Id, ast.Node> astMap = <Id, ast.Node>{}; | 70 new ResolvedAstComputer( |
45 Map<Id, Element> elementMap = <Id, Element>{}; | 71 compiler.reporter, actualMap, sourceSpanMap, resolvedAst) |
46 AstIdFinder astFinder = new AstIdFinder(resolvedAst.elements); | 72 .run(); |
47 for (Id id in expectedMap.keys.toList()) { | 73 } |
48 var result = astFinder.find(resolvedAst.node, id); | 74 |
49 if (result is ast.Node) { | 75 /// Mixin used for0computing a descriptive mapping of the [Id]s in a member. |
50 astMap[id] = result; | 76 class ComputerMixin { |
51 } else if (result is AstElement) { | 77 String computeMemberName(String className, String memberName) { |
52 elementMap[id] = result; | 78 if (className != null) { |
| 79 return 'member:$className.$memberName'; |
53 } | 80 } |
| 81 return 'member:$memberName'; |
54 } | 82 } |
55 | 83 |
56 Kernel kernel = compiler.backend.kernelTask.kernel; | 84 String computeLocalName(String localName) { |
57 Map<Id, ir.Node> irMap = <Id, ir.Node>{}; | 85 return 'local:$localName'; |
58 ir.Node node = kernel.elementToIr(member); | |
59 IrIdFinder irFinder = new IrIdFinder(); | |
60 for (Id id in expectedMap.keys.toList()) { | |
61 ir.Node result = irFinder.find(node, id); | |
62 if (result != null) { | |
63 irMap[id] = result; | |
64 } | |
65 } | 86 } |
66 | 87 |
67 elementMap.forEach((Id id, _element) { | 88 String computeDynamicGetName(String propertyName) { |
68 AstElement element = _element; | 89 return 'dynamic-get:$propertyName'; |
69 ir.Node irNode = irMap[id]; | 90 } |
70 Expect.equals(kernel.elementToIr(element), irNode, | 91 |
71 "Element mismatch on $id = $element"); | 92 String computeDynamicInvokeName(String propertyName) { |
72 expectedMap.remove(id); | 93 return 'dynamic-invoke:$propertyName'; |
73 irMap.remove(id); | 94 } |
74 }); | |
75 astMap.forEach((Id id, ast.Node astNode) { | |
76 ir.Node irNode = irMap[id]; | |
77 Expect.equals( | |
78 kernel.nodeToAst[irNode], astNode, "Node mismatch on $id = $astNode"); | |
79 expectedMap.remove(id); | |
80 irMap.remove(id); | |
81 }); | |
82 Expect.isTrue(irMap.isEmpty, "Extra IR ids: $irMap"); | |
83 } | 95 } |
| 96 |
| 97 /// AST visitor for computing a descriptive mapping of the [Id]s in a member. |
| 98 class ResolvedAstComputer extends AbstractResolvedAstComputer |
| 99 with ComputerMixin { |
| 100 ResolvedAstComputer(DiagnosticReporter reporter, Map<Id, String> actualMap, |
| 101 Map<Id, SourceSpan> spannableMap, ResolvedAst resolvedAst) |
| 102 : super(reporter, actualMap, spannableMap, resolvedAst); |
| 103 |
| 104 @override |
| 105 String computeNodeValue(ast.Node node, AstElement element) { |
| 106 if (element != null && element.isLocal) { |
| 107 return computeLocalName(element.name); |
| 108 } |
| 109 if (node is ast.Send) { |
| 110 dynamic sendStructure = elements.getSendStructure(node); |
| 111 if (sendStructure == null) return null; |
| 112 |
| 113 String getDynamicName() { |
| 114 switch (sendStructure.semantics.kind) { |
| 115 case AccessKind.DYNAMIC_PROPERTY: |
| 116 DynamicAccess access = sendStructure.semantics; |
| 117 return access.name.text; |
| 118 default: |
| 119 return null; |
| 120 } |
| 121 } |
| 122 |
| 123 switch (sendStructure.kind) { |
| 124 case SendStructureKind.GET: |
| 125 String dynamicName = getDynamicName(); |
| 126 if (dynamicName != null) return computeDynamicGetName(dynamicName); |
| 127 break; |
| 128 case SendStructureKind.INVOKE: |
| 129 String dynamicName = getDynamicName(); |
| 130 if (dynamicName != null) return computeDynamicInvokeName(dynamicName); |
| 131 break; |
| 132 default: |
| 133 } |
| 134 } |
| 135 return '<unknown:$node>'; |
| 136 } |
| 137 |
| 138 @override |
| 139 String computeElementValue(AstElement element) { |
| 140 return computeMemberName(element.enclosingClass?.name, element.name); |
| 141 } |
| 142 } |
| 143 |
| 144 /// Compute a descriptive mapping of the [Id]s in [member] as a kernel based |
| 145 /// member. |
| 146 /// |
| 147 /// Fills [actualMap] with the data and [sourceSpanMap] with the source spans |
| 148 /// for the data origin. |
| 149 void computeIrMemberData(Compiler compiler, MemberEntity member, |
| 150 Map<Id, String> actualMap, Map<Id, Spannable> spannableMap) { |
| 151 KernelBackendStrategy backendStrategy = compiler.backendStrategy; |
| 152 KernelToElementMap elementMap = backendStrategy.elementMap; |
| 153 new IrComputer(actualMap, spannableMap).run(elementMap.getMemberNode(member)); |
| 154 } |
| 155 |
| 156 /// IR visitor for computing a descriptive mapping of the [Id]s in a member. |
| 157 class IrComputer extends AbstractIrComputer with ComputerMixin { |
| 158 IrComputer(Map<Id, String> actualMap, Map<Id, SourceSpan> spannableMap) |
| 159 : super(actualMap, spannableMap); |
| 160 |
| 161 @override |
| 162 String computeNodeValue(ir.TreeNode node) { |
| 163 if (node is ir.VariableDeclaration) { |
| 164 return computeLocalName(node.name); |
| 165 } else if (node is ir.FunctionDeclaration) { |
| 166 return computeLocalName(node.variable.name); |
| 167 } else if (node is ir.MethodInvocation) { |
| 168 return computeDynamicInvokeName(node.name.name); |
| 169 } else if (node is ir.PropertyGet) { |
| 170 return computeDynamicGetName(node.name.name); |
| 171 } |
| 172 return '<unknown:$node>'; |
| 173 } |
| 174 |
| 175 @override |
| 176 String computeMemberValue(ir.Member member) { |
| 177 return computeMemberName(member.enclosingClass?.name, member.name.name); |
| 178 } |
| 179 } |
OLD | NEW |