| 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 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 this._definingLibrary, this._definingUnit, this._source, this._updateOffse
t, | 649 this._definingLibrary, this._definingUnit, this._source, this._updateOffse
t, |
| 650 this._updateOldLength, this._updateNewLength); | 650 this._updateOldLength, this._updateNewLength); |
| 651 | 651 |
| 652 /** | 652 /** |
| 653 * Resolve [node], reporting any errors or warnings to the given listener. | 653 * Resolve [node], reporting any errors or warnings to the given listener. |
| 654 * | 654 * |
| 655 * [node] - the root of the AST structure to be resolved. | 655 * [node] - the root of the AST structure to be resolved. |
| 656 */ | 656 */ |
| 657 void resolve(AstNode node) { | 657 void resolve(AstNode node) { |
| 658 AstNode rootNode = _findResolutionRoot(node); | 658 AstNode rootNode = _findResolutionRoot(node); |
| 659 Scope scope = ScopeBuilder.scopeFor(rootNode, _errorListener); | 659 if (_elementModelChanged(rootNode)) { |
| 660 if (_elementModelChanged(rootNode.parent)) { | |
| 661 throw new AnalysisException("Cannot resolve node: element model changed"); | 660 throw new AnalysisException("Cannot resolve node: element model changed"); |
| 662 } | 661 } |
| 662 // update elements |
| 663 _definingUnit.accept( | 663 _definingUnit.accept( |
| 664 new _ElementNameOffsetUpdater( | 664 new _ElementNameOffsetUpdater( |
| 665 _updateOffset, | 665 _updateOffset, |
| 666 _updateNewLength - _updateOldLength)); | 666 _updateNewLength - _updateOldLength)); |
| 667 _resolveTypes(node, scope); | 667 _updateElements(rootNode); |
| 668 _resolveVariables(node, scope); | 668 // resolve root in scope |
| 669 _resolveReferences(node, scope); | 669 Scope scope = ScopeBuilder.scopeFor(rootNode, _errorListener); |
| 670 _resolveTypes(rootNode, scope); |
| 671 _resolveVariables(rootNode, scope); |
| 672 _resolveReferences(rootNode, scope); |
| 670 } | 673 } |
| 671 | 674 |
| 672 /** | 675 /** |
| 673 * Return `true` if the given node can be resolved independently of any other | 676 * Return `true` if the given node can be resolved independently of any other |
| 674 * nodes. | 677 * nodes. |
| 675 * | 678 * |
| 676 * *Note*: This method needs to be kept in sync with | 679 * *Note*: This method needs to be kept in sync with |
| 677 * [ScopeBuilder.scopeForAstNode]. | 680 * [ScopeBuilder.scopeForAstNode]. |
| 678 * | 681 * |
| 679 * [node] - the node being tested. | 682 * [node] - the node being tested. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 708 | 711 |
| 709 /** | 712 /** |
| 710 * Starting at [node], find the smallest AST node that can be resolved | 713 * Starting at [node], find the smallest AST node that can be resolved |
| 711 * independently of any other nodes. Return the node that was found. | 714 * independently of any other nodes. Return the node that was found. |
| 712 * | 715 * |
| 713 * [node] - the node at which the search is to begin | 716 * [node] - the node at which the search is to begin |
| 714 * | 717 * |
| 715 * Throws [AnalysisException] if there is no such node. | 718 * Throws [AnalysisException] if there is no such node. |
| 716 */ | 719 */ |
| 717 AstNode _findResolutionRoot(AstNode node) { | 720 AstNode _findResolutionRoot(AstNode node) { |
| 718 AstNode result = node; | 721 while (node != null) { |
| 719 AstNode parent = result.parent; | 722 if (_canBeResolved(node)) { |
| 720 while (parent != null && !_canBeResolved(parent)) { | 723 return node; |
| 721 result = parent; | 724 } |
| 722 parent = result.parent; | 725 node = node.parent; |
| 723 } | 726 } |
| 724 if (parent == null) { | 727 throw new AnalysisException("Cannot resolve node: no resolvable node"); |
| 725 throw new AnalysisException("Cannot resolve node: no resolvable node"); | |
| 726 } | |
| 727 return result; | |
| 728 } | 728 } |
| 729 | 729 |
| 730 /** | 730 /** |
| 731 * Return the element defined by [node], or `null` if the node does not | 731 * Return the element defined by [node], or `null` if the node does not |
| 732 * define an element. | 732 * define an element. |
| 733 */ | 733 */ |
| 734 Element _getElement(AstNode node) { | 734 Element _getElement(AstNode node) { |
| 735 if (node is Declaration) { | 735 if (node is Declaration) { |
| 736 return node.element; | 736 return node.element; |
| 737 } else if (node is CompilationUnit) { | 737 } else if (node is CompilationUnit) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 762 | 762 |
| 763 void _resolveVariables(AstNode node, Scope scope) { | 763 void _resolveVariables(AstNode node, Scope scope) { |
| 764 VariableResolverVisitor visitor = new VariableResolverVisitor.con2( | 764 VariableResolverVisitor visitor = new VariableResolverVisitor.con2( |
| 765 _definingLibrary, | 765 _definingLibrary, |
| 766 _source, | 766 _source, |
| 767 _typeProvider, | 767 _typeProvider, |
| 768 scope, | 768 scope, |
| 769 _errorListener); | 769 _errorListener); |
| 770 node.accept(visitor); | 770 node.accept(visitor); |
| 771 } | 771 } |
| 772 |
| 773 void _updateElements(AstNode node) { |
| 774 // build elements in node |
| 775 ElementHolder holder; |
| 776 _ElementsRestorer elementsRestorer = new _ElementsRestorer(node); |
| 777 try { |
| 778 holder = new ElementHolder(); |
| 779 ElementBuilder builder = new ElementBuilder(holder); |
| 780 node.accept(builder); |
| 781 } finally { |
| 782 elementsRestorer.restore(); |
| 783 } |
| 784 // apply compatible changes to elements |
| 785 if (node is FunctionDeclaration) { |
| 786 FunctionElementImpl oldElement = node.element; |
| 787 FunctionElementImpl newElement = holder.functions[0]; |
| 788 oldElement.labels = newElement.labels; |
| 789 oldElement.localVariables = newElement.localVariables; |
| 790 } |
| 791 if (node is MethodDeclaration) { |
| 792 MethodElementImpl oldElement = node.element; |
| 793 MethodElementImpl newElement = holder.methods[0]; |
| 794 oldElement.labels = newElement.labels; |
| 795 oldElement.localVariables = newElement.localVariables; |
| 796 } |
| 797 } |
| 772 } | 798 } |
| 773 | 799 |
| 774 | 800 |
| 775 /** | 801 /** |
| 776 * Instances of the class [ScopeBuilder] build the scope for a given node in an | 802 * Instances of the class [ScopeBuilder] build the scope for a given node in an |
| 777 * AST structure. At the moment, this class only handles top-level and | 803 * AST structure. At the moment, this class only handles top-level and |
| 778 * class-level declarations. | 804 * class-level declarations. |
| 779 */ | 805 */ |
| 780 class ScopeBuilder { | 806 class ScopeBuilder { |
| 781 /** | 807 /** |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 966 // Don't visit children (such as property accessors). | 992 // Don't visit children (such as property accessors). |
| 967 } | 993 } |
| 968 | 994 |
| 969 void _addElement(Element element) { | 995 void _addElement(Element element) { |
| 970 if (element != null) { | 996 if (element != null) { |
| 971 matcher._allElements.add(element); | 997 matcher._allElements.add(element); |
| 972 matcher._unmatchedElements.add(element); | 998 matcher._unmatchedElements.add(element); |
| 973 } | 999 } |
| 974 } | 1000 } |
| 975 } | 1001 } |
| 1002 |
| 1003 |
| 1004 /** |
| 1005 * [ElementBuilder] not just builds elements, it also applies them to nodes. |
| 1006 * But we want to keep externally visible (and referenced) elements instances. |
| 1007 * So, we need to remember them and restore. |
| 1008 */ |
| 1009 class _ElementsRestorer extends RecursiveAstVisitor { |
| 1010 final Map<AstNode, Element> _elements = <AstNode, Element>{}; |
| 1011 |
| 1012 _ElementsRestorer(AstNode root) { |
| 1013 root.accept(this); |
| 1014 } |
| 1015 |
| 1016 void restore() { |
| 1017 _elements.forEach((AstNode node, Element element) { |
| 1018 if (node is ConstructorDeclaration) { |
| 1019 node.element = element; |
| 1020 } else if (node is FunctionExpression) { |
| 1021 node.element = element; |
| 1022 } else if (node is SimpleIdentifier) { |
| 1023 node.staticElement = element; |
| 1024 } |
| 1025 }); |
| 1026 } |
| 1027 |
| 1028 @override |
| 1029 visitBlockFunctionBody(BlockFunctionBody node) { |
| 1030 } |
| 1031 |
| 1032 @override |
| 1033 visitConstructorDeclaration(ConstructorDeclaration node) { |
| 1034 _elements[node] = node.element; |
| 1035 super.visitConstructorDeclaration(node); |
| 1036 } |
| 1037 |
| 1038 @override |
| 1039 visitExpressionFunctionBody(ExpressionFunctionBody node) { |
| 1040 } |
| 1041 |
| 1042 @override |
| 1043 visitFunctionExpression(FunctionExpression node) { |
| 1044 _elements[node] = node.element; |
| 1045 super.visitFunctionExpression(node); |
| 1046 } |
| 1047 |
| 1048 @override |
| 1049 visitSimpleIdentifier(SimpleIdentifier node) { |
| 1050 _elements[node] = node.staticElement; |
| 1051 } |
| 1052 } |
| OLD | NEW |