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 | 8 |
| 9 import 'ast.dart'; | 9 import 'ast.dart'; |
| 10 import 'element.dart'; | 10 import 'element.dart'; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 45 | 45 |
| 46 /** | 46 /** |
| 47 * The parameter containing the AST nodes being visited, or `null` if we are n ot in the | 47 * The parameter containing the AST nodes being visited, or `null` if we are n ot in the |
| 48 * scope of a parameter. | 48 * scope of a parameter. |
| 49 */ | 49 */ |
| 50 ParameterElement _enclosingParameter; | 50 ParameterElement _enclosingParameter; |
| 51 | 51 |
| 52 bool _inTopLevelVariableDeclaration = false; | 52 bool _inTopLevelVariableDeclaration = false; |
| 53 | 53 |
| 54 /** | 54 /** |
| 55 * Is `true` if the current class declaration has a constructor. | |
| 56 */ | |
| 57 bool _hasConstructor = false; | |
| 58 | |
| 59 /** | |
| 55 * A set containing all of the elements in the element model that were defined by the old AST node | 60 * A set containing all of the elements in the element model that were defined by the old AST node |
| 56 * corresponding to the AST node being visited. | 61 * corresponding to the AST node being visited. |
| 57 */ | 62 */ |
| 58 HashSet<Element> _allElements = new HashSet<Element>(); | 63 HashSet<Element> _allElements = new HashSet<Element>(); |
| 59 | 64 |
| 60 /** | 65 /** |
| 61 * A set containing all of the elements in the element model that were defined by the old AST node | 66 * A set containing all of the elements in the element model that were defined by the old AST node |
| 62 * corresponding to the AST node being visited that have not already been matc hed to nodes in the | 67 * corresponding to the AST node being visited that have not already been matc hed to nodes in the |
| 63 * AST structure being visited. | 68 * AST structure being visited. |
| 64 */ | 69 */ |
| 65 HashSet<Element> _unmatchedElements = new HashSet<Element>(); | 70 HashSet<Element> _unmatchedElements = new HashSet<Element>(); |
| 66 | 71 |
| 67 /** | 72 /** |
| 68 * Return `true` if the declarations within the given AST structure define an element model | 73 * Return `true` if the declarations within the given AST structure define an element model |
| 69 * that is equivalent to the corresponding elements rooted at the given elemen t. | 74 * that is equivalent to the corresponding elements rooted at the given elemen t. |
| 70 * | 75 * |
| 71 * @param node the AST structure being compared to the element model | 76 * @param node the AST structure being compared to the element model |
| 72 * @param element the root of the element model being compared to the AST stru cture | 77 * @param element the root of the element model being compared to the AST stru cture |
| 73 * @return `true` if the AST structure defines the same elements as those in t he given | 78 * @return `true` if the AST structure defines the same elements as those in t he given |
| 74 * element model | 79 * element model |
| 75 */ | 80 */ |
| 76 bool matches(AstNode node, Element element) { | 81 bool matches(AstNode node, Element element) { |
| 77 _captureEnclosingElements(element); | 82 _captureEnclosingElements(element); |
| 78 _gatherElements(element); | 83 _gatherElements(element); |
| 79 try { | 84 try { |
| 80 node.accept(this); | 85 node.accept(this); |
| 81 } on _DeclarationMismatchException catch (exception) { | 86 } on _DeclarationMismatchException catch (exception, st) { |
|
Brian Wilkerson
2014/11/19 23:07:22
Not sure why you added a parameter if we're not us
scheglov
2014/11/20 05:27:30
Actually the hint _is_ reported here.
So, it is my
| |
| 82 return false; | 87 return false; |
| 83 } | 88 } |
| 84 print(_unmatchedElements.join('\n')); | |
| 85 return _unmatchedElements.isEmpty; | 89 return _unmatchedElements.isEmpty; |
| 86 } | 90 } |
| 87 | 91 |
| 88 @override | 92 @override |
| 89 Object visitCatchClause(CatchClause node) { | 93 Object visitCatchClause(CatchClause node) { |
| 90 SimpleIdentifier exceptionParameter = node.exceptionParameter; | 94 SimpleIdentifier exceptionParameter = node.exceptionParameter; |
| 91 if (exceptionParameter != null) { | 95 if (exceptionParameter != null) { |
| 92 List<LocalVariableElement> localVariables = | 96 List<LocalVariableElement> localVariables = |
| 93 _enclosingExecutable.localVariables; | 97 _enclosingExecutable.localVariables; |
| 94 LocalVariableElement exceptionElement = | 98 LocalVariableElement exceptionElement = |
| 95 _findIdentifier(localVariables, exceptionParameter); | 99 _findIdentifier(localVariables, exceptionParameter); |
| 96 _processElement(exceptionElement); | 100 _processElement(exceptionElement); |
| 97 SimpleIdentifier stackTraceParameter = node.stackTraceParameter; | 101 SimpleIdentifier stackTraceParameter = node.stackTraceParameter; |
| 98 if (stackTraceParameter != null) { | 102 if (stackTraceParameter != null) { |
| 99 LocalVariableElement stackTraceElement = | 103 LocalVariableElement stackTraceElement = |
| 100 _findIdentifier(localVariables, stackTraceParameter); | 104 _findIdentifier(localVariables, stackTraceParameter); |
| 101 _processElement(stackTraceElement); | 105 _processElement(stackTraceElement); |
| 102 } | 106 } |
| 103 } | 107 } |
| 104 return super.visitCatchClause(node); | 108 return super.visitCatchClause(node); |
| 105 } | 109 } |
| 106 | 110 |
| 107 @override | 111 @override |
| 108 Object visitClassDeclaration(ClassDeclaration node) { | 112 Object visitClassDeclaration(ClassDeclaration node) { |
| 109 ClassElement outerClass = _enclosingClass; | 113 String name = node.name.name; |
| 110 try { | 114 ClassElement clazz = _findElement(_enclosingUnit.types, name); |
| 111 SimpleIdentifier className = node.name; | 115 _enclosingClass = clazz; |
| 112 _enclosingClass = _findIdentifier(_enclosingUnit.types, className); | 116 _processElement(clazz); |
| 113 _processElement(_enclosingClass); | 117 // check for missing clauses |
| 114 if (!_hasConstructor(node)) { | 118 if (node.extendsClause == null) { |
| 115 ConstructorElement constructor = _enclosingClass.unnamedConstructor; | 119 _assertTrue(clazz.supertype.name == 'Object'); |
| 116 if (constructor.isSynthetic) { | 120 } |
| 117 _processElement(constructor); | 121 if (node.implementsClause == null) { |
| 118 } | 122 _assertTrue(clazz.interfaces.isEmpty); |
| 123 } | |
| 124 if (node.withClause == null) { | |
| 125 _assertTrue(clazz.mixins.isEmpty); | |
| 126 } | |
| 127 // process clauses and members | |
| 128 _hasConstructor = false; | |
| 129 super.visitClassDeclaration(node); | |
| 130 // process default constructor | |
| 131 if (!_hasConstructor) { | |
| 132 ConstructorElement constructor = clazz.unnamedConstructor; | |
| 133 _processElement(constructor); | |
| 134 if (!constructor.isSynthetic) { | |
| 135 _assertEquals(constructor.parameters.length, 0); | |
| 119 } | 136 } |
| 120 return super.visitClassDeclaration(node); | |
| 121 } finally { | |
| 122 _enclosingClass = outerClass; | |
| 123 } | 137 } |
| 138 return null; | |
| 124 } | 139 } |
| 125 | 140 |
| 126 @override | 141 @override |
| 127 Object visitClassTypeAlias(ClassTypeAlias node) { | 142 Object visitClassTypeAlias(ClassTypeAlias node) { |
| 128 ClassElement outerClass = _enclosingClass; | 143 ClassElement outerClass = _enclosingClass; |
| 129 try { | 144 try { |
| 130 SimpleIdentifier className = node.name; | 145 SimpleIdentifier className = node.name; |
| 131 _enclosingClass = _findIdentifier(_enclosingUnit.types, className); | 146 _enclosingClass = _findIdentifier(_enclosingUnit.types, className); |
| 132 _processElement(_enclosingClass); | 147 _processElement(_enclosingClass); |
| 133 return super.visitClassTypeAlias(node); | 148 return super.visitClassTypeAlias(node); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 218 LibraryElement library = _enclosingUnit.library; | 233 LibraryElement library = _enclosingUnit.library; |
| 219 ExportElement exportElement = _findExport( | 234 ExportElement exportElement = _findExport( |
| 220 library.exports, | 235 library.exports, |
| 221 _enclosingUnit.context.sourceFactory.resolveUri(_enclosingUnit.source, uri)); | 236 _enclosingUnit.context.sourceFactory.resolveUri(_enclosingUnit.source, uri)); |
| 222 _processElement(exportElement); | 237 _processElement(exportElement); |
| 223 } | 238 } |
| 224 return super.visitExportDirective(node); | 239 return super.visitExportDirective(node); |
| 225 } | 240 } |
| 226 | 241 |
| 227 @override | 242 @override |
| 243 visitExtendsClause(ExtendsClause node) { | |
| 244 _assertSameType(node.superclass, _enclosingClass.supertype); | |
| 245 } | |
| 246 | |
| 247 @override | |
| 228 Object visitFieldFormalParameter(FieldFormalParameter node) { | 248 Object visitFieldFormalParameter(FieldFormalParameter node) { |
| 229 if (node.parent is! DefaultFormalParameter) { | 249 if (node.parent is! DefaultFormalParameter) { |
| 230 SimpleIdentifier parameterName = node.identifier; | 250 SimpleIdentifier parameterName = node.identifier; |
| 231 ParameterElement element = _getElementForParameter(node, parameterName); | 251 ParameterElement element = _getElementForParameter(node, parameterName); |
| 232 ParameterElement outerParameter = _enclosingParameter; | 252 ParameterElement outerParameter = _enclosingParameter; |
| 233 try { | 253 try { |
| 234 _enclosingParameter = element; | 254 _enclosingParameter = element; |
| 235 _processElement(_enclosingParameter); | 255 _processElement(_enclosingParameter); |
| 236 return super.visitFieldFormalParameter(node); | 256 return super.visitFieldFormalParameter(node); |
| 237 } finally { | 257 } finally { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 314 return super.visitFunctionTypedFormalParameter(node); | 334 return super.visitFunctionTypedFormalParameter(node); |
| 315 } finally { | 335 } finally { |
| 316 _enclosingParameter = outerParameter; | 336 _enclosingParameter = outerParameter; |
| 317 } | 337 } |
| 318 } else { | 338 } else { |
| 319 return super.visitFunctionTypedFormalParameter(node); | 339 return super.visitFunctionTypedFormalParameter(node); |
| 320 } | 340 } |
| 321 } | 341 } |
| 322 | 342 |
| 323 @override | 343 @override |
| 344 visitImplementsClause(ImplementsClause node) { | |
| 345 List<TypeName> nodes = node.interfaces; | |
| 346 List<InterfaceType> types = _enclosingClass.interfaces; | |
| 347 _assertSameTypes(nodes, types); | |
| 348 } | |
| 349 | |
| 350 @override | |
| 324 Object visitImportDirective(ImportDirective node) { | 351 Object visitImportDirective(ImportDirective node) { |
| 325 String uri = _getStringValue(node.uri); | 352 String uri = _getStringValue(node.uri); |
| 326 if (uri != null) { | 353 if (uri != null) { |
| 327 LibraryElement library = _enclosingUnit.library; | 354 LibraryElement library = _enclosingUnit.library; |
| 328 ImportElement importElement = _findImport( | 355 ImportElement importElement = _findImport( |
| 329 library.imports, | 356 library.imports, |
| 330 _enclosingUnit.context.sourceFactory.resolveUri(_enclosingUnit.source, uri), | 357 _enclosingUnit.context.sourceFactory.resolveUri(_enclosingUnit.source, uri), |
| 331 node.prefix); | 358 node.prefix); |
| 332 _processElement(importElement); | 359 _processElement(importElement); |
| 333 } | 360 } |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 473 VariableElement element; | 500 VariableElement element; |
| 474 if (_enclosingExecutable != null) { | 501 if (_enclosingExecutable != null) { |
| 475 element = _findElement(_enclosingExecutable.localVariables, name); | 502 element = _findElement(_enclosingExecutable.localVariables, name); |
| 476 } | 503 } |
| 477 if (element == null && _enclosingClass != null) { | 504 if (element == null && _enclosingClass != null) { |
| 478 element = _findElement(_enclosingClass.fields, name); | 505 element = _findElement(_enclosingClass.fields, name); |
| 479 } | 506 } |
| 480 return super.visitVariableDeclaration(node); | 507 return super.visitVariableDeclaration(node); |
| 481 } | 508 } |
| 482 | 509 |
| 510 @override | |
| 511 visitWithClause(WithClause node) { | |
| 512 List<TypeName> nodes = node.mixinTypes; | |
| 513 List<InterfaceType> types = _enclosingClass.mixins; | |
| 514 _assertSameTypes(nodes, types); | |
| 515 } | |
| 516 | |
| 517 void _assertEquals(Object a, Object b) { | |
| 518 if (a != b) { | |
| 519 throw new _DeclarationMismatchException(); | |
| 520 } | |
| 521 } | |
| 522 | |
| 523 void _assertFalse(bool condition) { | |
| 524 if (condition) { | |
| 525 throw new _DeclarationMismatchException(); | |
| 526 } | |
| 527 } | |
| 528 | |
| 529 void _assertNotNull(Element element) { | |
| 530 if (element == null) { | |
| 531 throw new _DeclarationMismatchException(); | |
| 532 } | |
| 533 } | |
| 534 | |
| 483 void _assertSameType(TypeName node, DartType type) { | 535 void _assertSameType(TypeName node, DartType type) { |
| 484 String nodeName = node.name.name; | 536 String nodeName = node.name.name; |
| 485 if (type is InterfaceType) { | 537 if (type is InterfaceType) { |
| 486 _assertEquals(nodeName, type.name); | 538 _assertEquals(nodeName, type.name); |
| 539 // check arguments | |
| 487 TypeArgumentList nodeArgumentList = node.typeArguments; | 540 TypeArgumentList nodeArgumentList = node.typeArguments; |
| 488 List<DartType> typeArguments = type.typeArguments; | 541 List<DartType> typeArguments = type.typeArguments; |
| 489 if (nodeArgumentList == null) { | 542 if (nodeArgumentList == null) { |
| 490 _assertTrue(typeArguments.isEmpty); | 543 _assertTrue(typeArguments.isEmpty); |
| 491 } else { | 544 } else { |
| 492 List<TypeName> nodeArguments = nodeArgumentList.arguments; | 545 List<TypeName> nodeArguments = nodeArgumentList.arguments; |
| 493 int numArguments = nodeArguments.length; | 546 _assertSameTypes(nodeArguments, typeArguments); |
| 494 _assertEquals(numArguments, typeArguments.length); | |
| 495 for (int i = 0; i < numArguments; i++) { | |
| 496 _assertSameType(nodeArguments[i], typeArguments[i]); | |
| 497 } | |
| 498 } | 547 } |
| 499 } else { | 548 } else { |
| 500 // TODO(scheglov) support other types | 549 // TODO(scheglov) support other types |
| 501 _assertTrue(false); | 550 _assertTrue(false); |
| 502 } | 551 } |
| 503 } | 552 } |
| 504 | 553 |
| 505 void _assertFalse(bool condition) { | 554 void _assertSameTypes(List<TypeName> nodes, List<DartType> type) { |
| 506 if (condition) { | 555 int length = nodes.length; |
| 507 throw new _DeclarationMismatchException(); | 556 _assertEquals(length, type.length); |
| 557 for (int i = 0; i < length; i++) { | |
| 558 _assertSameType(nodes[i], type[i]); | |
| 508 } | 559 } |
| 509 } | 560 } |
| 510 | 561 |
| 511 void _assertNotNull(Element element) { | |
| 512 if (element == null) { | |
| 513 throw new _DeclarationMismatchException(); | |
| 514 } | |
| 515 } | |
| 516 | |
| 517 void _assertEquals(Object a, Object b) { | |
| 518 if (a != b) { | |
| 519 throw new _DeclarationMismatchException(); | |
| 520 } | |
| 521 } | |
| 522 | |
| 523 void _assertTrue(bool condition) { | 562 void _assertTrue(bool condition) { |
| 524 if (!condition) { | 563 if (!condition) { |
| 525 throw new _DeclarationMismatchException(); | 564 throw new _DeclarationMismatchException(); |
| 526 } | 565 } |
| 527 } | 566 } |
| 528 | 567 |
| 529 /** | 568 /** |
| 530 * Given that the comparison is to begin with the given element, capture the e nclosing elements | 569 * Given that the comparison is to begin with the given element, capture the e nclosing elements |
| 531 * that might be used while performing the comparison. | 570 * that might be used while performing the comparison. |
| 532 * | 571 * |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 714 * @param literal the string literal whose value is to be returned | 753 * @param literal the string literal whose value is to be returned |
| 715 * @return the value of the given string literal | 754 * @return the value of the given string literal |
| 716 */ | 755 */ |
| 717 String _getStringValue(StringLiteral literal) { | 756 String _getStringValue(StringLiteral literal) { |
| 718 if (literal is StringInterpolation) { | 757 if (literal is StringInterpolation) { |
| 719 return null; | 758 return null; |
| 720 } | 759 } |
| 721 return literal.stringValue; | 760 return literal.stringValue; |
| 722 } | 761 } |
| 723 | 762 |
| 724 /** | |
| 725 * Return `true` if the given class defines at least one constructor. | |
| 726 * | |
| 727 * @param node the class being tested | |
| 728 * @return `true` if the class defines at least one constructor | |
| 729 */ | |
| 730 bool _hasConstructor(ClassDeclaration node) { | |
| 731 for (ClassMember member in node.members) { | |
| 732 if (member is ConstructorDeclaration) { | |
| 733 return true; | |
| 734 } | |
| 735 } | |
| 736 return false; | |
| 737 } | |
| 738 | |
| 739 void _processElement(Element element) { | 763 void _processElement(Element element) { |
| 740 _assertNotNull(element); | 764 _assertNotNull(element); |
| 741 if (!_allElements.contains(element)) { | 765 if (!_allElements.contains(element)) { |
| 742 throw new _DeclarationMismatchException(); | 766 throw new _DeclarationMismatchException(); |
| 743 } | 767 } |
| 744 bool did = _unmatchedElements.remove(element); | 768 _unmatchedElements.remove(element); |
| 745 print('remove: $element | $did'); | |
| 746 } | 769 } |
| 747 } | 770 } |
| 748 | 771 |
| 749 | 772 |
| 750 /** | 773 /** |
| 751 * Instances of the class [IncrementalResolver] resolve the smallest portion of | 774 * Instances of the class [IncrementalResolver] resolve the smallest portion of |
| 752 * an AST structure that we currently know how to resolve. | 775 * an AST structure that we currently know how to resolve. |
| 753 */ | 776 */ |
| 754 class IncrementalResolver { | 777 class IncrementalResolver { |
| 755 /** | 778 /** |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1079 } | 1102 } |
| 1080 } | 1103 } |
| 1081 | 1104 |
| 1082 void _addElement(Element element) { | 1105 void _addElement(Element element) { |
| 1083 if (element != null) { | 1106 if (element != null) { |
| 1084 matcher._allElements.add(element); | 1107 matcher._allElements.add(element); |
| 1085 matcher._unmatchedElements.add(element); | 1108 matcher._unmatchedElements.add(element); |
| 1086 } | 1109 } |
| 1087 } | 1110 } |
| 1088 } | 1111 } |
| OLD | NEW |