Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library engine.incremental_resolution_validator; | 5 library engine.incremental_resolution_validator; |
| 6 | 6 |
| 7 import 'package:analyzer/src/generated/ast.dart'; | 7 import 'package:analyzer/src/generated/ast.dart'; |
| 8 import 'package:analyzer/src/generated/element.dart'; | 8 import 'package:analyzer/src/generated/element.dart'; |
| 9 | 9 |
| 10 | 10 |
| 11 /** | |
| 12 * Validates that the [actual] and the [expected] units have the same structure | |
| 13 * and resolution. Throws [IncrementalResolutionMismatch] otherwise. | |
| 14 */ | |
| 11 void assertSameResolution(CompilationUnit actual, CompilationUnit expected, | 15 void assertSameResolution(CompilationUnit actual, CompilationUnit expected, |
| 12 FailHandler failHandler) { | 16 {bool validateTypes: false}) { |
|
danrubel
2015/01/07 22:32:48
validateTypes true by default?
| |
| 13 _SameResolutionValidator validator = | 17 _SameResolutionValidator validator = |
| 14 new _SameResolutionValidator(failHandler, expected); | 18 new _SameResolutionValidator(validateTypes, expected); |
| 15 actual.accept(validator); | 19 actual.accept(validator); |
| 16 } | 20 } |
| 17 | 21 |
| 18 | 22 |
| 19 typedef FailHandler(String reason); | 23 /** |
| 24 * This exception is thrown when a mismatch between actual and expected AST | |
| 25 * or resolution is found. | |
| 26 */ | |
| 27 class IncrementalResolutionMismatch { | |
| 28 final String message; | |
| 29 IncrementalResolutionMismatch(this.message); | |
| 30 } | |
| 20 | 31 |
| 21 | 32 |
| 22 class _SameResolutionValidator implements AstVisitor { | 33 class _SameResolutionValidator implements AstVisitor { |
| 23 final FailHandler failHandler; | 34 final bool validateTypes; |
| 24 AstNode other; | 35 AstNode other; |
| 25 | 36 |
| 26 _SameResolutionValidator(this.failHandler, this.other); | 37 _SameResolutionValidator(this.validateTypes, this.other); |
| 27 | 38 |
| 28 @override | 39 @override |
| 29 visitAdjacentStrings(AdjacentStrings node) { | 40 visitAdjacentStrings(AdjacentStrings node) { |
| 30 } | 41 } |
| 31 | 42 |
| 32 @override | 43 @override |
| 33 visitAnnotation(Annotation node) { | 44 visitAnnotation(Annotation node) { |
| 34 Annotation other = this.other; | 45 Annotation other = this.other; |
| 35 _visitNode(node.name, other.name); | 46 _visitNode(node.name, other.name); |
| 36 _visitNode(node.constructorName, other.constructorName); | 47 _visitNode(node.constructorName, other.constructorName); |
| (...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 768 visitYieldStatement(YieldStatement node) { | 779 visitYieldStatement(YieldStatement node) { |
| 769 YieldStatement other = this.other; | 780 YieldStatement other = this.other; |
| 770 _visitNode(node.expression, other.expression); | 781 _visitNode(node.expression, other.expression); |
| 771 } | 782 } |
| 772 | 783 |
| 773 void _expectEquals(actual, expected) { | 784 void _expectEquals(actual, expected) { |
| 774 if (actual != expected) { | 785 if (actual != expected) { |
| 775 String message = ''; | 786 String message = ''; |
| 776 message += 'Expected: $expected\n'; | 787 message += 'Expected: $expected\n'; |
| 777 message += ' Actual: $actual\n'; | 788 message += ' Actual: $actual\n'; |
| 778 failHandler(message); | 789 _fail(message); |
| 779 } | 790 } |
| 780 } | 791 } |
| 781 | 792 |
| 782 void _expectIsNull(obj) { | 793 void _expectIsNull(obj) { |
| 783 if (obj != null) { | 794 if (obj != null) { |
| 784 String message = ''; | 795 String message = ''; |
| 785 message += 'Expected: null\n'; | 796 message += 'Expected: null\n'; |
| 786 message += ' Actual: $obj\n'; | 797 message += ' Actual: $obj\n'; |
| 787 failHandler(message); | 798 _fail(message); |
| 788 } | 799 } |
| 789 } | 800 } |
| 790 | 801 |
| 791 void _expectLength(List actualList, int expected) { | 802 void _expectLength(List actualList, int expected) { |
| 792 String message = ''; | 803 String message = ''; |
| 793 message += 'Expected length: $expected\n'; | 804 message += 'Expected length: $expected\n'; |
| 794 if (actualList == null) { | 805 if (actualList == null) { |
| 795 message += 'but null found.'; | 806 message += 'but null found.'; |
| 796 failHandler(message); | 807 _fail(message); |
| 797 } | 808 } |
| 798 int actual = actualList.length; | 809 int actual = actualList.length; |
| 799 if (actual != expected) { | 810 if (actual != expected) { |
| 800 message += 'but $actual found\n'; | 811 message += 'but $actual found\n'; |
| 801 message += 'in $actualList'; | 812 message += 'in $actualList'; |
| 802 failHandler(message); | 813 _fail(message); |
| 803 } | 814 } |
| 804 } | 815 } |
| 805 | 816 |
| 817 void _fail(String message) { | |
| 818 throw new IncrementalResolutionMismatch(message); | |
| 819 } | |
| 820 | |
| 806 void _verifyElement(Element a, Element b) { | 821 void _verifyElement(Element a, Element b) { |
| 807 if (a != b) { | 822 if (a is Member && b is Member) { |
| 808 print(a.location); | 823 a = (a as Member).baseElement; |
| 809 print(b.location); | 824 b = (b as Member).baseElement; |
| 810 failHandler('Expected: $b\n Actual: $a'); | 825 } |
| 826 String locationA = _getElementLocationWithoutUri(a); | |
| 827 String locationB = _getElementLocationWithoutUri(b); | |
| 828 if (locationA != locationB) { | |
| 829 int offset = other.offset; | |
| 830 _fail('[$offset]\nExpected: $b ($locationB)\n Actual: $a ($locationA)'); | |
| 811 } | 831 } |
| 812 if (a == null && b == null) { | 832 if (a == null && b == null) { |
| 813 return; | 833 return; |
| 814 } | 834 } |
| 815 if (a.nameOffset != b.nameOffset) { | 835 if (a.nameOffset != b.nameOffset) { |
| 816 failHandler('Expected: ${b.nameOffset}\n Actual: ${a.nameOffset}'); | 836 _fail('Expected: ${b.nameOffset}\n Actual: ${a.nameOffset}'); |
| 817 } | 837 } |
| 818 } | 838 } |
| 819 | 839 |
| 820 void _verifyType(DartType a, DartType b) { | 840 void _verifyType(DartType a, DartType b) { |
| 841 if (!validateTypes) { | |
| 842 return; | |
| 843 } | |
| 821 if (a != b) { | 844 if (a != b) { |
| 822 failHandler('Expected: $b\n Actual: $a'); | 845 int offset = other.offset; |
| 846 _fail('[$offset]\nExpected: $b\n Actual: $a'); | |
| 823 } | 847 } |
| 824 } | 848 } |
| 825 | 849 |
| 826 void _visitAnnotatedNode(AnnotatedNode node, AnnotatedNode other) { | 850 void _visitAnnotatedNode(AnnotatedNode node, AnnotatedNode other) { |
| 827 _visitNode(node.documentationComment, other.documentationComment); | 851 _visitNode(node.documentationComment, other.documentationComment); |
| 828 _visitList(node.metadata, other.metadata); | 852 _visitList(node.metadata, other.metadata); |
| 829 } | 853 } |
| 830 | 854 |
| 831 _visitDeclaration(Declaration node, Declaration other) { | 855 _visitDeclaration(Declaration node, Declaration other) { |
| 832 _verifyElement(node.element, other.element); | 856 _verifyElement(node.element, other.element); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 864 } | 888 } |
| 865 } | 889 } |
| 866 | 890 |
| 867 void _visitNormalFormalParameter(NormalFormalParameter node, | 891 void _visitNormalFormalParameter(NormalFormalParameter node, |
| 868 NormalFormalParameter other) { | 892 NormalFormalParameter other) { |
| 869 _verifyElement(node.element, other.element); | 893 _verifyElement(node.element, other.element); |
| 870 _visitNode(node.documentationComment, other.documentationComment); | 894 _visitNode(node.documentationComment, other.documentationComment); |
| 871 _visitList(node.metadata, other.metadata); | 895 _visitList(node.metadata, other.metadata); |
| 872 _visitNode(node.identifier, other.identifier); | 896 _visitNode(node.identifier, other.identifier); |
| 873 } | 897 } |
| 898 | |
| 899 /** | |
| 900 * Returns an URI scheme independent version of the [element] location. | |
| 901 */ | |
| 902 static String _getElementLocationWithoutUri(Element element) { | |
| 903 if (element == null) { | |
| 904 return '<null>'; | |
| 905 } | |
| 906 if (element is UriReferencedElementImpl) { | |
| 907 return '<ignored>'; | |
| 908 } | |
| 909 ElementLocation location = element.location; | |
| 910 List<String> components = location.components; | |
| 911 String uriPrefix = ''; | |
| 912 Element unit = element is CompilationUnitElement ? | |
| 913 element : | |
| 914 element.getAncestor((e) => e is CompilationUnitElement); | |
| 915 if (unit != null) { | |
| 916 String libComponent = components[0]; | |
| 917 String unitComponent = components[1]; | |
| 918 components = components.sublist(2); | |
| 919 uriPrefix = _getShortElementLocationUri(libComponent) + | |
| 920 ':' + | |
| 921 _getShortElementLocationUri(unitComponent); | |
| 922 } else { | |
| 923 String libComponent = components[0]; | |
| 924 components = components.sublist(1); | |
| 925 uriPrefix = _getShortElementLocationUri(libComponent); | |
| 926 } | |
| 927 return uriPrefix + ':' + components.join(':'); | |
| 928 } | |
| 929 | |
| 930 /** | |
| 931 * Returns a "short" version of the given [uri]. | |
| 932 * | |
| 933 * For example: | |
| 934 * /User/me/project/lib/my_lib.dart -> my_lib.dart | |
| 935 * package:project/my_lib.dart -> my_lib.dart | |
| 936 */ | |
| 937 static String _getShortElementLocationUri(String uri) { | |
| 938 int index = uri.lastIndexOf('/'); | |
| 939 if (index == -1) { | |
| 940 return uri; | |
| 941 } | |
| 942 return uri.substring(index + 1); | |
| 943 } | |
| 874 } | 944 } |
| OLD | NEW |