| 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.resolver.element_resolver; | 5 library engine.resolver.element_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 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 if (operator.isUserDefinableOperator) { | 169 if (operator.isUserDefinableOperator) { |
| 170 _resolveBinaryExpression(node, operator.lexeme); | 170 _resolveBinaryExpression(node, operator.lexeme); |
| 171 } else if (operator.type == sc.TokenType.BANG_EQ) { | 171 } else if (operator.type == sc.TokenType.BANG_EQ) { |
| 172 _resolveBinaryExpression(node, sc.TokenType.EQ_EQ.lexeme); | 172 _resolveBinaryExpression(node, sc.TokenType.EQ_EQ.lexeme); |
| 173 } | 173 } |
| 174 return null; | 174 return null; |
| 175 } | 175 } |
| 176 | 176 |
| 177 @override | 177 @override |
| 178 Object visitBreakStatement(BreakStatement node) { | 178 Object visitBreakStatement(BreakStatement node) { |
| 179 _lookupLabel(node, node.label); | 179 node.target = _lookupBreakOrContinueTarget(node, node.label, false); |
| 180 return null; | 180 return null; |
| 181 } | 181 } |
| 182 | 182 |
| 183 @override | 183 @override |
| 184 Object visitClassDeclaration(ClassDeclaration node) { | 184 Object visitClassDeclaration(ClassDeclaration node) { |
| 185 _setMetadata(node.element, node); | 185 _setMetadata(node.element, node); |
| 186 return null; | 186 return null; |
| 187 } | 187 } |
| 188 | 188 |
| 189 @override | 189 @override |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 constructor = | 360 constructor = |
| 361 interfaceType.lookUpConstructor(name.name, _definingLibrary); | 361 interfaceType.lookUpConstructor(name.name, _definingLibrary); |
| 362 name.staticElement = constructor; | 362 name.staticElement = constructor; |
| 363 } | 363 } |
| 364 node.staticElement = constructor; | 364 node.staticElement = constructor; |
| 365 return null; | 365 return null; |
| 366 } | 366 } |
| 367 | 367 |
| 368 @override | 368 @override |
| 369 Object visitContinueStatement(ContinueStatement node) { | 369 Object visitContinueStatement(ContinueStatement node) { |
| 370 _lookupLabel(node, node.label); | 370 node.target = _lookupBreakOrContinueTarget(node, node.label, true); |
| 371 return null; | 371 return null; |
| 372 } | 372 } |
| 373 | 373 |
| 374 @override | 374 @override |
| 375 Object visitDeclaredIdentifier(DeclaredIdentifier node) { | 375 Object visitDeclaredIdentifier(DeclaredIdentifier node) { |
| 376 _setMetadata(node.element, node); | 376 _setMetadata(node.element, node); |
| 377 return null; | 377 return null; |
| 378 } | 378 } |
| 379 | 379 |
| 380 @override | 380 @override |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 _recordUndefinedToken( | 795 _recordUndefinedToken( |
| 796 propagatedType.element, | 796 propagatedType.element, |
| 797 HintCode.UNDEFINED_OPERATOR, | 797 HintCode.UNDEFINED_OPERATOR, |
| 798 node.operator, | 798 node.operator, |
| 799 [methodName, propagatedType.displayName]); | 799 [methodName, propagatedType.displayName]); |
| 800 } | 800 } |
| 801 return null; | 801 return null; |
| 802 } | 802 } |
| 803 | 803 |
| 804 @override | 804 @override |
| 805 Object visitPrefixExpression(PrefixExpression node) { | |
| 806 sc.Token operator = node.operator; | |
| 807 sc.TokenType operatorType = operator.type; | |
| 808 if (operatorType.isUserDefinableOperator || | |
| 809 operatorType == sc.TokenType.PLUS_PLUS || | |
| 810 operatorType == sc.TokenType.MINUS_MINUS) { | |
| 811 Expression operand = node.operand; | |
| 812 String methodName = _getPrefixOperator(node); | |
| 813 DartType staticType = _getStaticType(operand); | |
| 814 MethodElement staticMethod = | |
| 815 _lookUpMethod(operand, staticType, methodName); | |
| 816 node.staticElement = staticMethod; | |
| 817 DartType propagatedType = _getPropagatedType(operand); | |
| 818 MethodElement propagatedMethod = | |
| 819 _lookUpMethod(operand, propagatedType, methodName); | |
| 820 node.propagatedElement = propagatedMethod; | |
| 821 if (_shouldReportMissingMember(staticType, staticMethod)) { | |
| 822 _recordUndefinedToken( | |
| 823 staticType.element, | |
| 824 StaticTypeWarningCode.UNDEFINED_OPERATOR, | |
| 825 operator, | |
| 826 [methodName, staticType.displayName]); | |
| 827 } else if (_enableHints && | |
| 828 _shouldReportMissingMember(propagatedType, propagatedMethod) && | |
| 829 !_memberFoundInSubclass(propagatedType.element, methodName, true, fals
e)) { | |
| 830 _recordUndefinedToken( | |
| 831 propagatedType.element, | |
| 832 HintCode.UNDEFINED_OPERATOR, | |
| 833 operator, | |
| 834 [methodName, propagatedType.displayName]); | |
| 835 } | |
| 836 } | |
| 837 return null; | |
| 838 } | |
| 839 | |
| 840 @override | |
| 841 Object visitPrefixedIdentifier(PrefixedIdentifier node) { | 805 Object visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 842 SimpleIdentifier prefix = node.prefix; | 806 SimpleIdentifier prefix = node.prefix; |
| 843 SimpleIdentifier identifier = node.identifier; | 807 SimpleIdentifier identifier = node.identifier; |
| 844 // | 808 // |
| 845 // First, check the "lib.loadLibrary" case | 809 // First, check the "lib.loadLibrary" case |
| 846 // | 810 // |
| 847 if (identifier.name == FunctionElement.LOAD_LIBRARY_NAME && | 811 if (identifier.name == FunctionElement.LOAD_LIBRARY_NAME && |
| 848 _isDeferredPrefix(prefix)) { | 812 _isDeferredPrefix(prefix)) { |
| 849 LibraryElement importedLibrary = _getImportedLibrary(prefix); | 813 LibraryElement importedLibrary = _getImportedLibrary(prefix); |
| 850 identifier.staticElement = importedLibrary.loadLibraryFunction; | 814 identifier.staticElement = importedLibrary.loadLibraryFunction; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 909 } | 873 } |
| 910 // | 874 // |
| 911 // Otherwise, the prefix is really an expression that happens to be a simple | 875 // Otherwise, the prefix is really an expression that happens to be a simple |
| 912 // identifier and this is really equivalent to a property access node. | 876 // identifier and this is really equivalent to a property access node. |
| 913 // | 877 // |
| 914 _resolvePropertyAccess(prefix, identifier); | 878 _resolvePropertyAccess(prefix, identifier); |
| 915 return null; | 879 return null; |
| 916 } | 880 } |
| 917 | 881 |
| 918 @override | 882 @override |
| 883 Object visitPrefixExpression(PrefixExpression node) { |
| 884 sc.Token operator = node.operator; |
| 885 sc.TokenType operatorType = operator.type; |
| 886 if (operatorType.isUserDefinableOperator || |
| 887 operatorType == sc.TokenType.PLUS_PLUS || |
| 888 operatorType == sc.TokenType.MINUS_MINUS) { |
| 889 Expression operand = node.operand; |
| 890 String methodName = _getPrefixOperator(node); |
| 891 DartType staticType = _getStaticType(operand); |
| 892 MethodElement staticMethod = |
| 893 _lookUpMethod(operand, staticType, methodName); |
| 894 node.staticElement = staticMethod; |
| 895 DartType propagatedType = _getPropagatedType(operand); |
| 896 MethodElement propagatedMethod = |
| 897 _lookUpMethod(operand, propagatedType, methodName); |
| 898 node.propagatedElement = propagatedMethod; |
| 899 if (_shouldReportMissingMember(staticType, staticMethod)) { |
| 900 _recordUndefinedToken( |
| 901 staticType.element, |
| 902 StaticTypeWarningCode.UNDEFINED_OPERATOR, |
| 903 operator, |
| 904 [methodName, staticType.displayName]); |
| 905 } else if (_enableHints && |
| 906 _shouldReportMissingMember(propagatedType, propagatedMethod) && |
| 907 !_memberFoundInSubclass(propagatedType.element, methodName, true, fals
e)) { |
| 908 _recordUndefinedToken( |
| 909 propagatedType.element, |
| 910 HintCode.UNDEFINED_OPERATOR, |
| 911 operator, |
| 912 [methodName, propagatedType.displayName]); |
| 913 } |
| 914 } |
| 915 return null; |
| 916 } |
| 917 |
| 918 @override |
| 919 Object visitPropertyAccess(PropertyAccess node) { | 919 Object visitPropertyAccess(PropertyAccess node) { |
| 920 Expression target = node.realTarget; | 920 Expression target = node.realTarget; |
| 921 if (target is SuperExpression && !_isSuperInValidContext(target)) { | 921 if (target is SuperExpression && !_isSuperInValidContext(target)) { |
| 922 return null; | 922 return null; |
| 923 } | 923 } |
| 924 SimpleIdentifier propertyName = node.propertyName; | 924 SimpleIdentifier propertyName = node.propertyName; |
| 925 _resolvePropertyAccess(target, propertyName); | 925 _resolvePropertyAccess(target, propertyName); |
| 926 return null; | 926 return null; |
| 927 } | 927 } |
| 928 | 928 |
| (...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1567 return identical(parent.prefix, node); | 1567 return identical(parent.prefix, node); |
| 1568 } else if (parent is PrefixedIdentifier) { | 1568 } else if (parent is PrefixedIdentifier) { |
| 1569 return true; | 1569 return true; |
| 1570 } else if (parent is MethodInvocation) { | 1570 } else if (parent is MethodInvocation) { |
| 1571 return identical(parent.target, node); | 1571 return identical(parent.target, node); |
| 1572 } | 1572 } |
| 1573 return false; | 1573 return false; |
| 1574 } | 1574 } |
| 1575 | 1575 |
| 1576 /** | 1576 /** |
| 1577 * Return the target of a break or continue statement, and update the static |
| 1578 * element of its label (if any). [parentNode] is the AST node of the break |
| 1579 * or continue statement, [labelNode] is the label contained in that |
| 1580 * statement (if any), and [isContinue] is true if the node being visited is |
| 1581 * a continue statement. |
| 1582 */ |
| 1583 AstNode _lookupBreakOrContinueTarget(AstNode parentNode, |
| 1584 SimpleIdentifier labelNode, bool isContinue) { |
| 1585 if (labelNode == null) { |
| 1586 return _resolver.getUnlabeledBreakOrContinueTarget(isContinue); |
| 1587 } else { |
| 1588 LabelScope labelScope = _resolver.labelScope; |
| 1589 if (labelScope == null) { |
| 1590 // There are no labels in scope, so by definition the label is |
| 1591 // undefined. |
| 1592 _resolver.reportErrorForNode( |
| 1593 CompileTimeErrorCode.LABEL_UNDEFINED, |
| 1594 labelNode, |
| 1595 [labelNode.name]); |
| 1596 return null; |
| 1597 } |
| 1598 LabelScope definingScope = labelScope.lookup(labelNode.name); |
| 1599 if (definingScope == null) { |
| 1600 // No definition of the given label name could be found in any |
| 1601 // enclosing scope. |
| 1602 _resolver.reportErrorForNode( |
| 1603 CompileTimeErrorCode.LABEL_UNDEFINED, |
| 1604 labelNode, |
| 1605 [labelNode.name]); |
| 1606 return null; |
| 1607 } |
| 1608 // The target has been found. |
| 1609 labelNode.staticElement = definingScope.element; |
| 1610 ExecutableElement labelContainer = |
| 1611 definingScope.element.getAncestor((element) => element is ExecutableEl
ement); |
| 1612 if (!identical(labelContainer, _resolver.enclosingFunction)) { |
| 1613 _resolver.reportErrorForNode( |
| 1614 CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE, |
| 1615 labelNode, |
| 1616 [labelNode.name]); |
| 1617 } |
| 1618 return definingScope.node; |
| 1619 } |
| 1620 } |
| 1621 |
| 1622 /** |
| 1577 * Look up the getter with the given name in the given type. Return the elemen
t representing the | 1623 * Look up the getter with the given name in the given type. Return the elemen
t representing the |
| 1578 * getter that was found, or `null` if there is no getter with the given name. | 1624 * getter that was found, or `null` if there is no getter with the given name. |
| 1579 * | 1625 * |
| 1580 * @param target the target of the invocation, or `null` if there is no target | 1626 * @param target the target of the invocation, or `null` if there is no target |
| 1581 * @param type the type in which the getter is defined | 1627 * @param type the type in which the getter is defined |
| 1582 * @param getterName the name of the getter being looked up | 1628 * @param getterName the name of the getter being looked up |
| 1583 * @return the element representing the getter that was found | 1629 * @return the element representing the getter that was found |
| 1584 */ | 1630 */ |
| 1585 PropertyAccessorElement _lookUpGetter(Expression target, DartType type, | 1631 PropertyAccessorElement _lookUpGetter(Expression target, DartType type, |
| 1586 String getterName) { | 1632 String getterName) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 return null; | 1701 return null; |
| 1656 } | 1702 } |
| 1657 return _lookUpGetterInInterfaces( | 1703 return _lookUpGetterInInterfaces( |
| 1658 superclass, | 1704 superclass, |
| 1659 true, | 1705 true, |
| 1660 getterName, | 1706 getterName, |
| 1661 visitedInterfaces); | 1707 visitedInterfaces); |
| 1662 } | 1708 } |
| 1663 | 1709 |
| 1664 /** | 1710 /** |
| 1711 * Look up the method or getter with the given name in the given type. Return
the element |
| 1712 * representing the method or getter that was found, or `null` if there is no
method or |
| 1713 * getter with the given name. |
| 1714 * |
| 1715 * @param type the type in which the method or getter is defined |
| 1716 * @param memberName the name of the method or getter being looked up |
| 1717 * @return the element representing the method or getter that was found |
| 1718 */ |
| 1719 ExecutableElement _lookupGetterOrMethod(DartType type, String memberName) { |
| 1720 type = _resolveTypeParameter(type); |
| 1721 if (type is InterfaceType) { |
| 1722 InterfaceType interfaceType = type; |
| 1723 ExecutableElement member = |
| 1724 interfaceType.lookUpMethod(memberName, _definingLibrary); |
| 1725 if (member != null) { |
| 1726 return member; |
| 1727 } |
| 1728 member = interfaceType.lookUpGetter(memberName, _definingLibrary); |
| 1729 if (member != null) { |
| 1730 return member; |
| 1731 } |
| 1732 return _lookUpGetterOrMethodInInterfaces( |
| 1733 interfaceType, |
| 1734 false, |
| 1735 memberName, |
| 1736 new HashSet<ClassElement>()); |
| 1737 } |
| 1738 return null; |
| 1739 } |
| 1740 |
| 1741 /** |
| 1665 * Look up the method or getter with the given name in the interfaces implemen
ted by the given | 1742 * Look up the method or getter with the given name in the interfaces implemen
ted by the given |
| 1666 * type, either directly or indirectly. Return the element representing the me
thod or getter that | 1743 * type, either directly or indirectly. Return the element representing the me
thod or getter that |
| 1667 * was found, or `null` if there is no method or getter with the given name. | 1744 * was found, or `null` if there is no method or getter with the given name. |
| 1668 * | 1745 * |
| 1669 * @param targetType the type in which the method or getter might be defined | 1746 * @param targetType the type in which the method or getter might be defined |
| 1670 * @param includeTargetType `true` if the search should include the target typ
e | 1747 * @param includeTargetType `true` if the search should include the target typ
e |
| 1671 * @param memberName the name of the method or getter being looked up | 1748 * @param memberName the name of the method or getter being looked up |
| 1672 * @param visitedInterfaces a set containing all of the interfaces that have b
een examined, used | 1749 * @param visitedInterfaces a set containing all of the interfaces that have b
een examined, used |
| 1673 * to prevent infinite recursion and to optimize the search | 1750 * to prevent infinite recursion and to optimize the search |
| 1674 * @return the element representing the method or getter that was found | 1751 * @return the element representing the method or getter that was found |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1815 return null; | 1892 return null; |
| 1816 } | 1893 } |
| 1817 return _lookUpMethodInInterfaces( | 1894 return _lookUpMethodInInterfaces( |
| 1818 superclass, | 1895 superclass, |
| 1819 true, | 1896 true, |
| 1820 methodName, | 1897 methodName, |
| 1821 visitedInterfaces); | 1898 visitedInterfaces); |
| 1822 } | 1899 } |
| 1823 | 1900 |
| 1824 /** | 1901 /** |
| 1902 * Look up all methods of a given name defined on a union type. |
| 1903 * |
| 1904 * @param target |
| 1905 * @param type |
| 1906 * @param methodName |
| 1907 * @return all methods named `methodName` defined on the union type `type`. |
| 1908 */ |
| 1909 Set<ExecutableElement> _lookupMethods(Expression target, UnionType type, |
| 1910 String methodName) { |
| 1911 Set<ExecutableElement> methods = new HashSet<ExecutableElement>(); |
| 1912 bool allElementsHaveMethod = true; |
| 1913 for (DartType t in type.elements) { |
| 1914 MethodElement m = _lookUpMethod(target, t, methodName); |
| 1915 if (m != null) { |
| 1916 methods.add(m); |
| 1917 } else { |
| 1918 allElementsHaveMethod = false; |
| 1919 } |
| 1920 } |
| 1921 // For strict union types we require that all types in the union define the |
| 1922 // method. |
| 1923 if (AnalysisEngine.instance.strictUnionTypes) { |
| 1924 if (allElementsHaveMethod) { |
| 1925 return methods; |
| 1926 } else { |
| 1927 return new Set<ExecutableElement>(); |
| 1928 } |
| 1929 } else { |
| 1930 return methods; |
| 1931 } |
| 1932 } |
| 1933 |
| 1934 /** |
| 1825 * Look up the setter with the given name in the given type. Return the elemen
t representing the | 1935 * Look up the setter with the given name in the given type. Return the elemen
t representing the |
| 1826 * setter that was found, or `null` if there is no setter with the given name. | 1936 * setter that was found, or `null` if there is no setter with the given name. |
| 1827 * | 1937 * |
| 1828 * @param target the target of the invocation, or `null` if there is no target | 1938 * @param target the target of the invocation, or `null` if there is no target |
| 1829 * @param type the type in which the setter is defined | 1939 * @param type the type in which the setter is defined |
| 1830 * @param setterName the name of the setter being looked up | 1940 * @param setterName the name of the setter being looked up |
| 1831 * @return the element representing the setter that was found | 1941 * @return the element representing the setter that was found |
| 1832 */ | 1942 */ |
| 1833 PropertyAccessorElement _lookUpSetter(Expression target, DartType type, | 1943 PropertyAccessorElement _lookUpSetter(Expression target, DartType type, |
| 1834 String setterName) { | 1944 String setterName) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1903 return null; | 2013 return null; |
| 1904 } | 2014 } |
| 1905 return _lookUpSetterInInterfaces( | 2015 return _lookUpSetterInInterfaces( |
| 1906 superclass, | 2016 superclass, |
| 1907 true, | 2017 true, |
| 1908 setterName, | 2018 setterName, |
| 1909 visitedInterfaces); | 2019 visitedInterfaces); |
| 1910 } | 2020 } |
| 1911 | 2021 |
| 1912 /** | 2022 /** |
| 1913 * Look up the method or getter with the given name in the given type. Return
the element | |
| 1914 * representing the method or getter that was found, or `null` if there is no
method or | |
| 1915 * getter with the given name. | |
| 1916 * | |
| 1917 * @param type the type in which the method or getter is defined | |
| 1918 * @param memberName the name of the method or getter being looked up | |
| 1919 * @return the element representing the method or getter that was found | |
| 1920 */ | |
| 1921 ExecutableElement _lookupGetterOrMethod(DartType type, String memberName) { | |
| 1922 type = _resolveTypeParameter(type); | |
| 1923 if (type is InterfaceType) { | |
| 1924 InterfaceType interfaceType = type; | |
| 1925 ExecutableElement member = | |
| 1926 interfaceType.lookUpMethod(memberName, _definingLibrary); | |
| 1927 if (member != null) { | |
| 1928 return member; | |
| 1929 } | |
| 1930 member = interfaceType.lookUpGetter(memberName, _definingLibrary); | |
| 1931 if (member != null) { | |
| 1932 return member; | |
| 1933 } | |
| 1934 return _lookUpGetterOrMethodInInterfaces( | |
| 1935 interfaceType, | |
| 1936 false, | |
| 1937 memberName, | |
| 1938 new HashSet<ClassElement>()); | |
| 1939 } | |
| 1940 return null; | |
| 1941 } | |
| 1942 | |
| 1943 /** | |
| 1944 * Find the element corresponding to the given label node in the current label
scope. | |
| 1945 * | |
| 1946 * @param parentNode the node containing the given label | |
| 1947 * @param labelNode the node representing the label being looked up | |
| 1948 * @return the element corresponding to the given label node in the current sc
ope | |
| 1949 */ | |
| 1950 LabelElementImpl _lookupLabel(AstNode parentNode, | |
| 1951 SimpleIdentifier labelNode) { | |
| 1952 LabelScope labelScope = _resolver.labelScope; | |
| 1953 LabelElementImpl labelElement = null; | |
| 1954 if (labelNode == null) { | |
| 1955 if (labelScope == null) { | |
| 1956 // TODO(brianwilkerson) Do we need to report this error, or is this | |
| 1957 // condition always caught in the parser? | |
| 1958 // reportError(ResolverErrorCode.BREAK_OUTSIDE_LOOP); | |
| 1959 } else { | |
| 1960 labelElement = | |
| 1961 labelScope.lookup(LabelScope.EMPTY_LABEL) as LabelElementImpl; | |
| 1962 if (labelElement == null) { | |
| 1963 // TODO(brianwilkerson) Do we need to report this error, or is this | |
| 1964 // condition always caught in the parser? | |
| 1965 // reportError(ResolverErrorCode.BREAK_OUTSIDE_LOOP); | |
| 1966 } | |
| 1967 // | |
| 1968 // The label element that was returned was a marker for look-up and | |
| 1969 // isn't stored in the element model. | |
| 1970 // | |
| 1971 labelElement = null; | |
| 1972 } | |
| 1973 } else { | |
| 1974 if (labelScope == null) { | |
| 1975 _resolver.reportErrorForNode( | |
| 1976 CompileTimeErrorCode.LABEL_UNDEFINED, | |
| 1977 labelNode, | |
| 1978 [labelNode.name]); | |
| 1979 } else { | |
| 1980 labelElement = labelScope.lookup(labelNode.name) as LabelElementImpl; | |
| 1981 if (labelElement == null) { | |
| 1982 _resolver.reportErrorForNode( | |
| 1983 CompileTimeErrorCode.LABEL_UNDEFINED, | |
| 1984 labelNode, | |
| 1985 [labelNode.name]); | |
| 1986 } else { | |
| 1987 labelNode.staticElement = labelElement; | |
| 1988 } | |
| 1989 } | |
| 1990 } | |
| 1991 if (labelElement != null) { | |
| 1992 ExecutableElement labelContainer = | |
| 1993 labelElement.getAncestor((element) => element is ExecutableElement); | |
| 1994 if (!identical(labelContainer, _resolver.enclosingFunction)) { | |
| 1995 _resolver.reportErrorForNode( | |
| 1996 CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE, | |
| 1997 labelNode, | |
| 1998 [labelNode.name]); | |
| 1999 labelElement = null; | |
| 2000 } | |
| 2001 } | |
| 2002 return labelElement; | |
| 2003 } | |
| 2004 | |
| 2005 /** | |
| 2006 * Look up all methods of a given name defined on a union type. | |
| 2007 * | |
| 2008 * @param target | |
| 2009 * @param type | |
| 2010 * @param methodName | |
| 2011 * @return all methods named `methodName` defined on the union type `type`. | |
| 2012 */ | |
| 2013 Set<ExecutableElement> _lookupMethods(Expression target, UnionType type, | |
| 2014 String methodName) { | |
| 2015 Set<ExecutableElement> methods = new HashSet<ExecutableElement>(); | |
| 2016 bool allElementsHaveMethod = true; | |
| 2017 for (DartType t in type.elements) { | |
| 2018 MethodElement m = _lookUpMethod(target, t, methodName); | |
| 2019 if (m != null) { | |
| 2020 methods.add(m); | |
| 2021 } else { | |
| 2022 allElementsHaveMethod = false; | |
| 2023 } | |
| 2024 } | |
| 2025 // For strict union types we require that all types in the union define the | |
| 2026 // method. | |
| 2027 if (AnalysisEngine.instance.strictUnionTypes) { | |
| 2028 if (allElementsHaveMethod) { | |
| 2029 return methods; | |
| 2030 } else { | |
| 2031 return new Set<ExecutableElement>(); | |
| 2032 } | |
| 2033 } else { | |
| 2034 return methods; | |
| 2035 } | |
| 2036 } | |
| 2037 | |
| 2038 /** | |
| 2039 * Given some class element, this method uses [subtypeManager] to find the set
of all | 2023 * Given some class element, this method uses [subtypeManager] to find the set
of all |
| 2040 * subtypes; the subtypes are then searched for a member (method, getter, or s
etter), that matches | 2024 * subtypes; the subtypes are then searched for a member (method, getter, or s
etter), that matches |
| 2041 * a passed | 2025 * a passed |
| 2042 * | 2026 * |
| 2043 * @param element the class element to search the subtypes of, if a non-ClassE
lement element is | 2027 * @param element the class element to search the subtypes of, if a non-ClassE
lement element is |
| 2044 * passed, then `false` is returned | 2028 * passed, then `false` is returned |
| 2045 * @param memberName the member name to search for | 2029 * @param memberName the member name to search for |
| 2046 * @param asMethod `true` if the methods should be searched for in the subtype
s | 2030 * @param asMethod `true` if the methods should be searched for in the subtype
s |
| 2047 * @param asAccessor `true` if the accessors (getters and setters) should be s
earched for in | 2031 * @param asAccessor `true` if the accessors (getters and setters) should be s
earched for in |
| 2048 * the subtypes | 2032 * the subtypes |
| (...skipping 1030 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3079 @override | 3063 @override |
| 3080 Element get staticElement => null; | 3064 Element get staticElement => null; |
| 3081 | 3065 |
| 3082 @override | 3066 @override |
| 3083 accept(AstVisitor visitor) => null; | 3067 accept(AstVisitor visitor) => null; |
| 3084 | 3068 |
| 3085 @override | 3069 @override |
| 3086 void visitChildren(AstVisitor visitor) { | 3070 void visitChildren(AstVisitor visitor) { |
| 3087 } | 3071 } |
| 3088 } | 3072 } |
| OLD | NEW |