| 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 881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 * The [oldUnit] might be damaged. | 892 * The [oldUnit] might be damaged. |
| 893 */ | 893 */ |
| 894 bool resolve(CompilationUnit oldUnit, String newCode) { | 894 bool resolve(CompilationUnit oldUnit, String newCode) { |
| 895 try { | 895 try { |
| 896 CompilationUnit newUnit = _parseUnit(newCode); | 896 CompilationUnit newUnit = _parseUnit(newCode); |
| 897 _TokenPair firstPair = | 897 _TokenPair firstPair = |
| 898 _findFirstDifferentToken(oldUnit.beginToken, newUnit.beginToken); | 898 _findFirstDifferentToken(oldUnit.beginToken, newUnit.beginToken); |
| 899 _TokenPair lastPair = | 899 _TokenPair lastPair = |
| 900 _findLastDifferentToken(oldUnit.endToken, newUnit.endToken); | 900 _findLastDifferentToken(oldUnit.endToken, newUnit.endToken); |
| 901 if (firstPair != null && lastPair != null) { | 901 if (firstPair != null && lastPair != null) { |
| 902 // Prepare the "old" token range. | 902 int firstOffsetOld = firstPair.oldToken.offset; |
| 903 Token oldBeginToken; | 903 int firstOffsetNew = firstPair.newToken.offset; |
| 904 Token oldEndToken; | 904 int lastOffsetOld = lastPair.oldToken.end; |
| 905 if (firstPair.oldToken.offset < lastPair.oldToken.offset) { | 905 int lastOffsetNew = lastPair.newToken.end; |
| 906 oldBeginToken = firstPair.oldToken; | 906 int beginOffsetOld = math.min(firstOffsetOld, lastOffsetOld); |
| 907 oldEndToken = lastPair.oldToken; | 907 int endOffsetOld = math.max(firstOffsetOld, lastOffsetOld); |
| 908 } else { | 908 int beginOffsetNew = math.min(firstOffsetNew, lastOffsetNew); |
| 909 oldBeginToken = lastPair.oldToken; | 909 int endOffsetNew = math.max(firstOffsetNew, lastOffsetNew); |
| 910 oldEndToken = firstPair.oldToken; | 910 // print('beginOffsetOld: $beginOffsetOld endOffsetOld: $endOffsetOld'); |
| 911 } | 911 // print('beginOffsetNew: $beginOffsetNew endOffsetNew: $endOffsetNew'); |
| 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. | 912 // Find nodes covering the "old" and "new" token ranges. |
| 923 AstNode oldNode = | 913 AstNode oldNode = |
| 924 _findNodeWithTokens(oldUnit, oldBeginToken, oldEndToken); | 914 _findNodeCovering(oldUnit, beginOffsetOld, endOffsetOld); |
| 925 AstNode newNode = | 915 AstNode newNode = |
| 926 _findNodeWithTokens(newUnit, newBeginToken, newEndToken); | 916 _findNodeCovering(newUnit, beginOffsetNew, endOffsetNew); |
| 917 // print('oldNode: $oldNode'); |
| 918 // print('newNode: $newNode'); |
| 927 // Try to find the smallest common node, a FunctionBody currently. | 919 // Try to find the smallest common node, a FunctionBody currently. |
| 928 { | 920 { |
| 929 List<AstNode> oldParents = _getParents(oldNode); | 921 List<AstNode> oldParents = _getParents(oldNode); |
| 930 List<AstNode> newParents = _getParents(newNode); | 922 List<AstNode> newParents = _getParents(newNode); |
| 931 int length = math.min(oldParents.length, newParents.length); | 923 int length = math.min(oldParents.length, newParents.length); |
| 932 bool found = false; | 924 bool found = false; |
| 933 for (int i = 0; i < length; i++) { | 925 for (int i = 0; i < length; i++) { |
| 934 AstNode oldParent = oldParents[i]; | 926 AstNode oldParent = oldParents[i]; |
| 935 AstNode newParent = newParents[i]; | 927 AstNode newParent = newParents[i]; |
| 936 if (oldParent is FunctionBody && newParent is FunctionBody) { | 928 if (oldParent is FunctionBody && newParent is FunctionBody) { |
| 937 oldNode = oldParent; | 929 oldNode = oldParent; |
| 938 newNode = newParent; | 930 newNode = newParent; |
| 939 found = true; | 931 found = true; |
| 940 break; | 932 break; |
| 941 } | 933 } |
| 942 } | 934 } |
| 943 if (!found) { | 935 if (!found) { |
| 944 return false; | 936 return false; |
| 945 } | 937 } |
| 946 } | 938 } |
| 939 // prepare update range |
| 940 _updateOffset = oldNode.offset; |
| 941 _updateEndOld = oldNode.end; |
| 942 _updateEndNew = newNode.end; |
| 943 _updateDelta = _updateEndNew - _updateEndOld; |
| 944 // _updateDelta = lastPair.delta; |
| 947 // replace node | 945 // replace node |
| 948 NodeReplacer.replace(oldNode, newNode); | 946 NodeReplacer.replace(oldNode, newNode); |
| 949 // update token references | 947 // update token references |
| 950 oldNode.beginToken.previous.setNext(newNode.beginToken); | 948 oldNode.beginToken.previous.setNext(newNode.beginToken); |
| 951 oldNode.endToken.setNext(oldNode.endToken.next); | 949 newNode.endToken.setNext(oldNode.endToken.next); |
| 952 // prepare update range | 950 _shiftTokens(oldNode.endToken.next, _updateDelta); |
| 953 _updateOffset = oldNode.offset; | |
| 954 _updateDelta = lastPair.delta; | |
| 955 _updateEndOld = oldNode.end; | |
| 956 _updateEndNew = newNode.end; | |
| 957 // perform incremental resolution | 951 // perform incremental resolution |
| 958 CompilationUnitElement oldUnitElement = oldUnit.element; | 952 CompilationUnitElement oldUnitElement = oldUnit.element; |
| 959 IncrementalResolver incrementalResolver = new IncrementalResolver( | 953 IncrementalResolver incrementalResolver = new IncrementalResolver( |
| 960 _typeProvider, | 954 _typeProvider, |
| 961 oldUnitElement.library, | 955 oldUnitElement.library, |
| 962 oldUnitElement, | 956 oldUnitElement, |
| 963 oldUnitElement.source, | 957 oldUnitElement.source, |
| 964 _updateOffset, | 958 _updateOffset, |
| 965 oldNode.length, | 959 oldNode.length, |
| 966 newNode.length + _updateDelta); | 960 newNode.length); |
| 967 incrementalResolver.resolve(newNode); | 961 incrementalResolver.resolve(newNode); |
| 968 _newResolveErrors = incrementalResolver._resolveErrors; | 962 _newResolveErrors = incrementalResolver._resolveErrors; |
| 969 _newVerifyErrors = incrementalResolver._verifyErrors; | 963 _newVerifyErrors = incrementalResolver._verifyErrors; |
| 970 _newHints = incrementalResolver._hints; | 964 _newHints = incrementalResolver._hints; |
| 971 _updateEntry(); | 965 _updateEntry(); |
| 972 return true; | 966 return true; |
| 973 } | 967 } |
| 974 } catch (e, st) { | 968 } catch (e, st) { |
| 975 // TODO(scheglov) find a way to log these exceptions | 969 // TODO(scheglov) find a way to log these exceptions |
| 976 print(e); | 970 print(e); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1054 if (oldToken.type != newToken.type) { | 1048 if (oldToken.type != newToken.type) { |
| 1055 return false; | 1049 return false; |
| 1056 } | 1050 } |
| 1057 if (newToken.offset - oldToken.offset != delta) { | 1051 if (newToken.offset - oldToken.offset != delta) { |
| 1058 return false; | 1052 return false; |
| 1059 } | 1053 } |
| 1060 return oldToken.lexeme == newToken.lexeme; | 1054 return oldToken.lexeme == newToken.lexeme; |
| 1061 } | 1055 } |
| 1062 | 1056 |
| 1063 static _TokenPair _findFirstDifferentToken(Token oldToken, Token newToken) { | 1057 static _TokenPair _findFirstDifferentToken(Token oldToken, Token newToken) { |
| 1064 // print('first ------------'); | 1058 // print('first ------------'); |
| 1065 while (oldToken.type != TokenType.EOF && newToken.type != TokenType.EOF) { | 1059 while (oldToken.type != TokenType.EOF && newToken.type != TokenType.EOF) { |
| 1066 // print('old: $oldToken @ ${oldToken.offset}'); | 1060 // print('old: $oldToken @ ${oldToken.offset}'); |
| 1067 // print('new: $newToken @ ${newToken.offset}'); | 1061 // print('new: $newToken @ ${newToken.offset}'); |
| 1068 if (!_equalToken(oldToken, newToken, 0)) { | 1062 if (!_equalToken(oldToken, newToken, 0)) { |
| 1069 return new _TokenPair(oldToken, newToken, 0); | 1063 return new _TokenPair(oldToken, newToken); |
| 1070 } | 1064 } |
| 1071 oldToken = oldToken.next; | 1065 oldToken = oldToken.next; |
| 1072 newToken = newToken.next; | 1066 newToken = newToken.next; |
| 1073 } | 1067 } |
| 1074 return null; | 1068 return null; |
| 1075 } | 1069 } |
| 1076 | 1070 |
| 1077 static _TokenPair _findLastDifferentToken(Token oldToken, Token newToken) { | 1071 static _TokenPair _findLastDifferentToken(Token oldToken, Token newToken) { |
| 1078 // print('last ------------'); | 1072 // print('last ------------'); |
| 1079 int delta = newToken.offset - oldToken.offset; | 1073 int delta = newToken.offset - oldToken.offset; |
| 1080 while (oldToken.previous != oldToken && newToken.previous != newToken) { | 1074 while (oldToken.previous != oldToken && newToken.previous != newToken) { |
| 1081 // print('old: $oldToken @ ${oldToken.offset}'); | 1075 // print('old: $oldToken @ ${oldToken.offset}'); |
| 1082 // print('new: $newToken @ ${newToken.offset}'); | 1076 // print('new: $newToken @ ${newToken.offset}'); |
| 1083 if (!_equalToken(oldToken, newToken, delta)) { | 1077 if (!_equalToken(oldToken, newToken, delta)) { |
| 1084 return new _TokenPair(oldToken.next, newToken.next, delta); | 1078 return new _TokenPair(oldToken, newToken); |
| 1085 } | 1079 } |
| 1086 oldToken.offset += delta; | |
| 1087 oldToken = oldToken.previous; | 1080 oldToken = oldToken.previous; |
| 1088 newToken = newToken.previous; | 1081 newToken = newToken.previous; |
| 1089 } | 1082 } |
| 1090 return null; | 1083 return null; |
| 1091 } | 1084 } |
| 1092 | 1085 |
| 1093 static AstNode _findNodeWithTokens(AstNode root, Token first, Token last) { | 1086 static AstNode _findNodeCovering(AstNode root, int offset, int end) { |
| 1094 int offset = first.offset; | |
| 1095 int end = last.end; | |
| 1096 NodeLocator nodeLocator = new NodeLocator.con2(offset, end); | 1087 NodeLocator nodeLocator = new NodeLocator.con2(offset, end); |
| 1097 return nodeLocator.searchWithin(root); | 1088 return nodeLocator.searchWithin(root); |
| 1098 } | 1089 } |
| 1099 | 1090 |
| 1100 static List<AstNode> _getParents(AstNode node) { | 1091 static List<AstNode> _getParents(AstNode node) { |
| 1101 List<AstNode> parents = <AstNode>[]; | 1092 List<AstNode> parents = <AstNode>[]; |
| 1102 while (node != null) { | 1093 while (node != null) { |
| 1103 parents.insert(0, node); | 1094 parents.insert(0, node); |
| 1104 node = node.parent; | 1095 node = node.parent; |
| 1105 } | 1096 } |
| 1106 return parents; | 1097 return parents; |
| 1107 } | 1098 } |
| 1099 |
| 1100 static void _shiftTokens(Token token, int delta) { |
| 1101 while (true) { |
| 1102 token.offset += delta; |
| 1103 if (token.type == TokenType.EOF) { |
| 1104 break; |
| 1105 } |
| 1106 token = token.next; |
| 1107 } |
| 1108 } |
| 1108 } | 1109 } |
| 1109 | 1110 |
| 1110 | 1111 |
| 1111 /** | 1112 /** |
| 1112 * The context to resolve an [AstNode] in. | 1113 * The context to resolve an [AstNode] in. |
| 1113 */ | 1114 */ |
| 1114 class ResolutionContext { | 1115 class ResolutionContext { |
| 1115 ClassDeclaration enclosingClassDeclaration; | 1116 ClassDeclaration enclosingClassDeclaration; |
| 1116 ClassElement enclosingClass; | 1117 ClassElement enclosingClass; |
| 1117 Scope scope; | 1118 Scope scope; |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1394 @override | 1395 @override |
| 1395 visitSimpleIdentifier(SimpleIdentifier node) { | 1396 visitSimpleIdentifier(SimpleIdentifier node) { |
| 1396 _elements[node] = node.staticElement; | 1397 _elements[node] = node.staticElement; |
| 1397 } | 1398 } |
| 1398 } | 1399 } |
| 1399 | 1400 |
| 1400 | 1401 |
| 1401 class _TokenPair { | 1402 class _TokenPair { |
| 1402 final Token oldToken; | 1403 final Token oldToken; |
| 1403 final Token newToken; | 1404 final Token newToken; |
| 1404 final int delta; | 1405 _TokenPair(this.oldToken, this.newToken); |
| 1405 _TokenPair(this.oldToken, this.newToken, this.delta); | |
| 1406 } | 1406 } |
| OLD | NEW |