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 |