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_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'; | 10 import 'package:analyzer/src/generated/error_verifier.dart'; |
| (...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 663 this._updateNewLength); | 663 this._updateNewLength); |
| 664 | 664 |
| 665 /** | 665 /** |
| 666 * Resolve [node], reporting any errors or warnings to the given listener. | 666 * Resolve [node], reporting any errors or warnings to the given listener. |
| 667 * | 667 * |
| 668 * [node] - the root of the AST structure to be resolved. | 668 * [node] - the root of the AST structure to be resolved. |
| 669 */ | 669 */ |
| 670 void resolve(AstNode node) { | 670 void resolve(AstNode node) { |
| 671 AstNode rootNode = _findResolutionRoot(node); | 671 AstNode rootNode = _findResolutionRoot(node); |
| 672 // update elements | 672 // update elements |
| 673 _definingUnit.accept( | 673 _updateElementNameOffsets( |
| 674 new _ElementNameOffsetUpdater( | 674 _definingUnit, |
| 675 _updateOffset, | 675 _updateOffset, |
| 676 _updateNewLength - _updateOldLength)); | 676 _updateNewLength - _updateOldLength); |
| 677 if (_elementModelChanged(rootNode)) { | 677 if (_elementModelChanged(rootNode)) { |
| 678 throw new AnalysisException("Cannot resolve node: element model changed"); | 678 throw new AnalysisException("Cannot resolve node: element model changed"); |
| 679 } | 679 } |
| 680 _updateElements(rootNode); | 680 _updateElements(rootNode); |
| 681 // resolve | 681 // resolve |
| 682 _resolveReferences(rootNode); | 682 _resolveReferences(rootNode); |
| 683 // verify | 683 // verify |
| 684 _verify(rootNode); | 684 _verify(rootNode); |
| 685 _generateHints(rootNode); | 685 _generateHints(rootNode); |
| 686 } | 686 } |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 871 _definingLibrary, | 871 _definingLibrary, |
| 872 _typeProvider, | 872 _typeProvider, |
| 873 new InheritanceManager(_definingLibrary)); | 873 new InheritanceManager(_definingLibrary)); |
| 874 if (_resolutionContext.enclosingClassDeclaration != null) { | 874 if (_resolutionContext.enclosingClassDeclaration != null) { |
| 875 errorVerifier.visitClassDeclarationIncrementally( | 875 errorVerifier.visitClassDeclarationIncrementally( |
| 876 _resolutionContext.enclosingClassDeclaration); | 876 _resolutionContext.enclosingClassDeclaration); |
| 877 } | 877 } |
| 878 node.accept(errorVerifier); | 878 node.accept(errorVerifier); |
| 879 _verifyErrors = errorListener.getErrorsForSource(_source); | 879 _verifyErrors = errorListener.getErrorsForSource(_source); |
| 880 } | 880 } |
| 881 | |
| 882 static void _updateElementNameOffsets(Element root, int offset, int delta) { | |
| 883 root.accept(new _ElementNameOffsetUpdater(offset, delta)); | |
| 884 } | |
| 881 } | 885 } |
| 882 | 886 |
| 883 | 887 |
| 884 class PoorMansIncrementalResolver { | 888 class PoorMansIncrementalResolver { |
| 885 final TypeProvider _typeProvider; | 889 final TypeProvider _typeProvider; |
| 886 final Source _unitSource; | 890 final Source _unitSource; |
| 887 final Source _librarySource; | 891 final Source _librarySource; |
| 888 final DartEntry _entry; | 892 final DartEntry _entry; |
| 889 | 893 |
| 890 int _updateOffset; | 894 int _updateOffset; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 915 _findLastDifferentToken(oldUnit.endToken, newUnit.endToken); | 919 _findLastDifferentToken(oldUnit.endToken, newUnit.endToken); |
| 916 if (firstPair != null && lastPair != null) { | 920 if (firstPair != null && lastPair != null) { |
| 917 int firstOffsetOld = firstPair.oldToken.offset; | 921 int firstOffsetOld = firstPair.oldToken.offset; |
| 918 int firstOffsetNew = firstPair.newToken.offset; | 922 int firstOffsetNew = firstPair.newToken.offset; |
| 919 int lastOffsetOld = lastPair.oldToken.end; | 923 int lastOffsetOld = lastPair.oldToken.end; |
| 920 int lastOffsetNew = lastPair.newToken.end; | 924 int lastOffsetNew = lastPair.newToken.end; |
| 921 int beginOffsetOld = math.min(firstOffsetOld, lastOffsetOld); | 925 int beginOffsetOld = math.min(firstOffsetOld, lastOffsetOld); |
| 922 int endOffsetOld = math.max(firstOffsetOld, lastOffsetOld); | 926 int endOffsetOld = math.max(firstOffsetOld, lastOffsetOld); |
| 923 int beginOffsetNew = math.min(firstOffsetNew, lastOffsetNew); | 927 int beginOffsetNew = math.min(firstOffsetNew, lastOffsetNew); |
| 924 int endOffsetNew = math.max(firstOffsetNew, lastOffsetNew); | 928 int endOffsetNew = math.max(firstOffsetNew, lastOffsetNew); |
| 929 // check for a whitespace only change | |
|
Brian Wilkerson
2014/11/26 23:22:37
Does this handle changes in dartdoc comments? Chan
scheglov
2014/11/26 23:25:37
Not yet.
Support for incremental resolving dartdoc
| |
| 930 if (identical(lastPair.oldToken, firstPair.oldToken) && | |
| 931 identical(lastPair.newToken, firstPair.newToken)) { | |
| 932 _updateOffset = beginOffsetOld - 1; | |
| 933 _updateEndOld = endOffsetOld; | |
| 934 _updateDelta = newUnit.length - oldUnit.length; | |
| 935 _shiftTokens(firstPair.oldToken, _updateDelta); | |
| 936 IncrementalResolver._updateElementNameOffsets( | |
| 937 oldUnit.element, | |
| 938 _updateOffset, | |
| 939 _updateDelta); | |
| 940 _updateEntry(); | |
| 941 return true; | |
| 942 } | |
| 925 // print('beginOffsetOld: $beginOffsetOld endOffsetOld: $endOffsetOld'); | 943 // print('beginOffsetOld: $beginOffsetOld endOffsetOld: $endOffsetOld'); |
| 926 // print('beginOffsetNew: $beginOffsetNew endOffsetNew: $endOffsetNew'); | 944 // print('beginOffsetNew: $beginOffsetNew endOffsetNew: $endOffsetNew'); |
| 927 // Find nodes covering the "old" and "new" token ranges. | 945 // Find nodes covering the "old" and "new" token ranges. |
| 928 AstNode oldNode = | 946 AstNode oldNode = |
| 929 _findNodeCovering(oldUnit, beginOffsetOld, endOffsetOld); | 947 _findNodeCovering(oldUnit, beginOffsetOld, endOffsetOld); |
| 930 AstNode newNode = | 948 AstNode newNode = |
| 931 _findNodeCovering(newUnit, beginOffsetNew, endOffsetNew); | 949 _findNodeCovering(newUnit, beginOffsetNew, endOffsetNew); |
| 932 // print('oldNode: $oldNode'); | 950 // print('oldNode: $oldNode'); |
| 933 // print('newNode: $newNode'); | 951 // print('newNode: $newNode'); |
| 934 // Try to find the smallest common node, a FunctionBody currently. | 952 // Try to find the smallest common node, a FunctionBody currently. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 990 oldNode.length, | 1008 oldNode.length, |
| 991 newNode.length); | 1009 newNode.length); |
| 992 incrementalResolver.resolve(newNode); | 1010 incrementalResolver.resolve(newNode); |
| 993 _newResolveErrors = incrementalResolver._resolveErrors; | 1011 _newResolveErrors = incrementalResolver._resolveErrors; |
| 994 _newVerifyErrors = incrementalResolver._verifyErrors; | 1012 _newVerifyErrors = incrementalResolver._verifyErrors; |
| 995 _newHints = incrementalResolver._hints; | 1013 _newHints = incrementalResolver._hints; |
| 996 _updateEntry(); | 1014 _updateEntry(); |
| 997 // print('Successfully incrementally resolved.'); | 1015 // print('Successfully incrementally resolved.'); |
| 998 return true; | 1016 return true; |
| 999 } | 1017 } |
| 1000 } catch (e, st) { | 1018 } catch (e) { |
| 1001 // TODO(scheglov) find a way to log these exceptions | 1019 // TODO(scheglov) find a way to log these exceptions |
| 1002 print(e); | 1020 // print(e); |
| 1003 print(st); | 1021 // print(st); |
| 1004 } | 1022 } |
| 1005 return false; | 1023 return false; |
| 1006 } | 1024 } |
| 1007 | 1025 |
| 1008 CompilationUnit _parseUnit(String code) { | 1026 CompilationUnit _parseUnit(String code) { |
| 1009 Token token = _scan(code); | 1027 Token token = _scan(code); |
| 1010 RecordingErrorListener errorListener = new RecordingErrorListener(); | 1028 RecordingErrorListener errorListener = new RecordingErrorListener(); |
| 1011 Parser parser = new Parser(_unitSource, errorListener); | 1029 Parser parser = new Parser(_unitSource, errorListener); |
| 1012 CompilationUnit unit = parser.parseCompilationUnit(token); | 1030 CompilationUnit unit = parser.parseCompilationUnit(token); |
| 1013 _newParseErrors = errorListener.errors; | 1031 _newParseErrors = errorListener.errors; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1100 return null; | 1118 return null; |
| 1101 } | 1119 } |
| 1102 | 1120 |
| 1103 static _TokenPair _findLastDifferentToken(Token oldToken, Token newToken) { | 1121 static _TokenPair _findLastDifferentToken(Token oldToken, Token newToken) { |
| 1104 // print('last ------------'); | 1122 // print('last ------------'); |
| 1105 int delta = newToken.offset - oldToken.offset; | 1123 int delta = newToken.offset - oldToken.offset; |
| 1106 while (oldToken.previous != oldToken && newToken.previous != newToken) { | 1124 while (oldToken.previous != oldToken && newToken.previous != newToken) { |
| 1107 // print('old: $oldToken @ ${oldToken.offset}'); | 1125 // print('old: $oldToken @ ${oldToken.offset}'); |
| 1108 // print('new: $newToken @ ${newToken.offset}'); | 1126 // print('new: $newToken @ ${newToken.offset}'); |
| 1109 if (!_equalToken(oldToken, newToken, delta)) { | 1127 if (!_equalToken(oldToken, newToken, delta)) { |
| 1110 return new _TokenPair(oldToken, newToken); | 1128 return new _TokenPair(oldToken.next, newToken.next); |
| 1111 } | 1129 } |
| 1112 oldToken = oldToken.previous; | 1130 oldToken = oldToken.previous; |
| 1113 newToken = newToken.previous; | 1131 newToken = newToken.previous; |
| 1114 } | 1132 } |
| 1115 return null; | 1133 return null; |
| 1116 } | 1134 } |
| 1117 | 1135 |
| 1118 static AstNode _findNodeCovering(AstNode root, int offset, int end) { | 1136 static AstNode _findNodeCovering(AstNode root, int offset, int end) { |
| 1119 NodeLocator nodeLocator = new NodeLocator.con2(offset, end); | 1137 NodeLocator nodeLocator = new NodeLocator.con2(offset, end); |
| 1120 return nodeLocator.searchWithin(root); | 1138 return nodeLocator.searchWithin(root); |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1437 _elements[node] = node.staticElement; | 1455 _elements[node] = node.staticElement; |
| 1438 } | 1456 } |
| 1439 } | 1457 } |
| 1440 | 1458 |
| 1441 | 1459 |
| 1442 class _TokenPair { | 1460 class _TokenPair { |
| 1443 final Token oldToken; | 1461 final Token oldToken; |
| 1444 final Token newToken; | 1462 final Token newToken; |
| 1445 _TokenPair(this.oldToken, this.newToken); | 1463 _TokenPair(this.oldToken, this.newToken); |
| 1446 } | 1464 } |
| OLD | NEW |