| 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 'ast.dart'; | 10 import 'ast.dart'; |
| 11 import 'element.dart'; | 11 import 'element.dart'; |
| 12 import 'error.dart'; | 12 import 'error.dart'; |
| 13 import 'java_engine.dart'; | 13 import 'java_engine.dart'; |
| 14 import 'parser.dart'; |
| 14 import 'resolver.dart'; | 15 import 'resolver.dart'; |
| 15 import 'scanner.dart'; | 16 import 'scanner.dart'; |
| 16 import 'source.dart'; | 17 import 'source.dart'; |
| 17 import 'parser.dart'; | |
| 18 | 18 |
| 19 | 19 |
| 20 /** | 20 /** |
| 21 * Attempts to update [oldUnit] to the state that would correspond to [newCode]. | 21 * Attempts to update [oldUnit] to the state that would correspond to [newCode]. |
| 22 * Returns `true` if success, or `false` otherwise. | 22 * Returns `true` if success, or `false` otherwise. |
| 23 * The [oldUnit] might be damaged. | 23 * The [oldUnit] might be damaged. |
| 24 */ | 24 */ |
| 25 bool poorMansIncrementalResolution(TypeProvider typeProvider, | 25 bool poorMansIncrementalResolution(TypeProvider typeProvider, |
| 26 CompilationUnit oldUnit, String newCode) { | 26 CompilationUnit oldUnit, String newCode) { |
| 27 try { | 27 try { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 incrementalResolver.resolve(newNode); | 97 incrementalResolver.resolve(newNode); |
| 98 return true; | 98 return true; |
| 99 } | 99 } |
| 100 } catch (e) { | 100 } catch (e) { |
| 101 // TODO(scheglov) find a way to log these exceptions | 101 // TODO(scheglov) find a way to log these exceptions |
| 102 } | 102 } |
| 103 return false; | 103 return false; |
| 104 } | 104 } |
| 105 | 105 |
| 106 | 106 |
| 107 List<AstNode> _getParents(AstNode node) { | 107 bool _equalToken(Token oldToken, Token newToken, int delta) { |
| 108 List<AstNode> parents = <AstNode>[]; | 108 if (oldToken.type != newToken.type) { |
| 109 while (node != null) { | 109 return false; |
| 110 parents.insert(0, node); | |
| 111 node = node.parent; | |
| 112 } | 110 } |
| 113 return parents; | 111 if (newToken.offset - oldToken.offset != delta) { |
| 114 } | 112 return false; |
| 115 | 113 } |
| 116 AstNode _findNodeWithTokens(AstNode root, Token first, Token last) { | 114 return oldToken.lexeme == newToken.lexeme; |
| 117 int offset = first.offset; | |
| 118 int end = last.end; | |
| 119 NodeLocator nodeLocator = new NodeLocator.con2(offset, end); | |
| 120 return nodeLocator.searchWithin(root); | |
| 121 } | 115 } |
| 122 | 116 |
| 123 | 117 |
| 124 class _TokenPair { | |
| 125 final Token oldToken; | |
| 126 final Token newToken; | |
| 127 _TokenPair(this.oldToken, this.newToken); | |
| 128 } | |
| 129 | |
| 130 | |
| 131 _TokenPair _findFirstDifferentToken(Token oldToken, Token newToken) { | 118 _TokenPair _findFirstDifferentToken(Token oldToken, Token newToken) { |
| 132 // print('first ------------'); | 119 // print('first ------------'); |
| 133 while (oldToken.type != TokenType.EOF && newToken.type != TokenType.EOF) { | 120 while (oldToken.type != TokenType.EOF && newToken.type != TokenType.EOF) { |
| 134 // print('old: $oldToken @ ${oldToken.offset}'); | 121 // print('old: $oldToken @ ${oldToken.offset}'); |
| 135 // print('new: $newToken @ ${newToken.offset}'); | 122 // print('new: $newToken @ ${newToken.offset}'); |
| 136 if (!_equalToken(oldToken, newToken, 0)) { | 123 if (!_equalToken(oldToken, newToken, 0)) { |
| 137 return new _TokenPair(oldToken, newToken); | 124 return new _TokenPair(oldToken, newToken); |
| 138 } | 125 } |
| 139 oldToken = oldToken.next; | 126 oldToken = oldToken.next; |
| 140 newToken = newToken.next; | 127 newToken = newToken.next; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 153 return new _TokenPair(oldToken.next, newToken.next); | 140 return new _TokenPair(oldToken.next, newToken.next); |
| 154 } | 141 } |
| 155 oldToken.offset += delta; | 142 oldToken.offset += delta; |
| 156 oldToken = oldToken.previous; | 143 oldToken = oldToken.previous; |
| 157 newToken = newToken.previous; | 144 newToken = newToken.previous; |
| 158 } | 145 } |
| 159 return null; | 146 return null; |
| 160 } | 147 } |
| 161 | 148 |
| 162 | 149 |
| 163 bool _equalToken(Token a, Token b, int delta) { | 150 AstNode _findNodeWithTokens(AstNode root, Token first, Token last) { |
| 164 if (a.type != b.type) { | 151 int offset = first.offset; |
| 165 return false; | 152 int end = last.end; |
| 166 } | 153 NodeLocator nodeLocator = new NodeLocator.con2(offset, end); |
| 167 if (b.offset - a.offset != delta) { | 154 return nodeLocator.searchWithin(root); |
| 168 return false; | |
| 169 } | |
| 170 return a.lexeme == b.lexeme; | |
| 171 } | 155 } |
| 172 | 156 |
| 173 | 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 |
| 174 CompilationUnit _parseUnit(String code) { | 168 CompilationUnit _parseUnit(String code) { |
| 175 // TODO(scheglov) remember and update errors | 169 // TODO(scheglov) remember and update errors |
| 176 var errorListener = new BooleanErrorListener(); | 170 var errorListener = new BooleanErrorListener(); |
| 177 var reader = new CharSequenceReader(code); | 171 var reader = new CharSequenceReader(code); |
| 178 var scanner = new Scanner(null, reader, errorListener); | 172 var scanner = new Scanner(null, reader, errorListener); |
| 179 var token = scanner.tokenize(); | 173 var token = scanner.tokenize(); |
| 180 var parser = new Parser(null, errorListener); | 174 var parser = new Parser(null, errorListener); |
| 181 return parser.parseCompilationUnit(token); | 175 return parser.parseCompilationUnit(token); |
| 182 } | 176 } |
| 183 | 177 |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 _assertTrue(hideNames.remove(name)); | 541 _assertTrue(hideNames.remove(name)); |
| 548 } | 542 } |
| 549 } | 543 } |
| 550 } | 544 } |
| 551 _assertTrue(showNames.isEmpty); | 545 _assertTrue(showNames.isEmpty); |
| 552 _assertTrue(hideNames.isEmpty); | 546 _assertTrue(hideNames.isEmpty); |
| 553 } | 547 } |
| 554 | 548 |
| 555 void _assertCompatibleParameter(FormalParameter node, | 549 void _assertCompatibleParameter(FormalParameter node, |
| 556 ParameterElement element) { | 550 ParameterElement element) { |
| 557 if (node is SimpleFormalParameter) { | 551 if (node is DefaultFormalParameter) { |
| 552 _assertTrue(element.isInitializingFormal); |
| 553 // TODO(scheglov) check default value |
| 554 } else if (node is FieldFormalParameter) { |
| 555 _assertTrue(element.isInitializingFormal); |
| 556 } else if (node is SimpleFormalParameter) { |
| 558 _assertSameType(node.type, element.type); | 557 _assertSameType(node.type, element.type); |
| 559 node.identifier.staticElement = element; | 558 node.identifier.staticElement = element; |
| 560 (element as ElementImpl).nameOffset = node.identifier.offset; | 559 (element as ElementImpl).nameOffset = node.identifier.offset; |
| 561 (element as ElementImpl).name = node.identifier.name; | 560 (element as ElementImpl).name = node.identifier.name; |
| 562 } else { | 561 } else { |
| 563 // TODO(scheglov) support other parameter types | 562 // TODO(scheglov) support other parameter types |
| 563 // print('node: $node element: $element ${element.runtimeType}'); |
| 564 _assertTrue(false); | 564 _assertTrue(false); |
| 565 } | 565 } |
| 566 // TODO(scheglov) check names of named parameters | 566 // TODO(scheglov) check names of named parameters |
| 567 } | 567 } |
| 568 | 568 |
| 569 void _assertCompatibleParameters(FormalParameterList nodes, | 569 void _assertCompatibleParameters(FormalParameterList nodes, |
| 570 List<ParameterElement> elements) { | 570 List<ParameterElement> elements) { |
| 571 if (nodes == null) { | 571 if (nodes == null) { |
| 572 return _assertEquals(elements.length, 0); | 572 return _assertEquals(elements.length, 0); |
| 573 } | 573 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 601 if (element != null) { | 601 if (element != null) { |
| 602 throw new _DeclarationMismatchException(); | 602 throw new _DeclarationMismatchException(); |
| 603 } | 603 } |
| 604 } | 604 } |
| 605 | 605 |
| 606 void _assertSameType(TypeName node, DartType type) { | 606 void _assertSameType(TypeName node, DartType type) { |
| 607 // no return type == dynamic | 607 // no return type == dynamic |
| 608 if (node == null) { | 608 if (node == null) { |
| 609 return _assertTrue(type == null || type.isDynamic); | 609 return _assertTrue(type == null || type.isDynamic); |
| 610 } | 610 } |
| 611 if (type == null) { |
| 612 return _assertTrue(false); |
| 613 } |
| 611 // check specific type kinds | 614 // check specific type kinds |
| 612 String nodeName = node.name.name; | 615 String nodeName = node.name.name; |
| 613 if (type is InterfaceType) { | 616 if (type is InterfaceType) { |
| 614 _assertEquals(nodeName, type.name); | 617 _assertEquals(nodeName, type.name); |
| 615 // check arguments | 618 // check arguments |
| 616 TypeArgumentList nodeArgumentList = node.typeArguments; | 619 TypeArgumentList nodeArgumentList = node.typeArguments; |
| 617 List<DartType> typeArguments = type.typeArguments; | 620 List<DartType> typeArguments = type.typeArguments; |
| 618 if (nodeArgumentList == null) { | 621 if (nodeArgumentList == null) { |
| 619 _assertTrue(typeArguments.isEmpty); | 622 // Node doesn't have type arguments, so all type argument of the |
| 623 // element must be "dynamic". |
| 624 for (DartType typeArgument in typeArguments) { |
| 625 _assertTrue(typeArgument.isDynamic); |
| 626 } |
| 620 } else { | 627 } else { |
| 621 List<TypeName> nodeArguments = nodeArgumentList.arguments; | 628 List<TypeName> nodeArguments = nodeArgumentList.arguments; |
| 622 _assertSameTypes(nodeArguments, typeArguments); | 629 _assertSameTypes(nodeArguments, typeArguments); |
| 623 } | 630 } |
| 624 } else if (type is TypeParameterType) { | 631 } else if (type is TypeParameterType) { |
| 625 _assertEquals(nodeName, type.name); | 632 _assertEquals(nodeName, type.name); |
| 626 // TODO(scheglov) it should be possible to rename type parameters | 633 // TODO(scheglov) it should be possible to rename type parameters |
| 627 } else if (type is VoidType) { | 634 } else if (type.isVoid) { |
| 628 _assertEquals(nodeName, 'void'); | 635 _assertEquals(nodeName, 'void'); |
| 629 // TODO(scheglov) add test for "void" | 636 } else if (type.isDynamic) { |
| 637 _assertEquals(nodeName, 'dynamic'); |
| 630 } else { | 638 } else { |
| 631 // TODO(scheglov) support other types | 639 // TODO(scheglov) support other types |
| 632 // print('node: $node type: $type type.type: ${type.runtimeType}'); | 640 // print('node: $node type: $type type.type: ${type.runtimeType}'); |
| 633 _assertTrue(false); | 641 _assertTrue(false); |
| 634 } | 642 } |
| 635 } | 643 } |
| 636 | 644 |
| 637 void _assertSameTypes(List<TypeName> nodes, List<DartType> types) { | 645 void _assertSameTypes(List<TypeName> nodes, List<DartType> types) { |
| 638 int length = nodes.length; | 646 int length = nodes.length; |
| 639 _assertEquals(length, types.length); | 647 _assertEquals(length, types.length); |
| (...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1253 visitFunctionExpression(FunctionExpression node) { | 1261 visitFunctionExpression(FunctionExpression node) { |
| 1254 _elements[node] = node.element; | 1262 _elements[node] = node.element; |
| 1255 super.visitFunctionExpression(node); | 1263 super.visitFunctionExpression(node); |
| 1256 } | 1264 } |
| 1257 | 1265 |
| 1258 @override | 1266 @override |
| 1259 visitSimpleIdentifier(SimpleIdentifier node) { | 1267 visitSimpleIdentifier(SimpleIdentifier node) { |
| 1260 _elements[node] = node.staticElement; | 1268 _elements[node] = node.staticElement; |
| 1261 } | 1269 } |
| 1262 } | 1270 } |
| 1271 |
| 1272 |
| 1273 class _TokenPair { |
| 1274 final Token oldToken; |
| 1275 final Token newToken; |
| 1276 _TokenPair(this.oldToken, this.newToken); |
| 1277 } |
| OLD | NEW |