| 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 analyzer.src.generated.element_resolver; | 5 library analyzer.src.generated.element_resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/src/generated/ast.dart'; | 9 import 'package:analyzer/src/generated/ast.dart'; |
| 10 import 'package:analyzer/src/generated/element.dart'; | 10 import 'package:analyzer/src/generated/element.dart'; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 bool _enableStrictCallChecks = false; | 95 bool _enableStrictCallChecks = false; |
| 96 | 96 |
| 97 /** | 97 /** |
| 98 * The type representing the type 'dynamic'. | 98 * The type representing the type 'dynamic'. |
| 99 */ | 99 */ |
| 100 DartType _dynamicType; | 100 DartType _dynamicType; |
| 101 | 101 |
| 102 /** | 102 /** |
| 103 * The type representing the type 'type'. | 103 * The type representing the type 'type'. |
| 104 */ | 104 */ |
| 105 DartType _typeType; | 105 InterfaceType _typeType; |
| 106 | 106 |
| 107 /** | 107 /** |
| 108 * A utility class for the resolver to answer the question of "what are my | 108 * A utility class for the resolver to answer the question of "what are my |
| 109 * subtypes?". | 109 * subtypes?". |
| 110 */ | 110 */ |
| 111 SubtypeManager _subtypeManager; | 111 SubtypeManager _subtypeManager; |
| 112 | 112 |
| 113 /** | 113 /** |
| 114 * The object keeping track of which elements have had their types promoted. | 114 * The object keeping track of which elements have had their types promoted. |
| 115 */ | 115 */ |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 // We have a method invocation of one of two forms: 'e.m(a1, ..., an)' or | 587 // We have a method invocation of one of two forms: 'e.m(a1, ..., an)' or |
| 588 // 'm(a1, ..., an)'. The first step is to figure out which executable is | 588 // 'm(a1, ..., an)'. The first step is to figure out which executable is |
| 589 // being invoked, using both the static and the propagated type information. | 589 // being invoked, using both the static and the propagated type information. |
| 590 // | 590 // |
| 591 Expression target = node.realTarget; | 591 Expression target = node.realTarget; |
| 592 if (target is SuperExpression && !_isSuperInValidContext(target)) { | 592 if (target is SuperExpression && !_isSuperInValidContext(target)) { |
| 593 return null; | 593 return null; |
| 594 } | 594 } |
| 595 Element staticElement; | 595 Element staticElement; |
| 596 Element propagatedElement; | 596 Element propagatedElement; |
| 597 DartType staticType = null; | |
| 598 DartType propagatedType = null; | |
| 599 if (target == null) { | 597 if (target == null) { |
| 600 staticElement = _resolveInvokedElement(methodName); | 598 staticElement = _resolveInvokedElement(methodName); |
| 601 propagatedElement = null; | 599 propagatedElement = null; |
| 602 } else if (methodName.name == FunctionElement.LOAD_LIBRARY_NAME && | 600 } else if (methodName.name == FunctionElement.LOAD_LIBRARY_NAME && |
| 603 _isDeferredPrefix(target)) { | 601 _isDeferredPrefix(target)) { |
| 604 if (node.operator.type == sc.TokenType.QUESTION_PERIOD) { | 602 if (node.operator.type == sc.TokenType.QUESTION_PERIOD) { |
| 605 _resolver.reportErrorForNode( | 603 _resolver.reportErrorForNode( |
| 606 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, | 604 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, |
| 607 target, | 605 target, |
| 608 [(target as SimpleIdentifier).name]); | 606 [(target as SimpleIdentifier).name]); |
| 609 } | 607 } |
| 610 LibraryElement importedLibrary = _getImportedLibrary(target); | 608 LibraryElement importedLibrary = _getImportedLibrary(target); |
| 611 methodName.staticElement = importedLibrary.loadLibraryFunction; | 609 methodName.staticElement = importedLibrary.loadLibraryFunction; |
| 612 return null; | 610 return null; |
| 613 } else { | 611 } else { |
| 614 staticType = _getStaticType(target); | |
| 615 propagatedType = _getPropagatedType(target); | |
| 616 // | 612 // |
| 617 // If this method invocation is of the form 'C.m' where 'C' is a class, | 613 // If this method invocation is of the form 'C.m' where 'C' is a class, |
| 618 // then we don't call resolveInvokedElement(...) which walks up the class | 614 // then we don't call resolveInvokedElement(...) which walks up the class |
| 619 // hierarchy, instead we just look for the member in the type only. This | 615 // hierarchy, instead we just look for the member in the type only. This |
| 620 // does not apply to conditional method invocation (i.e. 'C?.m(...)'). | 616 // does not apply to conditional method invocation (i.e. 'C?.m(...)'). |
| 621 // | 617 // |
| 622 bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD; | 618 bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD; |
| 623 ClassElementImpl typeReference = getTypeReference(target); | 619 ClassElementImpl typeReference = getTypeReference(target); |
| 624 if (typeReference != null) { | 620 if (typeReference != null) { |
| 621 if (node.isCascaded) { |
| 622 typeReference = _typeType.element; |
| 623 } |
| 625 staticElement = _resolveElement(typeReference, methodName); | 624 staticElement = _resolveElement(typeReference, methodName); |
| 626 } else { | 625 } else { |
| 626 DartType staticType = _getStaticType(target); |
| 627 DartType propagatedType = _getPropagatedType(target); |
| 627 staticElement = _resolveInvokedElementWithTarget( | 628 staticElement = _resolveInvokedElementWithTarget( |
| 628 target, staticType, methodName, isConditional); | 629 target, staticType, methodName, isConditional); |
| 629 // If we have propagated type information use it (since it should | 630 // If we have propagated type information use it (since it should |
| 630 // not be redundant with the staticType). Otherwise, don't produce | 631 // not be redundant with the staticType). Otherwise, don't produce |
| 631 // a propagatedElement which duplicates the staticElement. | 632 // a propagatedElement which duplicates the staticElement. |
| 632 if (propagatedType is InterfaceType) { | 633 if (propagatedType is InterfaceType) { |
| 633 propagatedElement = _resolveInvokedElementWithTarget( | 634 propagatedElement = _resolveInvokedElementWithTarget( |
| 634 target, propagatedType, methodName, isConditional); | 635 target, propagatedType, methodName, isConditional); |
| 635 } | 636 } |
| 636 } | 637 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 } | 767 } |
| 767 if (!_enableStrictCallChecks && | 768 if (!_enableStrictCallChecks && |
| 768 targetType != null && | 769 targetType != null && |
| 769 targetType.isDartCoreFunction && | 770 targetType.isDartCoreFunction && |
| 770 methodName.name == FunctionElement.CALL_METHOD_NAME) { | 771 methodName.name == FunctionElement.CALL_METHOD_NAME) { |
| 771 // TODO(brianwilkerson) Can we ever resolve the function being | 772 // TODO(brianwilkerson) Can we ever resolve the function being |
| 772 // invoked? | 773 // invoked? |
| 773 // resolveArgumentsToParameters(node.getArgumentList(), invokedFunction
); | 774 // resolveArgumentsToParameters(node.getArgumentList(), invokedFunction
); |
| 774 return null; | 775 return null; |
| 775 } | 776 } |
| 776 ClassElementImpl typeReference = getTypeReference(target); | 777 if (!node.isCascaded) { |
| 777 if (typeReference != null) { | 778 ClassElementImpl typeReference = getTypeReference(target); |
| 778 ConstructorElement constructor = | 779 if (typeReference != null) { |
| 779 typeReference.getNamedConstructor(methodName.name); | 780 ConstructorElement constructor = |
| 780 if (constructor != null) { | 781 typeReference.getNamedConstructor(methodName.name); |
| 781 _recordUndefinedNode( | 782 if (constructor != null) { |
| 782 typeReference, | 783 _recordUndefinedNode( |
| 783 StaticTypeWarningCode.UNDEFINED_METHOD_WITH_CONSTRUCTOR, | 784 typeReference, |
| 784 methodName, | 785 StaticTypeWarningCode.UNDEFINED_METHOD_WITH_CONSTRUCTOR, |
| 785 [methodName.name, typeReference.name]); | 786 methodName, |
| 786 return null; | 787 [methodName.name, typeReference.name]); |
| 788 return null; |
| 789 } |
| 787 } | 790 } |
| 788 } | 791 } |
| 789 targetTypeName = targetType == null ? null : targetType.displayName; | 792 targetTypeName = targetType == null ? null : targetType.displayName; |
| 790 ErrorCode proxyErrorCode = (generatedWithTypePropagation | 793 ErrorCode proxyErrorCode = (generatedWithTypePropagation |
| 791 ? HintCode.UNDEFINED_METHOD | 794 ? HintCode.UNDEFINED_METHOD |
| 792 : StaticTypeWarningCode.UNDEFINED_METHOD); | 795 : StaticTypeWarningCode.UNDEFINED_METHOD); |
| 793 _recordUndefinedNode(targetType.element, proxyErrorCode, methodName, | 796 _recordUndefinedNode(targetType.element, proxyErrorCode, methodName, |
| 794 [methodName.name, targetTypeName]); | 797 [methodName.name, targetTypeName]); |
| 795 } | 798 } |
| 796 } else if (identical( | 799 } else if (identical( |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 } | 919 } |
| 917 // May be annotation, resolve invocation of "const" constructor. | 920 // May be annotation, resolve invocation of "const" constructor. |
| 918 if (node.parent is Annotation) { | 921 if (node.parent is Annotation) { |
| 919 Annotation annotation = node.parent as Annotation; | 922 Annotation annotation = node.parent as Annotation; |
| 920 _resolveAnnotationElement(annotation); | 923 _resolveAnnotationElement(annotation); |
| 921 } | 924 } |
| 922 // | 925 // |
| 923 // Otherwise, the prefix is really an expression that happens to be a simple | 926 // Otherwise, the prefix is really an expression that happens to be a simple |
| 924 // identifier and this is really equivalent to a property access node. | 927 // identifier and this is really equivalent to a property access node. |
| 925 // | 928 // |
| 926 _resolvePropertyAccess(prefix, identifier); | 929 _resolvePropertyAccess(prefix, identifier, false); |
| 927 return null; | 930 return null; |
| 928 } | 931 } |
| 929 | 932 |
| 930 @override | 933 @override |
| 931 Object visitPrefixExpression(PrefixExpression node) { | 934 Object visitPrefixExpression(PrefixExpression node) { |
| 932 sc.Token operator = node.operator; | 935 sc.Token operator = node.operator; |
| 933 sc.TokenType operatorType = operator.type; | 936 sc.TokenType operatorType = operator.type; |
| 934 if (operatorType.isUserDefinableOperator || | 937 if (operatorType.isUserDefinableOperator || |
| 935 operatorType == sc.TokenType.PLUS_PLUS || | 938 operatorType == sc.TokenType.PLUS_PLUS || |
| 936 operatorType == sc.TokenType.MINUS_MINUS) { | 939 operatorType == sc.TokenType.MINUS_MINUS) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 972 return null; | 975 return null; |
| 973 } | 976 } |
| 974 | 977 |
| 975 @override | 978 @override |
| 976 Object visitPropertyAccess(PropertyAccess node) { | 979 Object visitPropertyAccess(PropertyAccess node) { |
| 977 Expression target = node.realTarget; | 980 Expression target = node.realTarget; |
| 978 if (target is SuperExpression && !_isSuperInValidContext(target)) { | 981 if (target is SuperExpression && !_isSuperInValidContext(target)) { |
| 979 return null; | 982 return null; |
| 980 } | 983 } |
| 981 SimpleIdentifier propertyName = node.propertyName; | 984 SimpleIdentifier propertyName = node.propertyName; |
| 982 _resolvePropertyAccess(target, propertyName); | 985 _resolvePropertyAccess(target, propertyName, node.isCascaded); |
| 983 return null; | 986 return null; |
| 984 } | 987 } |
| 985 | 988 |
| 986 @override | 989 @override |
| 987 Object visitRedirectingConstructorInvocation( | 990 Object visitRedirectingConstructorInvocation( |
| 988 RedirectingConstructorInvocation node) { | 991 RedirectingConstructorInvocation node) { |
| 989 ClassElement enclosingClass = _resolver.enclosingClass; | 992 ClassElement enclosingClass = _resolver.enclosingClass; |
| 990 if (enclosingClass == null) { | 993 if (enclosingClass == null) { |
| 991 // TODO(brianwilkerson) Report this error. | 994 // TODO(brianwilkerson) Report this error. |
| 992 return null; | 995 return null; |
| (...skipping 1251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2244 if (memberElement == null) { | 2247 if (memberElement == null) { |
| 2245 memberElement = _lookUpGetter(target, targetType, propertyName.name); | 2248 memberElement = _lookUpGetter(target, targetType, propertyName.name); |
| 2246 } | 2249 } |
| 2247 if (memberElement == null) { | 2250 if (memberElement == null) { |
| 2248 memberElement = _lookUpMethod(target, targetType, propertyName.name); | 2251 memberElement = _lookUpMethod(target, targetType, propertyName.name); |
| 2249 } | 2252 } |
| 2250 return memberElement; | 2253 return memberElement; |
| 2251 } | 2254 } |
| 2252 | 2255 |
| 2253 void _resolvePropertyAccess( | 2256 void _resolvePropertyAccess( |
| 2254 Expression target, SimpleIdentifier propertyName) { | 2257 Expression target, SimpleIdentifier propertyName, bool isCascaded) { |
| 2255 DartType staticType = _getStaticType(target); | 2258 DartType staticType = _getStaticType(target); |
| 2256 DartType propagatedType = _getPropagatedType(target); | 2259 DartType propagatedType = _getPropagatedType(target); |
| 2257 Element staticElement = null; | 2260 Element staticElement = null; |
| 2258 Element propagatedElement = null; | 2261 Element propagatedElement = null; |
| 2259 // | 2262 // |
| 2260 // If this property access is of the form 'C.m' where 'C' is a class, | 2263 // If this property access is of the form 'C.m' where 'C' is a class, |
| 2261 // then we don't call resolveProperty(...) which walks up the class | 2264 // then we don't call resolveProperty(...) which walks up the class |
| 2262 // hierarchy, instead we just look for the member in the type only. This | 2265 // hierarchy, instead we just look for the member in the type only. This |
| 2263 // does not apply to conditional property accesses (i.e. 'C?.m'). | 2266 // does not apply to conditional property accesses (i.e. 'C?.m'). |
| 2264 // | 2267 // |
| 2265 ClassElementImpl typeReference = getTypeReference(target); | 2268 ClassElementImpl typeReference = getTypeReference(target); |
| 2266 if (typeReference != null) { | 2269 if (typeReference != null) { |
| 2270 if (isCascaded) { |
| 2271 typeReference = _typeType.element; |
| 2272 } |
| 2267 // TODO(brianwilkerson) Why are we setting the propagated element here? | 2273 // TODO(brianwilkerson) Why are we setting the propagated element here? |
| 2268 // It looks wrong. | 2274 // It looks wrong. |
| 2269 staticElement = | 2275 staticElement = |
| 2270 propagatedElement = _resolveElement(typeReference, propertyName); | 2276 propagatedElement = _resolveElement(typeReference, propertyName); |
| 2271 } else { | 2277 } else { |
| 2272 staticElement = _resolveProperty(target, staticType, propertyName); | 2278 staticElement = _resolveProperty(target, staticType, propertyName); |
| 2273 propagatedElement = | 2279 propagatedElement = |
| 2274 _resolveProperty(target, propagatedType, propertyName); | 2280 _resolveProperty(target, propagatedType, propertyName); |
| 2275 } | 2281 } |
| 2276 // May be part of annotation, record property element only if exists. | 2282 // May be part of annotation, record property element only if exists. |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2635 | 2641 |
| 2636 @override | 2642 @override |
| 2637 Element get staticElement => null; | 2643 Element get staticElement => null; |
| 2638 | 2644 |
| 2639 @override | 2645 @override |
| 2640 accept(AstVisitor visitor) => null; | 2646 accept(AstVisitor visitor) => null; |
| 2641 | 2647 |
| 2642 @override | 2648 @override |
| 2643 void visitChildren(AstVisitor visitor) {} | 2649 void visitChildren(AstVisitor visitor) {} |
| 2644 } | 2650 } |
| OLD | NEW |