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 |