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

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

Issue 901713004: Invalidate hints instead of computing them in the incremental resolver. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 months 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/services/lint.dart'; 10 import 'package:analyzer/src/services/lint.dart';
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 String toString() => name; 780 String toString() => name;
781 } 781 }
782 782
783 783
784 /** 784 /**
785 * Instances of the class [IncrementalResolver] resolve the smallest portion of 785 * Instances of the class [IncrementalResolver] resolve the smallest portion of
786 * an AST structure that we currently know how to resolve. 786 * an AST structure that we currently know how to resolve.
787 */ 787 */
788 class IncrementalResolver { 788 class IncrementalResolver {
789 /** 789 /**
790 * All resolved units of the [_definingLibrary].
791 */
792 final Map<Source, CompilationUnit> _units;
793
794 /**
795 * The element of the compilation unit being resolved. 790 * The element of the compilation unit being resolved.
796 */ 791 */
797 final CompilationUnitElement _definingUnit; 792 final CompilationUnitElement _definingUnit;
798 793
799 /** 794 /**
800 * The context the compilation unit being resolved in. 795 * The context the compilation unit being resolved in.
801 */ 796 */
802 AnalysisContextImpl _context; 797 AnalysisContextImpl _context;
803 798
804 /** 799 /**
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 ResolutionContext _resolutionContext; 842 ResolutionContext _resolutionContext;
848 843
849 List<AnalysisError> _resolveErrors = AnalysisError.NO_ERRORS; 844 List<AnalysisError> _resolveErrors = AnalysisError.NO_ERRORS;
850 List<AnalysisError> _verifyErrors = AnalysisError.NO_ERRORS; 845 List<AnalysisError> _verifyErrors = AnalysisError.NO_ERRORS;
851 List<AnalysisError> _lints = AnalysisError.NO_ERRORS; 846 List<AnalysisError> _lints = AnalysisError.NO_ERRORS;
852 847
853 /** 848 /**
854 * Initialize a newly created incremental resolver to resolve a node in the 849 * Initialize a newly created incremental resolver to resolve a node in the
855 * given source in the given library. 850 * given source in the given library.
856 */ 851 */
857 IncrementalResolver(this._units, this._definingUnit, this._updateOffset, 852 IncrementalResolver(this._definingUnit, this._updateOffset,
858 this._updateEndOld, this._updateEndNew) { 853 this._updateEndOld, this._updateEndNew) {
859 _updateDelta = _updateEndNew - _updateEndOld; 854 _updateDelta = _updateEndNew - _updateEndOld;
860 _definingLibrary = _definingUnit.library; 855 _definingLibrary = _definingUnit.library;
861 _librarySource = _definingLibrary.source; 856 _librarySource = _definingLibrary.source;
862 _source = _definingUnit.source; 857 _source = _definingUnit.source;
863 _context = _definingUnit.context; 858 _context = _definingUnit.context;
864 _typeProvider = _context.typeProvider; 859 _typeProvider = _context.typeProvider;
865 entry = _context.getReadableSourceEntryOrNull(_source); 860 entry = _context.getReadableSourceEntryOrNull(_source);
866 } 861 }
867 862
(...skipping 12 matching lines...) Expand all
880 // update elements 875 // update elements
881 _updateElementNameOffsets(); 876 _updateElementNameOffsets();
882 _buildElements(rootNode); 877 _buildElements(rootNode);
883 if (!_canBeIncrementallyResolved(rootNode)) { 878 if (!_canBeIncrementallyResolved(rootNode)) {
884 return false; 879 return false;
885 } 880 }
886 // resolve 881 // resolve
887 _resolveReferences(rootNode); 882 _resolveReferences(rootNode);
888 // verify 883 // verify
889 _verify(rootNode); 884 _verify(rootNode);
890 _generateHints(rootNode); 885 _context.invalidateLibraryHints(_librarySource);
891 _generateLints(rootNode); 886 _generateLints(rootNode);
892 // update entry errors 887 // update entry errors
893 _updateEntry(); 888 _updateEntry();
894 // OK 889 // OK
895 return true; 890 return true;
896 } finally { 891 } finally {
897 logger.exit(); 892 logger.exit();
898 } 893 }
899 } 894 }
900 895
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 AstNode _findResolutionRoot(AstNode node) { 966 AstNode _findResolutionRoot(AstNode node) {
972 while (node != null) { 967 while (node != null) {
973 if (_canBeResolved(node)) { 968 if (_canBeResolved(node)) {
974 return node; 969 return node;
975 } 970 }
976 node = node.parent; 971 node = node.parent;
977 } 972 }
978 throw new AnalysisException("Cannot resolve node: no resolvable node"); 973 throw new AnalysisException("Cannot resolve node: no resolvable node");
979 } 974 }
980 975
981 void _generateHints(AstNode node) {
982 LoggingTimer timer = logger.startTimer();
983 try {
984 RecordingErrorListener errorListener = new RecordingErrorListener();
985 // prepare a list of the library units
986 List<CompilationUnit> units;
987 {
988 CompilationUnit unit = node.getAncestor((n) => n is CompilationUnit);
989 _units[_source] = unit;
990 units = _units.values.toList();
991 }
992 // run the generator
993 AnalysisContext analysisContext = _definingLibrary.context;
994 HintGenerator hintGenerator =
995 new HintGenerator(units, analysisContext, errorListener);
996 hintGenerator.generateForLibrary();
997 // remember hints
998 for (Source source in _units.keys) {
999 List<AnalysisError> hints = errorListener.getErrorsForSource(source);
1000 DartEntry entry = _context.getReadableSourceEntryOrNull(source);
1001 entry.setValueInLibrary(DartEntry.HINTS, _librarySource, hints);
1002 }
1003 } finally {
1004 timer.stop('generate hints');
1005 }
1006 }
1007
1008 void _generateLints(AstNode node) { 976 void _generateLints(AstNode node) {
1009 LoggingTimer timer = logger.startTimer(); 977 LoggingTimer timer = logger.startTimer();
1010 try { 978 try {
1011 RecordingErrorListener errorListener = new RecordingErrorListener(); 979 RecordingErrorListener errorListener = new RecordingErrorListener();
1012 CompilationUnit unit = node.getAncestor((n) => n is CompilationUnit); 980 CompilationUnit unit = node.getAncestor((n) => n is CompilationUnit);
1013 LintGenerator lintGenerator = 981 LintGenerator lintGenerator =
1014 new LintGenerator(<CompilationUnit>[unit], errorListener); 982 new LintGenerator(<CompilationUnit>[unit], errorListener);
1015 lintGenerator.generate(); 983 lintGenerator.generate();
1016 _lints = errorListener.getErrorsForSource(_source); 984 _lints = errorListener.getErrorsForSource(_source);
1017 } finally { 985 } finally {
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1182 _verifyErrors = errorListener.getErrorsForSource(_source); 1150 _verifyErrors = errorListener.getErrorsForSource(_source);
1183 } finally { 1151 } finally {
1184 timer.stop('verify'); 1152 timer.stop('verify');
1185 } 1153 }
1186 } 1154 }
1187 } 1155 }
1188 1156
1189 1157
1190 class PoorMansIncrementalResolver { 1158 class PoorMansIncrementalResolver {
1191 final TypeProvider _typeProvider; 1159 final TypeProvider _typeProvider;
1192 final Map<Source, CompilationUnit> _units;
1193 final Source _unitSource; 1160 final Source _unitSource;
1194 final DartEntry _entry; 1161 final DartEntry _entry;
1162 final CompilationUnit _oldUnit;
1195 CompilationUnitElement _unitElement; 1163 CompilationUnitElement _unitElement;
1196 1164
1197 int _updateOffset; 1165 int _updateOffset;
1198 int _updateDelta; 1166 int _updateDelta;
1199 int _updateEndOld; 1167 int _updateEndOld;
1200 int _updateEndNew; 1168 int _updateEndNew;
1201 1169
1202 List<AnalysisError> _newScanErrors = <AnalysisError>[]; 1170 List<AnalysisError> _newScanErrors = <AnalysisError>[];
1203 List<AnalysisError> _newParseErrors = <AnalysisError>[]; 1171 List<AnalysisError> _newParseErrors = <AnalysisError>[];
1204 1172
1205 PoorMansIncrementalResolver(this._typeProvider, this._units, this._unitSource, 1173 PoorMansIncrementalResolver(this._typeProvider, this._unitSource,
1206 this._entry, bool resolveApiChanges) { 1174 this._entry, this._oldUnit, bool resolveApiChanges) {
1207 _resolveApiChanges = resolveApiChanges; 1175 _resolveApiChanges = resolveApiChanges;
1208 } 1176 }
1209 1177
1210 /** 1178 /**
1211 * Attempts to update [oldUnit] to the state corresponding to [newCode]. 1179 * Attempts to update [_oldUnit] to the state corresponding to [newCode].
1212 * Returns `true` if success, or `false` otherwise. 1180 * Returns `true` if success, or `false` otherwise.
1213 * The [oldUnit] might be damaged. 1181 * The [_oldUnit] might be damaged.
1214 */ 1182 */
1215 bool resolve(String newCode) { 1183 bool resolve(String newCode) {
1216 logger.enter('diff/resolve $_unitSource'); 1184 logger.enter('diff/resolve $_unitSource');
1217 try { 1185 try {
1218 // prepare old unit 1186 // prepare old unit
1219 CompilationUnit oldUnit = _units[_unitSource]; 1187 if (!_areCurlyBracketsBalanced(_oldUnit.beginToken)) {
1220 if (!_areCurlyBracketsBalanced(oldUnit.beginToken)) {
1221 logger.log('Unbalanced number of curly brackets in the old unit.'); 1188 logger.log('Unbalanced number of curly brackets in the old unit.');
1222 return false; 1189 return false;
1223 } 1190 }
1224 _unitElement = oldUnit.element; 1191 _unitElement = _oldUnit.element;
1225 // prepare new unit 1192 // prepare new unit
1226 CompilationUnit newUnit = _parseUnit(newCode); 1193 CompilationUnit newUnit = _parseUnit(newCode);
1227 if (!_areCurlyBracketsBalanced(newUnit.beginToken)) { 1194 if (!_areCurlyBracketsBalanced(newUnit.beginToken)) {
1228 logger.log('Unbalanced number of curly brackets in the new unit.'); 1195 logger.log('Unbalanced number of curly brackets in the new unit.');
1229 return false; 1196 return false;
1230 } 1197 }
1231 // find difference 1198 // find difference
1232 _TokenPair firstPair = 1199 _TokenPair firstPair =
1233 _findFirstDifferentToken(oldUnit.beginToken, newUnit.beginToken); 1200 _findFirstDifferentToken(_oldUnit.beginToken, newUnit.beginToken);
1234 _TokenPair lastPair = 1201 _TokenPair lastPair =
1235 _findLastDifferentToken(oldUnit.endToken, newUnit.endToken); 1202 _findLastDifferentToken(_oldUnit.endToken, newUnit.endToken);
1236 if (firstPair != null && lastPair != null) { 1203 if (firstPair != null && lastPair != null) {
1237 int firstOffsetOld = firstPair.oldToken.offset; 1204 int firstOffsetOld = firstPair.oldToken.offset;
1238 int firstOffsetNew = firstPair.newToken.offset; 1205 int firstOffsetNew = firstPair.newToken.offset;
1239 int lastOffsetOld = lastPair.oldToken.end; 1206 int lastOffsetOld = lastPair.oldToken.end;
1240 int lastOffsetNew = lastPair.newToken.end; 1207 int lastOffsetNew = lastPair.newToken.end;
1241 int beginOffsetOld = math.min(firstOffsetOld, lastOffsetOld); 1208 int beginOffsetOld = math.min(firstOffsetOld, lastOffsetOld);
1242 int endOffsetOld = math.max(firstOffsetOld, lastOffsetOld); 1209 int endOffsetOld = math.max(firstOffsetOld, lastOffsetOld);
1243 int beginOffsetNew = math.min(firstOffsetNew, lastOffsetNew); 1210 int beginOffsetNew = math.min(firstOffsetNew, lastOffsetNew);
1244 int endOffsetNew = math.max(firstOffsetNew, lastOffsetNew); 1211 int endOffsetNew = math.max(firstOffsetNew, lastOffsetNew);
1245 // check for a whitespace only change 1212 // check for a whitespace only change
1246 if (identical(lastPair.oldToken, firstPair.oldToken) && 1213 if (identical(lastPair.oldToken, firstPair.oldToken) &&
1247 identical(lastPair.newToken, firstPair.newToken)) { 1214 identical(lastPair.newToken, firstPair.newToken)) {
1248 _updateOffset = beginOffsetOld - 1; 1215 _updateOffset = beginOffsetOld - 1;
1249 _updateEndOld = endOffsetOld; 1216 _updateEndOld = endOffsetOld;
1250 _updateEndNew = endOffsetNew; 1217 _updateEndNew = endOffsetNew;
1251 _updateDelta = newUnit.length - oldUnit.length; 1218 _updateDelta = newUnit.length - _oldUnit.length;
1252 // A Dart documentation comment change. 1219 // A Dart documentation comment change.
1253 if (firstPair.kind == _TokenDifferenceKind.COMMENT_DOC) { 1220 if (firstPair.kind == _TokenDifferenceKind.COMMENT_DOC) {
1254 bool success = _resolveComment(oldUnit, newUnit, firstPair); 1221 bool success = _resolveComment(_oldUnit, newUnit, firstPair);
1255 logger.log('Documentation comment resolved: $success'); 1222 logger.log('Documentation comment resolved: $success');
1256 return success; 1223 return success;
1257 } 1224 }
1258 // A pure whitespace change. 1225 // A pure whitespace change.
1259 if (firstPair.kind == _TokenDifferenceKind.OFFSET) { 1226 if (firstPair.kind == _TokenDifferenceKind.OFFSET) {
1260 logger.log('Whitespace change.'); 1227 logger.log('Whitespace change.');
1261 _shiftTokens(firstPair.oldToken); 1228 _shiftTokens(firstPair.oldToken);
1262 { 1229 {
1263 IncrementalResolver incrementalResolver = new IncrementalResolver( 1230 IncrementalResolver incrementalResolver = new IncrementalResolver(
1264 _units,
1265 _unitElement, 1231 _unitElement,
1266 _updateOffset, 1232 _updateOffset,
1267 _updateEndOld, 1233 _updateEndOld,
1268 _updateEndNew); 1234 _updateEndNew);
1269 incrementalResolver._updateElementNameOffsets(); 1235 incrementalResolver._updateElementNameOffsets();
1270 incrementalResolver._shiftEntryErrors(); 1236 incrementalResolver._shiftEntryErrors();
1271 } 1237 }
1272 _updateEntry(); 1238 _updateEntry();
1273 logger.log('Success.'); 1239 logger.log('Success.');
1274 return true; 1240 return true;
1275 } 1241 }
1276 // fall-through, end-of-line comment 1242 // fall-through, end-of-line comment
1277 } 1243 }
1278 // Find nodes covering the "old" and "new" token ranges. 1244 // Find nodes covering the "old" and "new" token ranges.
1279 AstNode oldNode = 1245 AstNode oldNode =
1280 _findNodeCovering(oldUnit, beginOffsetOld, endOffsetOld); 1246 _findNodeCovering(_oldUnit, beginOffsetOld, endOffsetOld);
1281 AstNode newNode = 1247 AstNode newNode =
1282 _findNodeCovering(newUnit, beginOffsetNew, endOffsetNew); 1248 _findNodeCovering(newUnit, beginOffsetNew, endOffsetNew);
1283 logger.log(() => 'oldNode: $oldNode'); 1249 logger.log(() => 'oldNode: $oldNode');
1284 logger.log(() => 'newNode: $newNode'); 1250 logger.log(() => 'newNode: $newNode');
1285 // Try to find the smallest common node, a FunctionBody currently. 1251 // Try to find the smallest common node, a FunctionBody currently.
1286 { 1252 {
1287 List<AstNode> oldParents = _getParents(oldNode); 1253 List<AstNode> oldParents = _getParents(oldNode);
1288 List<AstNode> newParents = _getParents(newNode); 1254 List<AstNode> newParents = _getParents(newNode);
1289 int length = math.min(oldParents.length, newParents.length); 1255 int length = math.min(oldParents.length, newParents.length);
1290 bool found = false; 1256 bool found = false;
(...skipping 27 matching lines...) Expand all
1318 _updateEndOld = oldNode.end; 1284 _updateEndOld = oldNode.end;
1319 _updateEndNew = newNode.end; 1285 _updateEndNew = newNode.end;
1320 _updateDelta = _updateEndNew - _updateEndOld; 1286 _updateDelta = _updateEndNew - _updateEndOld;
1321 // replace node 1287 // replace node
1322 NodeReplacer.replace(oldNode, newNode); 1288 NodeReplacer.replace(oldNode, newNode);
1323 // update token references 1289 // update token references
1324 { 1290 {
1325 Token oldBeginToken = _getBeginTokenNotComment(oldNode); 1291 Token oldBeginToken = _getBeginTokenNotComment(oldNode);
1326 Token newBeginToken = _getBeginTokenNotComment(newNode); 1292 Token newBeginToken = _getBeginTokenNotComment(newNode);
1327 if (oldBeginToken.previous.type == TokenType.EOF) { 1293 if (oldBeginToken.previous.type == TokenType.EOF) {
1328 oldUnit.beginToken = newBeginToken; 1294 _oldUnit.beginToken = newBeginToken;
1329 } else { 1295 } else {
1330 oldBeginToken.previous.setNext(newBeginToken); 1296 oldBeginToken.previous.setNext(newBeginToken);
1331 } 1297 }
1332 newNode.endToken.setNext(oldNode.endToken.next); 1298 newNode.endToken.setNext(oldNode.endToken.next);
1333 _shiftTokens(oldNode.endToken.next); 1299 _shiftTokens(oldNode.endToken.next);
1334 } 1300 }
1335 // perform incremental resolution 1301 // perform incremental resolution
1336 IncrementalResolver incrementalResolver = new IncrementalResolver( 1302 IncrementalResolver incrementalResolver = new IncrementalResolver(
1337 _units,
1338 _unitElement, 1303 _unitElement,
1339 _updateOffset, 1304 _updateOffset,
1340 _updateEndOld, 1305 _updateEndOld,
1341 _updateEndNew); 1306 _updateEndNew);
1342 bool success = incrementalResolver.resolve(newNode); 1307 bool success = incrementalResolver.resolve(newNode);
1343 // check if success 1308 // check if success
1344 if (!success) { 1309 if (!success) {
1345 logger.log('Failure: element model changed.'); 1310 logger.log('Failure: element model changed.');
1346 return false; 1311 return false;
1347 } 1312 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1395 logger.log('oldComment.beginToken: ${oldComment.beginToken}'); 1360 logger.log('oldComment.beginToken: ${oldComment.beginToken}');
1396 logger.log('newComment.beginToken: ${newComment.beginToken}'); 1361 logger.log('newComment.beginToken: ${newComment.beginToken}');
1397 _updateOffset = oldToken.offset - 1; 1362 _updateOffset = oldToken.offset - 1;
1398 // update token references 1363 // update token references
1399 _shiftTokens(firstPair.oldToken); 1364 _shiftTokens(firstPair.oldToken);
1400 _setPrecedingComments(oldToken, newComment.tokens.first); 1365 _setPrecedingComments(oldToken, newComment.tokens.first);
1401 // replace node 1366 // replace node
1402 NodeReplacer.replace(oldComment, newComment); 1367 NodeReplacer.replace(oldComment, newComment);
1403 // update elements 1368 // update elements
1404 IncrementalResolver incrementalResolver = new IncrementalResolver( 1369 IncrementalResolver incrementalResolver = new IncrementalResolver(
1405 _units,
1406 _unitElement, 1370 _unitElement,
1407 _updateOffset, 1371 _updateOffset,
1408 _updateEndOld, 1372 _updateEndOld,
1409 _updateEndNew); 1373 _updateEndNew);
1410 incrementalResolver._updateElementNameOffsets(); 1374 incrementalResolver._updateElementNameOffsets();
1411 incrementalResolver._shiftEntryErrors(); 1375 incrementalResolver._shiftEntryErrors();
1412 _updateEntry(); 1376 _updateEntry();
1413 // resolve references in the comment 1377 // resolve references in the comment
1414 incrementalResolver._resolveReferences(newComment); 1378 incrementalResolver._resolveReferences(newComment);
1415 // OK 1379 // OK
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
1871 String toString() => name; 1835 String toString() => name;
1872 } 1836 }
1873 1837
1874 1838
1875 class _TokenPair { 1839 class _TokenPair {
1876 final _TokenDifferenceKind kind; 1840 final _TokenDifferenceKind kind;
1877 final Token oldToken; 1841 final Token oldToken;
1878 final Token newToken; 1842 final Token newToken;
1879 _TokenPair(this.kind, this.oldToken, this.newToken); 1843 _TokenPair(this.kind, this.oldToken, this.newToken);
1880 } 1844 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698