Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: pkg/analyzer/lib/src/generated/incremental_resolver.dart

Issue 757743004: Update errors during incremental resolution. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_resolver; 5 library engine.incremental_resolver;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 import 'dart:math' as math; 8 import 'dart:math' as math;
9 9
10 import 'package:analyzer/src/generated/error_verifier.dart';
11
10 import 'ast.dart'; 12 import 'ast.dart';
11 import 'element.dart'; 13 import 'element.dart';
14 import 'engine.dart';
12 import 'error.dart'; 15 import 'error.dart';
13 import 'java_engine.dart'; 16 import 'java_engine.dart';
14 import 'parser.dart'; 17 import 'parser.dart';
15 import 'resolver.dart'; 18 import 'resolver.dart';
16 import 'scanner.dart'; 19 import 'scanner.dart';
17 import 'source.dart'; 20 import 'source.dart';
18 21
19 22
20 /** 23 /**
21 * Attempts to update [oldUnit] to the state that would correspond to [newCode].
22 * Returns `true` if success, or `false` otherwise.
23 * The [oldUnit] might be damaged.
24 */
25 bool poorMansIncrementalResolution(TypeProvider typeProvider,
26 CompilationUnit oldUnit, String newCode) {
27 try {
28 CompilationUnit newUnit = _parseUnit(newCode);
29 _TokenPair firstPair =
30 _findFirstDifferentToken(oldUnit.beginToken, newUnit.beginToken);
31 _TokenPair lastPair =
32 _findLastDifferentToken(oldUnit.endToken, newUnit.endToken);
33 if (firstPair != null && lastPair != null) {
34 // Prepare the "old" token range.
35 Token oldBeginToken;
36 Token oldEndToken;
37 if (firstPair.oldToken.offset < lastPair.oldToken.offset) {
38 oldBeginToken = firstPair.oldToken;
39 oldEndToken = lastPair.oldToken;
40 } else {
41 oldBeginToken = lastPair.oldToken;
42 oldEndToken = firstPair.oldToken;
43 }
44 // Prepare the "old" token tange.
45 Token newBeginToken;
46 Token newEndToken;
47 if (firstPair.newToken.offset < lastPair.newToken.offset) {
48 newBeginToken = firstPair.newToken;
49 newEndToken = lastPair.newToken;
50 } else {
51 newBeginToken = lastPair.newToken;
52 newEndToken = firstPair.newToken;
53 }
54 // Find nodes covering the "old" and "new" token ranges.
55 AstNode oldNode =
56 _findNodeWithTokens(oldUnit, oldBeginToken, oldEndToken);
57 AstNode newNode =
58 _findNodeWithTokens(newUnit, newBeginToken, newEndToken);
59 // Try to find the smallest common node, a FunctionBody currently.
60 {
61 List<AstNode> oldParents = _getParents(oldNode);
62 List<AstNode> newParents = _getParents(newNode);
63 int length = math.min(oldParents.length, newParents.length);
64 bool found = false;
65 for (int i = 0; i < length; i++) {
66 AstNode oldParent = oldParents[i];
67 AstNode newParent = newParents[i];
68 if (oldParent is FunctionBody && newParent is FunctionBody) {
69 oldNode = oldParent;
70 newNode = newParent;
71 found = true;
72 break;
73 }
74 }
75 if (!found) {
76 return false;
77 }
78 }
79 // replace node
80 NodeReplacer.replace(oldNode, newNode);
81 // update token references
82 oldNode.beginToken.previous.setNext(newNode.beginToken);
83 oldNode.endToken.setNext(oldNode.endToken.next);
84 // perform incremental resolution
85 // TODO(scheglov) update errors
86 AnalysisErrorListener errorListener = new BooleanErrorListener();
87 CompilationUnitElement oldUnitElement = oldUnit.element;
88 IncrementalResolver incrementalResolver = new IncrementalResolver(
89 errorListener,
90 typeProvider,
91 oldUnitElement.library,
92 oldUnitElement,
93 oldUnitElement.source,
94 oldNode.offset,
95 oldNode.length,
96 newNode.length);
97 incrementalResolver.resolve(newNode);
98 return true;
99 }
100 } catch (e) {
101 // TODO(scheglov) find a way to log these exceptions
102 }
103 return false;
104 }
105
106
107 bool _equalToken(Token oldToken, Token newToken, int delta) {
108 if (oldToken.type != newToken.type) {
109 return false;
110 }
111 if (newToken.offset - oldToken.offset != delta) {
112 return false;
113 }
114 return oldToken.lexeme == newToken.lexeme;
115 }
116
117
118 _TokenPair _findFirstDifferentToken(Token oldToken, Token newToken) {
119 // print('first ------------');
120 while (oldToken.type != TokenType.EOF && newToken.type != TokenType.EOF) {
121 // print('old: $oldToken @ ${oldToken.offset}');
122 // print('new: $newToken @ ${newToken.offset}');
123 if (!_equalToken(oldToken, newToken, 0)) {
124 return new _TokenPair(oldToken, newToken);
125 }
126 oldToken = oldToken.next;
127 newToken = newToken.next;
128 }
129 return null;
130 }
131
132
133 _TokenPair _findLastDifferentToken(Token oldToken, Token newToken) {
134 // print('last ------------');
135 int delta = newToken.offset - oldToken.offset;
136 while (oldToken.previous != oldToken && newToken.previous != newToken) {
137 // print('old: $oldToken @ ${oldToken.offset}');
138 // print('new: $newToken @ ${newToken.offset}');
139 if (!_equalToken(oldToken, newToken, delta)) {
140 return new _TokenPair(oldToken.next, newToken.next);
141 }
142 oldToken.offset += delta;
143 oldToken = oldToken.previous;
144 newToken = newToken.previous;
145 }
146 return null;
147 }
148
149
150 AstNode _findNodeWithTokens(AstNode root, Token first, Token last) {
151 int offset = first.offset;
152 int end = last.end;
153 NodeLocator nodeLocator = new NodeLocator.con2(offset, end);
154 return nodeLocator.searchWithin(root);
155 }
156
157
158 List<AstNode> _getParents(AstNode node) {
159 List<AstNode> parents = <AstNode>[];
160 while (node != null) {
161 parents.insert(0, node);
162 node = node.parent;
163 }
164 return parents;
165 }
166
167
168 CompilationUnit _parseUnit(String code) {
169 // TODO(scheglov) remember and update errors
170 var errorListener = new BooleanErrorListener();
171 var reader = new CharSequenceReader(code);
172 var scanner = new Scanner(null, reader, errorListener);
173 var token = scanner.tokenize();
174 var parser = new Parser(null, errorListener);
175 return parser.parseCompilationUnit(token);
176 }
177
178
179 /**
180 * Instances of the class [DeclarationMatcher] determine whether the element 24 * Instances of the class [DeclarationMatcher] determine whether the element
181 * model defined by a given AST structure matches an existing element model. 25 * model defined by a given AST structure matches an existing element model.
182 */ 26 */
183 class DeclarationMatcher extends RecursiveAstVisitor { 27 class DeclarationMatcher extends RecursiveAstVisitor {
184 /** 28 /**
185 * The libary containing the AST nodes being visited. 29 * The libary containing the AST nodes being visited.
186 */ 30 */
187 LibraryElement _enclosingLibrary; 31 LibraryElement _enclosingLibrary;
188 32
189 /** 33 /**
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 } 619 }
776 } 620 }
777 621
778 622
779 /** 623 /**
780 * Instances of the class [IncrementalResolver] resolve the smallest portion of 624 * Instances of the class [IncrementalResolver] resolve the smallest portion of
781 * an AST structure that we currently know how to resolve. 625 * an AST structure that we currently know how to resolve.
782 */ 626 */
783 class IncrementalResolver { 627 class IncrementalResolver {
784 /** 628 /**
785 * The error listener that will be informed of any errors that are found
786 * during resolution.
787 */
788 final AnalysisErrorListener _errorListener;
789
790 /**
791 * The object used to access the types from the core library. 629 * The object used to access the types from the core library.
792 */ 630 */
793 final TypeProvider _typeProvider; 631 final TypeProvider _typeProvider;
794 632
795 /** 633 /**
796 * The element for the library containing the compilation unit being resolved. 634 * The element for the library containing the compilation unit being resolved.
797 */ 635 */
798 final LibraryElement _definingLibrary; 636 final LibraryElement _definingLibrary;
799 637
800 /** 638 /**
(...skipping 14 matching lines...) Expand all
815 /** 653 /**
816 * The number of characters in the original contents that were replaced. 654 * The number of characters in the original contents that were replaced.
817 */ 655 */
818 final int _updateOldLength; 656 final int _updateOldLength;
819 657
820 /** 658 /**
821 * The number of characters in the replacement text. 659 * The number of characters in the replacement text.
822 */ 660 */
823 final int _updateNewLength; 661 final int _updateNewLength;
824 662
663 ResolutionContext _resolutionContext;
664
665 List<AnalysisError> _resolveErrors = AnalysisError.NO_ERRORS;
666 List<AnalysisError> _verifyErrors = AnalysisError.NO_ERRORS;
667 List<AnalysisError> _hints = AnalysisError.NO_ERRORS;
668
825 /** 669 /**
826 * Initialize a newly created incremental resolver to resolve a node in the 670 * Initialize a newly created incremental resolver to resolve a node in the
827 * given source in the given library, reporting errors to the given error 671 * given source in the given library.
828 * listener.
829 */ 672 */
830 IncrementalResolver(this._errorListener, this._typeProvider, 673 IncrementalResolver(this._typeProvider, this._definingLibrary,
831 this._definingLibrary, this._definingUnit, this._source, this._updateOffse t, 674 this._definingUnit, this._source, this._updateOffset, this._updateOldLengt h,
832 this._updateOldLength, this._updateNewLength); 675 this._updateNewLength);
833 676
834 /** 677 /**
835 * Resolve [node], reporting any errors or warnings to the given listener. 678 * Resolve [node], reporting any errors or warnings to the given listener.
836 * 679 *
837 * [node] - the root of the AST structure to be resolved. 680 * [node] - the root of the AST structure to be resolved.
838 */ 681 */
839 void resolve(AstNode node) { 682 void resolve(AstNode node) {
840 AstNode rootNode = _findResolutionRoot(node); 683 AstNode rootNode = _findResolutionRoot(node);
841 // update elements 684 // update elements
842 _definingUnit.accept( 685 _definingUnit.accept(
843 new _ElementNameOffsetUpdater( 686 new _ElementNameOffsetUpdater(
844 _updateOffset, 687 _updateOffset,
845 _updateNewLength - _updateOldLength)); 688 _updateNewLength - _updateOldLength));
846 if (_elementModelChanged(rootNode)) { 689 if (_elementModelChanged(rootNode)) {
847 throw new AnalysisException("Cannot resolve node: element model changed"); 690 throw new AnalysisException("Cannot resolve node: element model changed");
848 } 691 }
849 _updateElements(rootNode); 692 _updateElements(rootNode);
850 // resolve root in scope 693 // resolve
851 ResolutionContext context = 694 _resolveReferences(rootNode);
852 ResolutionContextBuilder.contextFor(rootNode, _errorListener); 695 // verify
853 Scope scope = context.scope; 696 _verify(rootNode);
854 _resolveTypes(rootNode, scope); 697 _generateHints(rootNode);
855 _resolveVariables(rootNode, scope);
856 _resolveReferences(rootNode, context);
857 } 698 }
858 699
859 /** 700 /**
860 * Return `true` if the given node can be resolved independently of any other 701 * Return `true` if the given node can be resolved independently of any other
861 * nodes. 702 * nodes.
862 * 703 *
863 * *Note*: This method needs to be kept in sync with 704 * *Note*: This method needs to be kept in sync with
864 * [ScopeBuilder.ContextBuilder]. 705 * [ScopeBuilder.ContextBuilder].
865 * 706 *
866 * [node] - the node being tested. 707 * [node] - the node being tested.
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 AstNode _findResolutionRoot(AstNode node) { 751 AstNode _findResolutionRoot(AstNode node) {
911 while (node != null) { 752 while (node != null) {
912 if (_canBeResolved(node)) { 753 if (_canBeResolved(node)) {
913 return node; 754 return node;
914 } 755 }
915 node = node.parent; 756 node = node.parent;
916 } 757 }
917 throw new AnalysisException("Cannot resolve node: no resolvable node"); 758 throw new AnalysisException("Cannot resolve node: no resolvable node");
918 } 759 }
919 760
761 void _generateHints(AstNode node) {
762 RecordingErrorListener errorListener = new RecordingErrorListener();
763 CompilationUnit unit = node.getAncestor((n) => n is CompilationUnit);
764 AnalysisContext analysisContext = _definingLibrary.context;
765 HintGenerator hintGenerator =
766 new HintGenerator(<CompilationUnit>[unit], analysisContext, errorListene r);
767 hintGenerator.generateForLibrary();
768 _hints = errorListener.getErrorsForSource(_source);
769 }
770
920 /** 771 /**
921 * Return the element defined by [node], or `null` if the node does not 772 * Return the element defined by [node], or `null` if the node does not
922 * define an element. 773 * define an element.
923 */ 774 */
924 Element _getElement(AstNode node) { 775 Element _getElement(AstNode node) {
925 if (node is Declaration) { 776 if (node is Declaration) {
926 return node.element; 777 return node.element;
927 } else if (node is CompilationUnit) { 778 } else if (node is CompilationUnit) {
928 return node.element; 779 return node.element;
929 } 780 }
930 return null; 781 return null;
931 } 782 }
932 783
933 void _resolveReferences(AstNode node, ResolutionContext context) { 784 _resolveReferences(AstNode node) {
934 ResolverVisitor visitor = new ResolverVisitor.con3( 785 RecordingErrorListener errorListener = new RecordingErrorListener();
935 _definingLibrary, 786 // prepare context
936 _source, 787 _resolutionContext =
937 _typeProvider, 788 ResolutionContextBuilder.contextFor(node, errorListener);
938 context.scope, 789 Scope scope = _resolutionContext.scope;
939 _errorListener); 790 // resolve types
940 visitor.enclosingClass = context.enclosingClass; 791 {
941 node.accept(visitor); 792 TypeResolverVisitor visitor = new TypeResolverVisitor.con3(
942 } 793 _definingLibrary,
943 794 _source,
944 void _resolveTypes(AstNode node, Scope scope) { 795 _typeProvider,
945 TypeResolverVisitor visitor = new TypeResolverVisitor.con3( 796 scope,
946 _definingLibrary, 797 errorListener);
947 _source, 798 node.accept(visitor);
948 _typeProvider, 799 }
949 scope, 800 // resolve variables
950 _errorListener); 801 {
951 node.accept(visitor); 802 VariableResolverVisitor visitor = new VariableResolverVisitor.con2(
952 } 803 _definingLibrary,
953 804 _source,
954 void _resolveVariables(AstNode node, Scope scope) { 805 _typeProvider,
955 VariableResolverVisitor visitor = new VariableResolverVisitor.con2( 806 scope,
956 _definingLibrary, 807 errorListener);
957 _source, 808 node.accept(visitor);
958 _typeProvider, 809 }
959 scope, 810 // resolve references
960 _errorListener); 811 {
961 node.accept(visitor); 812 ResolverVisitor visitor = new ResolverVisitor.con3(
813 _definingLibrary,
814 _source,
815 _typeProvider,
816 _resolutionContext.scope,
817 errorListener);
818 visitor.enclosingClass = _resolutionContext.enclosingClass;
819 node.accept(visitor);
820 }
821 // remember errors
822 _resolveErrors = errorListener.getErrorsForSource(_source);
962 } 823 }
963 824
964 void _updateElements(AstNode node) { 825 void _updateElements(AstNode node) {
965 // build elements in node 826 // build elements in node
966 ElementHolder holder; 827 ElementHolder holder;
967 _ElementsRestorer elementsRestorer = new _ElementsRestorer(node); 828 _ElementsRestorer elementsRestorer = new _ElementsRestorer(node);
968 try { 829 try {
969 holder = new ElementHolder(); 830 holder = new ElementHolder();
970 ElementBuilder builder = new ElementBuilder(holder); 831 ElementBuilder builder = new ElementBuilder(holder);
971 node.accept(builder); 832 node.accept(builder);
972 } finally { 833 } finally {
973 elementsRestorer.restore(); 834 elementsRestorer.restore();
974 } 835 }
975 // apply compatible changes to elements 836 // apply compatible changes to elements
976 if (node is FunctionDeclaration) { 837 if (node is FunctionDeclaration) {
977 FunctionElementImpl oldElement = node.element; 838 FunctionElementImpl oldElement = node.element;
978 FunctionElementImpl newElement = holder.functions[0]; 839 FunctionElementImpl newElement = holder.functions[0];
979 oldElement.labels = newElement.labels; 840 oldElement.labels = newElement.labels;
980 oldElement.localVariables = newElement.localVariables; 841 oldElement.localVariables = newElement.localVariables;
981 } 842 }
982 if (node is MethodDeclaration) { 843 if (node is MethodDeclaration) {
983 MethodElementImpl oldElement = node.element; 844 MethodElementImpl oldElement = node.element;
984 MethodElementImpl newElement = holder.methods[0]; 845 MethodElementImpl newElement = holder.methods[0];
985 oldElement.labels = newElement.labels; 846 oldElement.labels = newElement.labels;
986 oldElement.localVariables = newElement.localVariables; 847 oldElement.localVariables = newElement.localVariables;
987 } 848 }
988 } 849 }
850
851 void _verify(AstNode node) {
852 RecordingErrorListener errorListener = new RecordingErrorListener();
853 ErrorReporter errorReporter = new ErrorReporter(errorListener, _source);
854 ErrorVerifier errorVerifier = new ErrorVerifier(
855 errorReporter,
856 _definingLibrary,
857 _typeProvider,
858 new InheritanceManager(_definingLibrary));
859 if (_resolutionContext.enclosingClassDeclaration != null) {
860 errorVerifier.initClassDeclaration(
861 _resolutionContext.enclosingClassDeclaration);
862 }
863 node.accept(errorVerifier);
864 _verifyErrors = errorListener.getErrorsForSource(_source);
865 }
989 } 866 }
990 867
991 868
869 class PoorMansIncrementalResolver {
870 final TypeProvider _typeProvider;
871 final Source _unitSource;
872 final Source _librarySource;
873 final DartEntry _entry;
874
875 int _updateOffset;
876 int _updateDelta;
877 int _updateEndOld;
878 int _updateEndNew;
879
880 List<AnalysisError> _newScanErrors = <AnalysisError>[];
881 List<AnalysisError> _newParseErrors = <AnalysisError>[];
882 List<AnalysisError> _newResolveErrors = <AnalysisError>[];
883 List<AnalysisError> _newVerifyErrors = <AnalysisError>[];
884 List<AnalysisError> _newHints = <AnalysisError>[];
885
886 PoorMansIncrementalResolver(this._typeProvider, this._unitSource,
887 this._librarySource, this._entry);
888
889 /**
890 * Attempts to update [oldUnit] to the state corresponding to [newCode].
891 * Returns `true` if success, or `false` otherwise.
892 * The [oldUnit] might be damaged.
893 */
894 bool resolve(CompilationUnit oldUnit, String newCode) {
895 try {
896 CompilationUnit newUnit = _parseUnit(newCode);
897 _TokenPair firstPair =
898 _findFirstDifferentToken(oldUnit.beginToken, newUnit.beginToken);
899 _TokenPair lastPair =
900 _findLastDifferentToken(oldUnit.endToken, newUnit.endToken);
901 if (firstPair != null && lastPair != null) {
902 // Prepare the "old" token range.
903 Token oldBeginToken;
904 Token oldEndToken;
905 if (firstPair.oldToken.offset < lastPair.oldToken.offset) {
906 oldBeginToken = firstPair.oldToken;
907 oldEndToken = lastPair.oldToken;
908 } else {
909 oldBeginToken = lastPair.oldToken;
910 oldEndToken = firstPair.oldToken;
911 }
912 // Prepare the "old" token tange.
913 Token newBeginToken;
914 Token newEndToken;
915 if (firstPair.newToken.offset < lastPair.newToken.offset) {
916 newBeginToken = firstPair.newToken;
917 newEndToken = lastPair.newToken;
918 } else {
919 newBeginToken = lastPair.newToken;
920 newEndToken = firstPair.newToken;
921 }
922 // Find nodes covering the "old" and "new" token ranges.
923 AstNode oldNode =
924 _findNodeWithTokens(oldUnit, oldBeginToken, oldEndToken);
925 AstNode newNode =
926 _findNodeWithTokens(newUnit, newBeginToken, newEndToken);
927 // Try to find the smallest common node, a FunctionBody currently.
928 {
929 List<AstNode> oldParents = _getParents(oldNode);
930 List<AstNode> newParents = _getParents(newNode);
931 int length = math.min(oldParents.length, newParents.length);
932 bool found = false;
933 for (int i = 0; i < length; i++) {
934 AstNode oldParent = oldParents[i];
935 AstNode newParent = newParents[i];
936 if (oldParent is FunctionBody && newParent is FunctionBody) {
937 oldNode = oldParent;
938 newNode = newParent;
939 found = true;
940 break;
941 }
942 }
943 if (!found) {
944 return false;
945 }
946 }
947 // replace node
948 NodeReplacer.replace(oldNode, newNode);
949 // update token references
950 oldNode.beginToken.previous.setNext(newNode.beginToken);
951 oldNode.endToken.setNext(oldNode.endToken.next);
952 // prepare update range
953 _updateOffset = oldNode.offset;
954 _updateDelta = lastPair.delta;
955 _updateEndOld = oldNode.end;
956 _updateEndNew = newNode.end;
957 // perform incremental resolution
958 CompilationUnitElement oldUnitElement = oldUnit.element;
959 IncrementalResolver incrementalResolver = new IncrementalResolver(
960 _typeProvider,
961 oldUnitElement.library,
962 oldUnitElement,
963 oldUnitElement.source,
964 _updateOffset,
965 oldNode.length,
966 newNode.length + _updateDelta);
967 incrementalResolver.resolve(newNode);
968 _newResolveErrors = incrementalResolver._resolveErrors;
969 _newVerifyErrors = incrementalResolver._verifyErrors;
970 _newHints = incrementalResolver._hints;
971 _updateEntry();
972 return true;
973 }
974 } catch (e, st) {
975 // TODO(scheglov) find a way to log these exceptions
976 print(e);
977 print(st);
978 }
979 return false;
980 }
981
982 CompilationUnit _parseUnit(String code) {
983 Token token = _scan(code);
984 RecordingErrorListener errorListener = new RecordingErrorListener();
985 Parser parser = new Parser(_unitSource, errorListener);
986 CompilationUnit unit = parser.parseCompilationUnit(token);
987 _newParseErrors = errorListener.errors;
988 return unit;
989 }
990
991 Token _scan(String code) {
992 RecordingErrorListener errorListener = new RecordingErrorListener();
993 CharSequenceReader reader = new CharSequenceReader(code);
994 Scanner scanner = new Scanner(_unitSource, reader, errorListener);
995 Token token = scanner.tokenize();
996 _newScanErrors = errorListener.errors;
997 return token;
998 }
999
1000 void _updateEntry() {
1001 {
1002 List<AnalysisError> oldErrors = _entry.getValue(DartEntry.SCAN_ERRORS);
1003 List<AnalysisError> errors = _updateErrors(oldErrors, _newScanErrors);
Brian Wilkerson 2014/11/25 14:53:58 Given that we're scanning and parsing the whole fi
scheglov 2014/11/25 18:54:11 Good idea! Done.
1004 _entry.setValue(DartEntry.SCAN_ERRORS, errors);
1005 }
1006 {
1007 List<AnalysisError> oldErrors = _entry.getValue(DartEntry.PARSE_ERRORS);
1008 List<AnalysisError> errors = _updateErrors(oldErrors, _newParseErrors);
1009 _entry.setValue(DartEntry.PARSE_ERRORS, errors);
1010 }
1011 {
1012 List<AnalysisError> oldErrors =
1013 _entry.getValueInLibrary(DartEntry.RESOLUTION_ERRORS, _librarySource);
1014 List<AnalysisError> errors = _updateErrors(oldErrors, _newResolveErrors);
1015 _entry.setValueInLibrary(
1016 DartEntry.RESOLUTION_ERRORS,
1017 _librarySource,
1018 errors);
1019 }
1020 {
1021 List<AnalysisError> oldErrors =
1022 _entry.getValueInLibrary(DartEntry.VERIFICATION_ERRORS, _librarySource );
1023 List<AnalysisError> errors = _updateErrors(oldErrors, _newVerifyErrors);
1024 _entry.setValueInLibrary(
1025 DartEntry.VERIFICATION_ERRORS,
1026 _librarySource,
1027 errors);
1028 }
1029 {
1030 List<AnalysisError> oldErrors =
1031 _entry.getValueInLibrary(DartEntry.HINTS, _librarySource);
1032 List<AnalysisError> errors = _updateErrors(oldErrors, _newHints);
1033 _entry.setValueInLibrary(DartEntry.HINTS, _librarySource, errors);
1034 }
1035 }
1036
1037 List<AnalysisError> _updateErrors(List<AnalysisError> oldErrors,
1038 List<AnalysisError> newErrors) {
1039 List<AnalysisError> errors = new List<AnalysisError>();
1040 // add updated old errors
1041 for (AnalysisError error in oldErrors) {
1042 int errorOffset = error.offset;
1043 if (errorOffset < _updateOffset) {
1044 errors.add(error);
1045 } else if (errorOffset > _updateEndOld) {
1046 error.offset += _updateDelta;
1047 errors.add(error);
1048 }
1049 }
1050 // add new errors
1051 for (AnalysisError error in newErrors) {
1052 int errorOffset = error.offset;
1053 if (errorOffset > _updateOffset && errorOffset < _updateEndNew) {
1054 errors.add(error);
1055 }
1056 }
1057 // done
1058 return errors;
1059 }
1060
1061 static bool _equalToken(Token oldToken, Token newToken, int delta) {
1062 if (oldToken.type != newToken.type) {
1063 return false;
1064 }
1065 if (newToken.offset - oldToken.offset != delta) {
1066 return false;
1067 }
1068 return oldToken.lexeme == newToken.lexeme;
1069 }
1070
1071 static _TokenPair _findFirstDifferentToken(Token oldToken, Token newToken) {
1072 // print('first ------------');
1073 while (oldToken.type != TokenType.EOF && newToken.type != TokenType.EOF) {
1074 // print('old: $oldToken @ ${oldToken.offset}');
1075 // print('new: $newToken @ ${newToken.offset}');
1076 if (!_equalToken(oldToken, newToken, 0)) {
1077 return new _TokenPair(oldToken, newToken, 0);
1078 }
1079 oldToken = oldToken.next;
1080 newToken = newToken.next;
1081 }
1082 return null;
1083 }
1084
1085 static _TokenPair _findLastDifferentToken(Token oldToken, Token newToken) {
1086 // print('last ------------');
1087 int delta = newToken.offset - oldToken.offset;
1088 while (oldToken.previous != oldToken && newToken.previous != newToken) {
1089 // print('old: $oldToken @ ${oldToken.offset}');
1090 // print('new: $newToken @ ${newToken.offset}');
1091 if (!_equalToken(oldToken, newToken, delta)) {
1092 return new _TokenPair(oldToken.next, newToken.next, delta);
1093 }
1094 oldToken.offset += delta;
1095 oldToken = oldToken.previous;
1096 newToken = newToken.previous;
1097 }
1098 return null;
1099 }
1100
1101 static AstNode _findNodeWithTokens(AstNode root, Token first, Token last) {
1102 int offset = first.offset;
1103 int end = last.end;
1104 NodeLocator nodeLocator = new NodeLocator.con2(offset, end);
1105 return nodeLocator.searchWithin(root);
1106 }
1107
1108 static List<AstNode> _getParents(AstNode node) {
1109 List<AstNode> parents = <AstNode>[];
1110 while (node != null) {
1111 parents.insert(0, node);
1112 node = node.parent;
1113 }
1114 return parents;
1115 }
1116 }
1117
1118
992 /** 1119 /**
993 * The context to resolve an [AstNode] in. 1120 * The context to resolve an [AstNode] in.
994 */ 1121 */
995 class ResolutionContext { 1122 class ResolutionContext {
1123 ClassDeclaration enclosingClassDeclaration;
996 ClassElement enclosingClass; 1124 ClassElement enclosingClass;
997 Scope scope; 1125 Scope scope;
998 } 1126 }
999 1127
1000 1128
1001 /** 1129 /**
1002 * Instances of the class [ResolutionContextBuilder] build the context for a 1130 * Instances of the class [ResolutionContextBuilder] build the context for a
1003 * given node in an AST structure. At the moment, this class only handles 1131 * given node in an AST structure. At the moment, this class only handles
1004 * top-level and class-level declarations. 1132 * top-level and class-level declarations.
1005 */ 1133 */
1006 class ResolutionContextBuilder { 1134 class ResolutionContextBuilder {
1007 /** 1135 /**
1008 * The listener to which analysis errors will be reported. 1136 * The listener to which analysis errors will be reported.
1009 */ 1137 */
1010 final AnalysisErrorListener _errorListener; 1138 final AnalysisErrorListener _errorListener;
1011 1139
1012 /** 1140 /**
1013 * The class containing the AST nodes being visited, or `null` if we are not 1141 * The class containing the enclosing [ClassDeclaration], or `null` if we are
1142 * not in the scope of a class.
1143 */
1144 ClassDeclaration _enclosingClassDeclaration;
1145
1146 /**
1147 * The class containing the enclosing [ClassElement], or `null` if we are not
1014 * in the scope of a class. 1148 * in the scope of a class.
1015 */ 1149 */
1016 ClassElement _enclosingClass; 1150 ClassElement _enclosingClass;
1017 1151
1018 /** 1152 /**
1019 * Initialize a newly created scope builder to generate a scope that will 1153 * Initialize a newly created scope builder to generate a scope that will
1020 * report errors to the given listener. 1154 * report errors to the given listener.
1021 */ 1155 */
1022 ResolutionContextBuilder(this._errorListener); 1156 ResolutionContextBuilder(this._errorListener);
1023 1157
(...skipping 24 matching lines...) Expand all
1048 if (node is CompilationUnit) { 1182 if (node is CompilationUnit) {
1049 return _scopeForCompilationUnit(node); 1183 return _scopeForCompilationUnit(node);
1050 } 1184 }
1051 AstNode parent = node.parent; 1185 AstNode parent = node.parent;
1052 if (parent == null) { 1186 if (parent == null) {
1053 throw new AnalysisException( 1187 throw new AnalysisException(
1054 "Cannot create scope: node is not part of a CompilationUnit"); 1188 "Cannot create scope: node is not part of a CompilationUnit");
1055 } 1189 }
1056 Scope scope = _scopeForAstNode(parent); 1190 Scope scope = _scopeForAstNode(parent);
1057 if (node is ClassDeclaration) { 1191 if (node is ClassDeclaration) {
1192 _enclosingClassDeclaration = node;
1058 _enclosingClass = node.element; 1193 _enclosingClass = node.element;
1059 if (_enclosingClass == null) { 1194 if (_enclosingClass == null) {
1060 throw new AnalysisException( 1195 throw new AnalysisException(
1061 "Cannot build a scope for an unresolved class"); 1196 "Cannot build a scope for an unresolved class");
1062 } 1197 }
1063 scope = new ClassScope( 1198 scope = new ClassScope(
1064 new TypeParameterScope(scope, _enclosingClass), 1199 new TypeParameterScope(scope, _enclosingClass),
1065 _enclosingClass); 1200 _enclosingClass);
1066 } else if (node is ClassTypeAlias) { 1201 } else if (node is ClassTypeAlias) {
1067 ClassElement element = node.element; 1202 ClassElement element = node.element;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 if (node == null) { 1266 if (node == null) {
1132 throw new AnalysisException("Cannot create context: node is null"); 1267 throw new AnalysisException("Cannot create context: node is null");
1133 } 1268 }
1134 // build scope 1269 // build scope
1135 ResolutionContextBuilder builder = 1270 ResolutionContextBuilder builder =
1136 new ResolutionContextBuilder(errorListener); 1271 new ResolutionContextBuilder(errorListener);
1137 Scope scope = builder._scopeFor(node); 1272 Scope scope = builder._scopeFor(node);
1138 // prepare context 1273 // prepare context
1139 ResolutionContext context = new ResolutionContext(); 1274 ResolutionContext context = new ResolutionContext();
1140 context.scope = scope; 1275 context.scope = scope;
1276 context.enclosingClassDeclaration = builder._enclosingClassDeclaration;
1141 context.enclosingClass = builder._enclosingClass; 1277 context.enclosingClass = builder._enclosingClass;
1142 return context; 1278 return context;
1143 } 1279 }
1144 } 1280 }
1145 1281
1146 1282
1147 /** 1283 /**
1148 * Instances of the class [_DeclarationMismatchException] represent an exception 1284 * Instances of the class [_DeclarationMismatchException] represent an exception
1149 * that is thrown when the element model defined by a given AST structure does 1285 * that is thrown when the element model defined by a given AST structure does
1150 * not match an existing element model. 1286 * not match an existing element model.
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1266 @override 1402 @override
1267 visitSimpleIdentifier(SimpleIdentifier node) { 1403 visitSimpleIdentifier(SimpleIdentifier node) {
1268 _elements[node] = node.staticElement; 1404 _elements[node] = node.staticElement;
1269 } 1405 }
1270 } 1406 }
1271 1407
1272 1408
1273 class _TokenPair { 1409 class _TokenPair {
1274 final Token oldToken; 1410 final Token oldToken;
1275 final Token newToken; 1411 final Token newToken;
1276 _TokenPair(this.oldToken, this.newToken); 1412 final int delta;
1413 _TokenPair(this.oldToken, this.newToken, this.delta);
1277 } 1414 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/error_verifier.dart ('k') | pkg/analyzer/test/generated/incremental_resolver_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698