OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 /// Functions for asserting equivalence across serialization. | 5 /// Functions for asserting equivalence across serialization. |
6 | 6 |
7 library dart2js.serialization.equivalence; | 7 library dart2js.serialization.equivalence; |
8 | 8 |
9 import '../common.dart'; | 9 import '../common.dart'; |
10 import '../common/resolution.dart'; | 10 import '../common/resolution.dart'; |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 areTypesEquivalent(ad.semantics.type, bd.semantics.type) && | 269 areTypesEquivalent(ad.semantics.type, bd.semantics.type) && |
270 areSelectorsEquivalent(ad.selector, bd.selector); | 270 areSelectorsEquivalent(ad.selector, bd.selector); |
271 case NewStructureKind.CONST_INVOKE: | 271 case NewStructureKind.CONST_INVOKE: |
272 return ad.constantInvokeKind == bd.constantInvokeKind && | 272 return ad.constantInvokeKind == bd.constantInvokeKind && |
273 areConstantsEquivalent(ad.constant, bd.constant); | 273 areConstantsEquivalent(ad.constant, bd.constant); |
274 case NewStructureKind.LATE_CONST: | 274 case NewStructureKind.LATE_CONST: |
275 throw new UnsupportedError('Unsupported NewStructure kind ${a.kind}.'); | 275 throw new UnsupportedError('Unsupported NewStructure kind ${a.kind}.'); |
276 } | 276 } |
277 } | 277 } |
278 | 278 |
| 279 /// Returns `true` if nodes [a] and [b] are equivalent. |
| 280 bool areNodesEquivalent(Node node1, Node node2) { |
| 281 if (identical(node1, node2)) return true; |
| 282 if (node1 == null || node2 == null) return false; |
| 283 return node1.accept1(const NodeEquivalenceVisitor(), node2); |
| 284 } |
| 285 |
279 /// Strategy for testing equivalence. | 286 /// Strategy for testing equivalence. |
280 /// | 287 /// |
281 /// Use this strategy to determine equivalence without failing on inequivalence. | 288 /// Use this strategy to determine equivalence without failing on inequivalence. |
282 class TestStrategy { | 289 class TestStrategy { |
283 const TestStrategy(); | 290 const TestStrategy(); |
284 | 291 |
285 bool test(var object1, var object2, String property, var value1, var value2, | 292 bool test(var object1, var object2, String property, var value1, var value2, |
286 [bool equivalence(a, b) = equality]) { | 293 [bool equivalence(a, b) = equality]) { |
287 return equivalence(value1, value2); | 294 return equivalence(value1, value2); |
288 } | 295 } |
(...skipping 27 matching lines...) Expand all Loading... |
316 | 323 |
317 bool testTypeLists(Object object1, Object object2, String property, | 324 bool testTypeLists(Object object1, Object object2, String property, |
318 List<DartType> list1, List<DartType> list2) { | 325 List<DartType> list1, List<DartType> list2) { |
319 return areTypeListsEquivalent(list1, list2); | 326 return areTypeListsEquivalent(list1, list2); |
320 } | 327 } |
321 | 328 |
322 bool testConstantLists(Object object1, Object object2, String property, | 329 bool testConstantLists(Object object1, Object object2, String property, |
323 List<ConstantExpression> list1, List<ConstantExpression> list2) { | 330 List<ConstantExpression> list1, List<ConstantExpression> list2) { |
324 return areConstantListsEquivalent(list1, list2); | 331 return areConstantListsEquivalent(list1, list2); |
325 } | 332 } |
| 333 |
| 334 bool testNodes( |
| 335 Object object1, Object object2, String property, Node node1, Node node2) { |
| 336 return areNodesEquivalent(node1, node2); |
| 337 } |
326 } | 338 } |
327 | 339 |
328 /// Visitor that checks for equivalence of [Element]s. | 340 /// Visitor that checks for equivalence of [Element]s. |
329 class ElementIdentityEquivalence extends BaseElementVisitor<bool, Element> { | 341 class ElementIdentityEquivalence extends BaseElementVisitor<bool, Element> { |
330 final TestStrategy strategy; | 342 final TestStrategy strategy; |
331 | 343 |
332 const ElementIdentityEquivalence([this.strategy = const TestStrategy()]); | 344 const ElementIdentityEquivalence([this.strategy = const TestStrategy()]); |
333 | 345 |
334 bool visit(Element element1, Element element2) { | 346 bool visit(Element element1, Element element2) { |
335 if (element1 == null && element2 == null) { | 347 if (element1 == null && element2 == null) { |
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
758 ResolvedAst resolvedAst1, ResolvedAst resolvedAst2, | 770 ResolvedAst resolvedAst1, ResolvedAst resolvedAst2, |
759 [TestStrategy strategy = const TestStrategy()]) { | 771 [TestStrategy strategy = const TestStrategy()]) { |
760 if (!strategy.test(resolvedAst1, resolvedAst1, 'kind', resolvedAst1.kind, | 772 if (!strategy.test(resolvedAst1, resolvedAst1, 'kind', resolvedAst1.kind, |
761 resolvedAst2.kind)) { | 773 resolvedAst2.kind)) { |
762 return false; | 774 return false; |
763 } | 775 } |
764 if (resolvedAst1.kind != ResolvedAstKind.PARSED) { | 776 if (resolvedAst1.kind != ResolvedAstKind.PARSED) { |
765 // Nothing more to check. | 777 // Nothing more to check. |
766 return true; | 778 return true; |
767 } | 779 } |
768 return strategy.testElements(resolvedAst1, resolvedAst2, 'element', | 780 bool result = strategy.testElements(resolvedAst1, resolvedAst2, 'element', |
769 resolvedAst1.element, resolvedAst2.element) && | 781 resolvedAst1.element, resolvedAst2.element) && |
770 new NodeEquivalenceVisitor(strategy).testNodes(resolvedAst1, resolvedAst2, | 782 strategy.testNodes(resolvedAst1, resolvedAst2, 'node', resolvedAst1.node, |
771 'node', resolvedAst1.node, resolvedAst2.node) && | 783 resolvedAst2.node) && |
772 new NodeEquivalenceVisitor(strategy).testNodes(resolvedAst1, resolvedAst2, | 784 strategy.testNodes(resolvedAst1, resolvedAst2, 'body', resolvedAst1.body, |
773 'body', resolvedAst1.body, resolvedAst2.body) && | 785 resolvedAst2.body) && |
774 testTreeElementsEquivalence(resolvedAst1, resolvedAst2, strategy) && | 786 testTreeElementsEquivalence(resolvedAst1, resolvedAst2, strategy) && |
775 strategy.test(resolvedAst1, resolvedAst2, 'sourceUri', | 787 strategy.test(resolvedAst1, resolvedAst2, 'sourceUri', |
776 resolvedAst1.sourceUri, resolvedAst2.sourceUri); | 788 resolvedAst1.sourceUri, resolvedAst2.sourceUri); |
| 789 if (resolvedAst1.element is FunctionElement) { |
| 790 FunctionElement element1 = resolvedAst1.element; |
| 791 FunctionElement element2 = resolvedAst2.element; |
| 792 for (int index = 0; index < element1.parameters.length; index++) { |
| 793 var parameter1 = element1.parameters[index]; |
| 794 var parameter2 = element2.parameters[index]; |
| 795 result = result && |
| 796 strategy.testNodes(parameter1, parameter2, 'node', |
| 797 parameter1.implementation.node, parameter2.implementation.node) && |
| 798 strategy.testNodes( |
| 799 parameter1, |
| 800 parameter2, |
| 801 'initializer', |
| 802 parameter1.implementation.initializer, |
| 803 parameter2.implementation.initializer); |
| 804 } |
| 805 } |
| 806 return result; |
777 } | 807 } |
778 | 808 |
779 /// Tests the equivalence of the data stored in the [TreeElements] of | 809 /// Tests the equivalence of the data stored in the [TreeElements] of |
780 /// [resolvedAst1] and [resolvedAst2] using [strategy]. | 810 /// [resolvedAst1] and [resolvedAst2] using [strategy]. |
781 bool testTreeElementsEquivalence( | 811 bool testTreeElementsEquivalence( |
782 ResolvedAst resolvedAst1, ResolvedAst resolvedAst2, | 812 ResolvedAst resolvedAst1, ResolvedAst resolvedAst2, |
783 [TestStrategy strategy = const TestStrategy()]) { | 813 [TestStrategy strategy = const TestStrategy()]) { |
784 AstIndexComputer indices1 = new AstIndexComputer(); | 814 AstIndexComputer indices1 = new AstIndexComputer(); |
785 resolvedAst1.node.accept(indices1); | 815 resolvedAst1.node.accept(indices1); |
786 AstIndexComputer indices2 = new AstIndexComputer(); | 816 AstIndexComputer indices2 = new AstIndexComputer(); |
(...skipping 970 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1757 @override | 1787 @override |
1758 bool visitStatement(Statement node1, Statement node2) { | 1788 bool visitStatement(Statement node1, Statement node2) { |
1759 throw new UnsupportedError('Unexpected nodes: $node1 <> $node2'); | 1789 throw new UnsupportedError('Unexpected nodes: $node1 <> $node2'); |
1760 } | 1790 } |
1761 | 1791 |
1762 @override | 1792 @override |
1763 bool visitStringNode(StringNode node1, StringNode node2) { | 1793 bool visitStringNode(StringNode node1, StringNode node2) { |
1764 throw new UnsupportedError('Unexpected nodes: $node1 <> $node2'); | 1794 throw new UnsupportedError('Unexpected nodes: $node1 <> $node2'); |
1765 } | 1795 } |
1766 } | 1796 } |
OLD | NEW |