| 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/services/lint.dart'; | 10 import 'package:analyzer/src/services/lint.dart'; |
| (...skipping 1171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1182 int endOffsetOld = math.max(firstOffsetOld, lastOffsetOld); | 1182 int endOffsetOld = math.max(firstOffsetOld, lastOffsetOld); |
| 1183 int beginOffsetNew = math.min(firstOffsetNew, lastOffsetNew); | 1183 int beginOffsetNew = math.min(firstOffsetNew, lastOffsetNew); |
| 1184 int endOffsetNew = math.max(firstOffsetNew, lastOffsetNew); | 1184 int endOffsetNew = math.max(firstOffsetNew, lastOffsetNew); |
| 1185 // check for a whitespace only change | 1185 // check for a whitespace only change |
| 1186 if (identical(lastPair.oldToken, firstPair.oldToken) && | 1186 if (identical(lastPair.oldToken, firstPair.oldToken) && |
| 1187 identical(lastPair.newToken, firstPair.newToken)) { | 1187 identical(lastPair.newToken, firstPair.newToken)) { |
| 1188 _updateOffset = beginOffsetOld - 1; | 1188 _updateOffset = beginOffsetOld - 1; |
| 1189 _updateEndOld = endOffsetOld; | 1189 _updateEndOld = endOffsetOld; |
| 1190 _updateEndNew = endOffsetNew; | 1190 _updateEndNew = endOffsetNew; |
| 1191 _updateDelta = newUnit.length - _oldUnit.length; | 1191 _updateDelta = newUnit.length - _oldUnit.length; |
| 1192 // A comment change. |
| 1193 if (firstPair.kind == _TokenDifferenceKind.COMMENT) { |
| 1194 bool success = _resolveComment(newUnit, firstPair); |
| 1195 logger.log('Comment change: $success'); |
| 1196 return success; |
| 1197 } |
| 1192 // A Dart documentation comment change. | 1198 // A Dart documentation comment change. |
| 1193 if (firstPair.kind == _TokenDifferenceKind.COMMENT_DOC) { | 1199 if (firstPair.kind == _TokenDifferenceKind.COMMENT_DOC) { |
| 1194 bool success = _resolveComment(_oldUnit, newUnit, firstPair); | 1200 bool success = _resolveCommentDoc(newUnit, firstPair); |
| 1195 logger.log('Documentation comment resolved: $success'); | 1201 logger.log('Documentation comment resolved: $success'); |
| 1196 return success; | 1202 return success; |
| 1197 } | 1203 } |
| 1198 // A pure whitespace change. | 1204 // A pure whitespace change. |
| 1199 if (firstPair.kind == _TokenDifferenceKind.OFFSET) { | 1205 if (firstPair.kind == _TokenDifferenceKind.OFFSET) { |
| 1200 logger.log('Whitespace change.'); | 1206 logger.log('Whitespace change.'); |
| 1201 _shiftTokens(firstPair.oldToken); | 1207 _shiftTokens(firstPair.oldToken); |
| 1202 { | 1208 { |
| 1203 IncrementalResolver incrementalResolver = new IncrementalResolver( | 1209 IncrementalResolver incrementalResolver = new IncrementalResolver( |
| 1204 _unitElement, _updateOffset, _updateEndOld, _updateEndNew); | 1210 _unitElement, _updateOffset, _updateEndOld, _updateEndNew); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1302 Parser parser = new Parser(_unitSource, errorListener); | 1308 Parser parser = new Parser(_unitSource, errorListener); |
| 1303 CompilationUnit unit = parser.parseCompilationUnit(token); | 1309 CompilationUnit unit = parser.parseCompilationUnit(token); |
| 1304 _newParseErrors = errorListener.errors; | 1310 _newParseErrors = errorListener.errors; |
| 1305 return unit; | 1311 return unit; |
| 1306 } finally { | 1312 } finally { |
| 1307 timer.stop('parse'); | 1313 timer.stop('parse'); |
| 1308 } | 1314 } |
| 1309 } | 1315 } |
| 1310 | 1316 |
| 1311 /** | 1317 /** |
| 1318 * Attempts to resolve a comment change. |
| 1319 * Returns `true` if success. |
| 1320 */ |
| 1321 bool _resolveComment(CompilationUnit newUnit, _TokenPair firstPair) { |
| 1322 Token oldToken = firstPair.oldToken; |
| 1323 Token newToken = firstPair.newToken; |
| 1324 CommentToken newComments = newToken.precedingComments; |
| 1325 // update token references |
| 1326 _updateOffset = oldToken.offset - 1; |
| 1327 _shiftTokens(firstPair.oldToken); |
| 1328 _setPrecedingComments(oldToken, newComments); |
| 1329 // update elements |
| 1330 IncrementalResolver incrementalResolver = new IncrementalResolver( |
| 1331 _unitElement, _updateOffset, _updateEndOld, _updateEndNew); |
| 1332 incrementalResolver._updateElementNameOffsets(); |
| 1333 incrementalResolver._shiftEntryErrors(); |
| 1334 _updateEntry(); |
| 1335 // OK |
| 1336 return true; |
| 1337 } |
| 1338 |
| 1339 /** |
| 1312 * Attempts to resolve a documentation comment change. | 1340 * Attempts to resolve a documentation comment change. |
| 1313 * Returns `true` if success. | 1341 * Returns `true` if success. |
| 1314 */ | 1342 */ |
| 1315 bool _resolveComment( | 1343 bool _resolveCommentDoc(CompilationUnit newUnit, _TokenPair firstPair) { |
| 1316 CompilationUnit oldUnit, CompilationUnit newUnit, _TokenPair firstPair) { | |
| 1317 Token oldToken = firstPair.oldToken; | 1344 Token oldToken = firstPair.oldToken; |
| 1318 Token newToken = firstPair.newToken; | 1345 Token newToken = firstPair.newToken; |
| 1319 CommentToken oldComments = oldToken.precedingComments; | 1346 CommentToken oldComments = oldToken.precedingComments; |
| 1320 CommentToken newComments = newToken.precedingComments; | 1347 CommentToken newComments = newToken.precedingComments; |
| 1321 if (oldComments == null || newComments == null) { | 1348 if (oldComments == null || newComments == null) { |
| 1322 return false; | 1349 return false; |
| 1323 } | 1350 } |
| 1324 // find nodes | 1351 // find nodes |
| 1325 int offset = oldComments.offset; | 1352 int offset = oldComments.offset; |
| 1326 logger.log('offset: $offset'); | 1353 logger.log('offset: $offset'); |
| 1327 Comment oldComment = _findNodeCovering(oldUnit, offset, offset); | 1354 Comment oldComment = _findNodeCovering(_oldUnit, offset, offset); |
| 1328 Comment newComment = _findNodeCovering(newUnit, offset, offset); | 1355 Comment newComment = _findNodeCovering(newUnit, offset, offset); |
| 1329 logger.log('oldComment.beginToken: ${oldComment.beginToken}'); | 1356 logger.log('oldComment.beginToken: ${oldComment.beginToken}'); |
| 1330 logger.log('newComment.beginToken: ${newComment.beginToken}'); | 1357 logger.log('newComment.beginToken: ${newComment.beginToken}'); |
| 1331 _updateOffset = oldToken.offset - 1; | 1358 _updateOffset = oldToken.offset - 1; |
| 1332 // update token references | 1359 // update token references |
| 1333 _shiftTokens(firstPair.oldToken); | 1360 _shiftTokens(firstPair.oldToken); |
| 1334 _setPrecedingComments(oldToken, newComment.tokens.first); | 1361 _setPrecedingComments(oldToken, newComment.tokens.first); |
| 1335 // replace node | 1362 // replace node |
| 1336 NodeReplacer.replace(oldComment, newComment); | 1363 NodeReplacer.replace(oldComment, newComment); |
| 1337 // update elements | 1364 // update elements |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1348 | 1375 |
| 1349 Token _scan(String code) { | 1376 Token _scan(String code) { |
| 1350 RecordingErrorListener errorListener = new RecordingErrorListener(); | 1377 RecordingErrorListener errorListener = new RecordingErrorListener(); |
| 1351 CharSequenceReader reader = new CharSequenceReader(code); | 1378 CharSequenceReader reader = new CharSequenceReader(code); |
| 1352 Scanner scanner = new Scanner(_unitSource, reader, errorListener); | 1379 Scanner scanner = new Scanner(_unitSource, reader, errorListener); |
| 1353 Token token = scanner.tokenize(); | 1380 Token token = scanner.tokenize(); |
| 1354 _newScanErrors = errorListener.errors; | 1381 _newScanErrors = errorListener.errors; |
| 1355 return token; | 1382 return token; |
| 1356 } | 1383 } |
| 1357 | 1384 |
| 1385 /** |
| 1386 * Set the given [comment] as a "precedingComments" for [token]. |
| 1387 */ |
| 1388 void _setPrecedingComments(Token token, CommentToken comment) { |
| 1389 if (token is BeginTokenWithComment) { |
| 1390 token.precedingComments = comment; |
| 1391 } else if (token is KeywordTokenWithComment) { |
| 1392 token.precedingComments = comment; |
| 1393 } else if (token is KeywordToken) { |
| 1394 KeywordTokenWithComment newToken = |
| 1395 new KeywordTokenWithComment(token.keyword, token.offset, comment); |
| 1396 token.previous.setNext(newToken); |
| 1397 newToken.setNext(token.next); |
| 1398 if (_oldUnit.beginToken == token) { |
| 1399 _oldUnit.beginToken = newToken; |
| 1400 } |
| 1401 } else if (token is StringTokenWithComment) { |
| 1402 token.precedingComments = comment; |
| 1403 } else if (token is StringToken) { |
| 1404 StringTokenWithComment newToken = new StringTokenWithComment( |
| 1405 token.type, token.value(), token.offset, comment); |
| 1406 token.previous.setNext(newToken); |
| 1407 newToken.setNext(token.next); |
| 1408 if (_oldUnit.beginToken == token) { |
| 1409 _oldUnit.beginToken = newToken; |
| 1410 } |
| 1411 } else if (token is TokenWithComment) { |
| 1412 token.precedingComments = comment; |
| 1413 } else { |
| 1414 Type parentType = token != null ? token.runtimeType : null; |
| 1415 throw new AnalysisException('Uknown parent token type: $parentType'); |
| 1416 } |
| 1417 } |
| 1418 |
| 1358 void _shiftTokens(Token token) { | 1419 void _shiftTokens(Token token) { |
| 1359 while (token != null) { | 1420 while (token != null) { |
| 1360 if (token.offset > _updateOffset) { | 1421 if (token.offset > _updateOffset) { |
| 1361 token.offset += _updateDelta; | 1422 token.offset += _updateDelta; |
| 1362 } | 1423 } |
| 1363 // comments | 1424 // comments |
| 1364 _shiftTokens(token.precedingComments); | 1425 _shiftTokens(token.precedingComments); |
| 1365 if (token is DocumentationCommentToken) { | 1426 if (token is DocumentationCommentToken) { |
| 1366 for (Token reference in token.references) { | 1427 for (Token reference in token.references) { |
| 1367 _shiftTokens(reference); | 1428 _shiftTokens(reference); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1511 static int _getTokenCount(Token token, TokenType type) { | 1572 static int _getTokenCount(Token token, TokenType type) { |
| 1512 int count = 0; | 1573 int count = 0; |
| 1513 while (token.type != TokenType.EOF) { | 1574 while (token.type != TokenType.EOF) { |
| 1514 if (token.type == type) { | 1575 if (token.type == type) { |
| 1515 count++; | 1576 count++; |
| 1516 } | 1577 } |
| 1517 token = token.next; | 1578 token = token.next; |
| 1518 } | 1579 } |
| 1519 return count; | 1580 return count; |
| 1520 } | 1581 } |
| 1521 | |
| 1522 /** | |
| 1523 * Set the given [comment] as a "precedingComments" for [parent]. | |
| 1524 */ | |
| 1525 static void _setPrecedingComments(Token parent, CommentToken comment) { | |
| 1526 if (parent is BeginTokenWithComment) { | |
| 1527 parent.precedingComments = comment; | |
| 1528 } else if (parent is KeywordTokenWithComment) { | |
| 1529 parent.precedingComments = comment; | |
| 1530 } else if (parent is StringTokenWithComment) { | |
| 1531 parent.precedingComments = comment; | |
| 1532 } else if (parent is TokenWithComment) { | |
| 1533 parent.precedingComments = comment; | |
| 1534 } else { | |
| 1535 Type parentType = parent != null ? parent.runtimeType : null; | |
| 1536 throw new AnalysisException('Uknown parent token type: $parentType'); | |
| 1537 } | |
| 1538 } | |
| 1539 } | 1582 } |
| 1540 | 1583 |
| 1541 /** | 1584 /** |
| 1542 * The context to resolve an [AstNode] in. | 1585 * The context to resolve an [AstNode] in. |
| 1543 */ | 1586 */ |
| 1544 class ResolutionContext { | 1587 class ResolutionContext { |
| 1545 CompilationUnitElement enclosingUnit; | 1588 CompilationUnitElement enclosingUnit; |
| 1546 ClassDeclaration enclosingClassDeclaration; | 1589 ClassDeclaration enclosingClassDeclaration; |
| 1547 ClassElement enclosingClass; | 1590 ClassElement enclosingClass; |
| 1548 Scope scope; | 1591 Scope scope; |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1799 @override | 1842 @override |
| 1800 String toString() => name; | 1843 String toString() => name; |
| 1801 } | 1844 } |
| 1802 | 1845 |
| 1803 class _TokenPair { | 1846 class _TokenPair { |
| 1804 final _TokenDifferenceKind kind; | 1847 final _TokenDifferenceKind kind; |
| 1805 final Token oldToken; | 1848 final Token oldToken; |
| 1806 final Token newToken; | 1849 final Token newToken; |
| 1807 _TokenPair(this.kind, this.oldToken, this.newToken); | 1850 _TokenPair(this.kind, this.oldToken, this.newToken); |
| 1808 } | 1851 } |
| OLD | NEW |