| 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 1555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1566 /** | 1566 /** |
| 1567 * Look up the getter with the given [getterName] in the given [type]. Return | 1567 * Look up the getter with the given [getterName] in the given [type]. Return |
| 1568 * the element representing the getter that was found, or `null` if there is | 1568 * the element representing the getter that was found, or `null` if there is |
| 1569 * no getter with the given name. The [target] is the target of the | 1569 * no getter with the given name. The [target] is the target of the |
| 1570 * invocation, or `null` if there is no target. | 1570 * invocation, or `null` if there is no target. |
| 1571 */ | 1571 */ |
| 1572 PropertyAccessorElement _lookUpGetter( | 1572 PropertyAccessorElement _lookUpGetter( |
| 1573 Expression target, DartType type, String getterName) { | 1573 Expression target, DartType type, String getterName) { |
| 1574 type = _resolveTypeParameter(type); | 1574 type = _resolveTypeParameter(type); |
| 1575 if (type is InterfaceType) { | 1575 if (type is InterfaceType) { |
| 1576 InterfaceType interfaceType = type; | 1576 return type.lookUpInheritedGetter(getterName, |
| 1577 PropertyAccessorElement accessor; | 1577 library: _definingLibrary, thisType: target is! SuperExpression); |
| 1578 if (target is SuperExpression) { | |
| 1579 accessor = interfaceType.lookUpGetterInSuperclass( | |
| 1580 getterName, _definingLibrary); | |
| 1581 } else { | |
| 1582 accessor = interfaceType.lookUpGetter(getterName, _definingLibrary); | |
| 1583 } | |
| 1584 if (accessor != null) { | |
| 1585 return accessor; | |
| 1586 } | |
| 1587 return _lookUpGetterInInterfaces( | |
| 1588 interfaceType, false, getterName, new HashSet<ClassElement>()); | |
| 1589 } | 1578 } |
| 1590 return null; | 1579 return null; |
| 1591 } | 1580 } |
| 1592 | 1581 |
| 1593 /** | 1582 /** |
| 1594 * Look up the getter with the given [getterName] in the interfaces | |
| 1595 * implemented by the given [targetType], either directly or indirectly. | |
| 1596 * Return the element representing the getter that was found, or `null` if | |
| 1597 * there is no getter with the given name. The flag [includeTargetType] should | |
| 1598 * be `true` if the search should include the target type. The | |
| 1599 * [visitedInterfaces] is a set containing all of the interfaces that have | |
| 1600 * been examined, used to prevent infinite recursion and to optimize the | |
| 1601 * search. | |
| 1602 */ | |
| 1603 PropertyAccessorElement _lookUpGetterInInterfaces( | |
| 1604 InterfaceType targetType, | |
| 1605 bool includeTargetType, | |
| 1606 String getterName, | |
| 1607 HashSet<ClassElement> visitedInterfaces) { | |
| 1608 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | |
| 1609 // specification (titled "Inheritance and Overriding" under "Interfaces") | |
| 1610 // describes a much more complex scheme for finding the inherited member. | |
| 1611 // We need to follow that scheme. The code below should cover the 80% case. | |
| 1612 ClassElement targetClass = targetType.element; | |
| 1613 if (visitedInterfaces.contains(targetClass)) { | |
| 1614 return null; | |
| 1615 } | |
| 1616 visitedInterfaces.add(targetClass); | |
| 1617 if (includeTargetType) { | |
| 1618 PropertyAccessorElement getter = targetType.getGetter(getterName); | |
| 1619 if (getter != null && getter.isAccessibleIn(_definingLibrary)) { | |
| 1620 return getter; | |
| 1621 } | |
| 1622 } | |
| 1623 for (InterfaceType interfaceType in targetType.interfaces) { | |
| 1624 PropertyAccessorElement getter = _lookUpGetterInInterfaces( | |
| 1625 interfaceType, true, getterName, visitedInterfaces); | |
| 1626 if (getter != null) { | |
| 1627 return getter; | |
| 1628 } | |
| 1629 } | |
| 1630 for (InterfaceType mixinType in targetType.mixins.reversed) { | |
| 1631 PropertyAccessorElement getter = _lookUpGetterInInterfaces( | |
| 1632 mixinType, true, getterName, visitedInterfaces); | |
| 1633 if (getter != null) { | |
| 1634 return getter; | |
| 1635 } | |
| 1636 } | |
| 1637 InterfaceType superclass = targetType.superclass; | |
| 1638 if (superclass == null) { | |
| 1639 return null; | |
| 1640 } | |
| 1641 return _lookUpGetterInInterfaces( | |
| 1642 superclass, true, getterName, visitedInterfaces); | |
| 1643 } | |
| 1644 | |
| 1645 /** | |
| 1646 * Look up the method or getter with the given [memberName] in the given | 1583 * Look up the method or getter with the given [memberName] in the given |
| 1647 * [type]. Return the element representing the method or getter that was | 1584 * [type]. Return the element representing the method or getter that was |
| 1648 * found, or `null` if there is no method or getter with the given name. | 1585 * found, or `null` if there is no method or getter with the given name. |
| 1649 */ | 1586 */ |
| 1650 ExecutableElement _lookupGetterOrMethod(DartType type, String memberName) { | 1587 ExecutableElement _lookupGetterOrMethod(DartType type, String memberName) { |
| 1651 type = _resolveTypeParameter(type); | 1588 type = _resolveTypeParameter(type); |
| 1652 if (type is InterfaceType) { | 1589 if (type is InterfaceType) { |
| 1653 InterfaceType interfaceType = type; | 1590 return type.lookUpInheritedGetterOrMethod(memberName, |
| 1654 ExecutableElement member = | 1591 library: _definingLibrary); |
| 1655 interfaceType.lookUpMethod(memberName, _definingLibrary); | |
| 1656 if (member != null) { | |
| 1657 return member; | |
| 1658 } | |
| 1659 member = interfaceType.lookUpGetter(memberName, _definingLibrary); | |
| 1660 if (member != null) { | |
| 1661 return member; | |
| 1662 } | |
| 1663 return _lookUpGetterOrMethodInInterfaces( | |
| 1664 interfaceType, false, memberName, new HashSet<ClassElement>()); | |
| 1665 } | 1592 } |
| 1666 return null; | 1593 return null; |
| 1667 } | 1594 } |
| 1668 | 1595 |
| 1669 /** | 1596 /** |
| 1670 * Look up the method or getter with the given [memberName] in the interfaces | |
| 1671 * implemented by the given [targetType], either directly or indirectly. | |
| 1672 * Return the element representing the method or getter that was found, or | |
| 1673 * `null` if there is no method or getter with the given name. The flag | |
| 1674 * [includeTargetType] should be `true` if the search should include the | |
| 1675 * target type. The [visitedInterfaces] is a set containing all of the | |
| 1676 * interfaces that have been examined, used to prevent infinite recursion and | |
| 1677 * to optimize the search. | |
| 1678 */ | |
| 1679 ExecutableElement _lookUpGetterOrMethodInInterfaces( | |
| 1680 InterfaceType targetType, | |
| 1681 bool includeTargetType, | |
| 1682 String memberName, | |
| 1683 HashSet<ClassElement> visitedInterfaces) { | |
| 1684 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | |
| 1685 // specification (titled "Inheritance and Overriding" under "Interfaces") | |
| 1686 // describes a much more complex scheme for finding the inherited member. | |
| 1687 // We need to follow that scheme. The code below should cover the 80% case. | |
| 1688 ClassElement targetClass = targetType.element; | |
| 1689 if (visitedInterfaces.contains(targetClass)) { | |
| 1690 return null; | |
| 1691 } | |
| 1692 visitedInterfaces.add(targetClass); | |
| 1693 if (includeTargetType) { | |
| 1694 ExecutableElement member = targetType.getMethod(memberName); | |
| 1695 if (member != null) { | |
| 1696 return member; | |
| 1697 } | |
| 1698 member = targetType.getGetter(memberName); | |
| 1699 if (member != null) { | |
| 1700 return member; | |
| 1701 } | |
| 1702 } | |
| 1703 for (InterfaceType interfaceType in targetType.interfaces) { | |
| 1704 ExecutableElement member = _lookUpGetterOrMethodInInterfaces( | |
| 1705 interfaceType, true, memberName, visitedInterfaces); | |
| 1706 if (member != null) { | |
| 1707 return member; | |
| 1708 } | |
| 1709 } | |
| 1710 for (InterfaceType mixinType in targetType.mixins.reversed) { | |
| 1711 ExecutableElement member = _lookUpGetterOrMethodInInterfaces( | |
| 1712 mixinType, true, memberName, visitedInterfaces); | |
| 1713 if (member != null) { | |
| 1714 return member; | |
| 1715 } | |
| 1716 } | |
| 1717 InterfaceType superclass = targetType.superclass; | |
| 1718 if (superclass == null) { | |
| 1719 return null; | |
| 1720 } | |
| 1721 return _lookUpGetterOrMethodInInterfaces( | |
| 1722 superclass, true, memberName, visitedInterfaces); | |
| 1723 } | |
| 1724 | |
| 1725 /** | |
| 1726 * Look up the method with the given [methodName] in the given [type]. Return | 1597 * Look up the method with the given [methodName] in the given [type]. Return |
| 1727 * the element representing the method that was found, or `null` if there is | 1598 * the element representing the method that was found, or `null` if there is |
| 1728 * no method with the given name. The [target] is the target of the | 1599 * no method with the given name. The [target] is the target of the |
| 1729 * invocation, or `null` if there is no target. | 1600 * invocation, or `null` if there is no target. |
| 1730 */ | 1601 */ |
| 1731 MethodElement _lookUpMethod( | 1602 MethodElement _lookUpMethod( |
| 1732 Expression target, DartType type, String methodName) { | 1603 Expression target, DartType type, String methodName) { |
| 1733 type = _resolveTypeParameter(type); | 1604 type = _resolveTypeParameter(type); |
| 1734 if (type is InterfaceType) { | 1605 if (type is InterfaceType) { |
| 1735 InterfaceType interfaceType = type; | 1606 return type.lookUpInheritedMethod(methodName, |
| 1736 MethodElement method; | 1607 library: _definingLibrary, thisType: target is! SuperExpression); |
| 1737 if (target is SuperExpression) { | |
| 1738 method = interfaceType.lookUpMethodInSuperclass( | |
| 1739 methodName, _definingLibrary); | |
| 1740 } else { | |
| 1741 method = interfaceType.lookUpMethod(methodName, _definingLibrary); | |
| 1742 } | |
| 1743 if (method != null) { | |
| 1744 return method; | |
| 1745 } | |
| 1746 return _lookUpMethodInInterfaces( | |
| 1747 interfaceType, false, methodName, new HashSet<ClassElement>()); | |
| 1748 } | 1608 } |
| 1749 return null; | 1609 return null; |
| 1750 } | 1610 } |
| 1751 | 1611 |
| 1752 /** | 1612 /** |
| 1753 * Look up the method with the given [methodName] in the interfaces | |
| 1754 * implemented by the given [targetType], either directly or indirectly. | |
| 1755 * Return the element representing the method that was found, or `null` if | |
| 1756 * there is no method with the given name. The flag [includeTargetType] should | |
| 1757 * be `true` if the search should include the target type. The | |
| 1758 * [visitedInterfaces] is a set containing all of the interfaces that have | |
| 1759 * been examined, used to prevent infinite recursion and to optimize the | |
| 1760 * search. | |
| 1761 */ | |
| 1762 MethodElement _lookUpMethodInInterfaces( | |
| 1763 InterfaceType targetType, | |
| 1764 bool includeTargetType, | |
| 1765 String methodName, | |
| 1766 HashSet<ClassElement> visitedInterfaces) { | |
| 1767 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | |
| 1768 // specification (titled "Inheritance and Overriding" under "Interfaces") | |
| 1769 // describes a much more complex scheme for finding the inherited member. | |
| 1770 // We need to follow that scheme. The code below should cover the 80% case. | |
| 1771 ClassElement targetClass = targetType.element; | |
| 1772 if (visitedInterfaces.contains(targetClass)) { | |
| 1773 return null; | |
| 1774 } | |
| 1775 visitedInterfaces.add(targetClass); | |
| 1776 if (includeTargetType) { | |
| 1777 MethodElement method = targetType.getMethod(methodName); | |
| 1778 if (method != null && method.isAccessibleIn(_definingLibrary)) { | |
| 1779 return method; | |
| 1780 } | |
| 1781 } | |
| 1782 for (InterfaceType interfaceType in targetType.interfaces) { | |
| 1783 MethodElement method = _lookUpMethodInInterfaces( | |
| 1784 interfaceType, true, methodName, visitedInterfaces); | |
| 1785 if (method != null) { | |
| 1786 return method; | |
| 1787 } | |
| 1788 } | |
| 1789 for (InterfaceType mixinType in targetType.mixins.reversed) { | |
| 1790 MethodElement method = _lookUpMethodInInterfaces( | |
| 1791 mixinType, true, methodName, visitedInterfaces); | |
| 1792 if (method != null) { | |
| 1793 return method; | |
| 1794 } | |
| 1795 } | |
| 1796 InterfaceType superclass = targetType.superclass; | |
| 1797 if (superclass == null) { | |
| 1798 return null; | |
| 1799 } | |
| 1800 return _lookUpMethodInInterfaces( | |
| 1801 superclass, true, methodName, visitedInterfaces); | |
| 1802 } | |
| 1803 | |
| 1804 /** | |
| 1805 * Look up the setter with the given [setterName] in the given [type]. Return | 1613 * Look up the setter with the given [setterName] in the given [type]. Return |
| 1806 * the element representing the setter that was found, or `null` if there is | 1614 * the element representing the setter that was found, or `null` if there is |
| 1807 * no setter with the given name. The [target] is the target of the | 1615 * no setter with the given name. The [target] is the target of the |
| 1808 * invocation, or `null` if there is no target. | 1616 * invocation, or `null` if there is no target. |
| 1809 */ | 1617 */ |
| 1810 PropertyAccessorElement _lookUpSetter( | 1618 PropertyAccessorElement _lookUpSetter( |
| 1811 Expression target, DartType type, String setterName) { | 1619 Expression target, DartType type, String setterName) { |
| 1812 type = _resolveTypeParameter(type); | 1620 type = _resolveTypeParameter(type); |
| 1813 if (type is InterfaceType) { | 1621 if (type is InterfaceType) { |
| 1814 InterfaceType interfaceType = type; | 1622 return type.lookUpInheritedSetter(setterName, |
| 1815 PropertyAccessorElement accessor; | 1623 library: _definingLibrary, thisType: target is! SuperExpression); |
| 1816 if (target is SuperExpression) { | |
| 1817 accessor = interfaceType.lookUpSetterInSuperclass( | |
| 1818 setterName, _definingLibrary); | |
| 1819 } else { | |
| 1820 accessor = interfaceType.lookUpSetter(setterName, _definingLibrary); | |
| 1821 } | |
| 1822 if (accessor != null) { | |
| 1823 return accessor; | |
| 1824 } | |
| 1825 return _lookUpSetterInInterfaces( | |
| 1826 interfaceType, false, setterName, new HashSet<ClassElement>()); | |
| 1827 } | 1624 } |
| 1828 return null; | 1625 return null; |
| 1829 } | 1626 } |
| 1830 | 1627 |
| 1831 /** | 1628 /** |
| 1832 * Look up the setter with the given [setterName] in the interfaces | |
| 1833 * implemented by the given [targetType], either directly or indirectly. | |
| 1834 * Return the element representing the setter that was found, or `null` if | |
| 1835 * there is no setter with the given name. The [targetType] is the type in | |
| 1836 * which the setter might be defined. The flag [includeTargetType] should be | |
| 1837 * `true` if the search should include the target type. The | |
| 1838 * [visitedInterfaces] is a set containing all of the interfaces that have | |
| 1839 * been examined, used to prevent infinite recursion and to optimize the | |
| 1840 * search. | |
| 1841 */ | |
| 1842 PropertyAccessorElement _lookUpSetterInInterfaces( | |
| 1843 InterfaceType targetType, | |
| 1844 bool includeTargetType, | |
| 1845 String setterName, | |
| 1846 HashSet<ClassElement> visitedInterfaces) { | |
| 1847 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | |
| 1848 // specification (titled "Inheritance and Overriding" under "Interfaces") | |
| 1849 // describes a much more complex scheme for finding the inherited member. | |
| 1850 // We need to follow that scheme. The code below should cover the 80% case. | |
| 1851 ClassElement targetClass = targetType.element; | |
| 1852 if (visitedInterfaces.contains(targetClass)) { | |
| 1853 return null; | |
| 1854 } | |
| 1855 visitedInterfaces.add(targetClass); | |
| 1856 if (includeTargetType) { | |
| 1857 PropertyAccessorElement setter = targetType.getSetter(setterName); | |
| 1858 if (setter != null && setter.isAccessibleIn(_definingLibrary)) { | |
| 1859 return setter; | |
| 1860 } | |
| 1861 } | |
| 1862 for (InterfaceType interfaceType in targetType.interfaces) { | |
| 1863 PropertyAccessorElement setter = _lookUpSetterInInterfaces( | |
| 1864 interfaceType, true, setterName, visitedInterfaces); | |
| 1865 if (setter != null) { | |
| 1866 return setter; | |
| 1867 } | |
| 1868 } | |
| 1869 for (InterfaceType mixinType in targetType.mixins.reversed) { | |
| 1870 PropertyAccessorElement setter = _lookUpSetterInInterfaces( | |
| 1871 mixinType, true, setterName, visitedInterfaces); | |
| 1872 if (setter != null) { | |
| 1873 return setter; | |
| 1874 } | |
| 1875 } | |
| 1876 InterfaceType superclass = targetType.superclass; | |
| 1877 if (superclass == null) { | |
| 1878 return null; | |
| 1879 } | |
| 1880 return _lookUpSetterInInterfaces( | |
| 1881 superclass, true, setterName, visitedInterfaces); | |
| 1882 } | |
| 1883 | |
| 1884 /** | |
| 1885 * Given some class [element], this method uses [_subtypeManager] to find the | 1629 * Given some class [element], this method uses [_subtypeManager] to find the |
| 1886 * set of all subtypes; the subtypes are then searched for a member (method, | 1630 * set of all subtypes; the subtypes are then searched for a member (method, |
| 1887 * getter, or setter), that has the given [memberName]. The flag [asMethod] | 1631 * getter, or setter), that has the given [memberName]. The flag [asMethod] |
| 1888 * should be `true` if the methods should be searched for in the subtypes. The | 1632 * should be `true` if the methods should be searched for in the subtypes. The |
| 1889 * flag [asAccessor] should be `true` if the accessors (getters and setters) | 1633 * flag [asAccessor] should be `true` if the accessors (getters and setters) |
| 1890 * should be searched for in the subtypes. | 1634 * should be searched for in the subtypes. |
| 1891 */ | 1635 */ |
| 1892 bool _memberFoundInSubclass( | 1636 bool _memberFoundInSubclass( |
| 1893 Element element, String memberName, bool asMethod, bool asAccessor) { | 1637 Element element, String memberName, bool asMethod, bool asAccessor) { |
| 1894 if (element is ClassElement) { | 1638 if (element is ClassElement) { |
| (...skipping 928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2823 | 2567 |
| 2824 @override | 2568 @override |
| 2825 Element get staticElement => null; | 2569 Element get staticElement => null; |
| 2826 | 2570 |
| 2827 @override | 2571 @override |
| 2828 accept(AstVisitor visitor) => null; | 2572 accept(AstVisitor visitor) => null; |
| 2829 | 2573 |
| 2830 @override | 2574 @override |
| 2831 void visitChildren(AstVisitor visitor) {} | 2575 void visitChildren(AstVisitor visitor) {} |
| 2832 } | 2576 } |
| OLD | NEW |