OLD | NEW |
---|---|
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be | 5 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be |
6 // refactored to fit into analyzer. | 6 // refactored to fit into analyzer. |
7 library analyzer.src.task.strong.checker; | 7 library analyzer.src.task.strong.checker; |
8 | 8 |
9 import 'dart:collection'; | 9 import 'dart:collection'; |
10 import 'package:analyzer/analyzer.dart'; | 10 import 'package:analyzer/analyzer.dart'; |
(...skipping 1634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1645 element.mixins.forEach(visitTypeAndSupertypes); | 1645 element.mixins.forEach(visitTypeAndSupertypes); |
1646 element.interfaces.forEach(visitTypeAndSupertypes); | 1646 element.interfaces.forEach(visitTypeAndSupertypes); |
1647 } | 1647 } |
1648 } | 1648 } |
1649 | 1649 |
1650 visitTypeAndSupertypes(type); | 1650 visitTypeAndSupertypes(type); |
1651 | 1651 |
1652 return genericSupertypes; | 1652 return genericSupertypes; |
1653 } | 1653 } |
1654 | 1654 |
1655 /// Checks that implementations correctly override all reachable interfaces. | 1655 /// Checks that members on this class correctly override all reachable |
1656 /// interfaces. | |
1657 void _checkAllInterfaceOverrides(Declaration node, ClassElement element) { | |
1658 var interfaces = _collectInterfacesToCheck(element.type); | |
1659 var visitedClasses = new Set<InterfaceType>(); | |
1660 | |
1661 // Visit all members on `type` (including inherited) and report errors if | |
1662 // all `interfaces` are not correctly overridden. | |
1663 // | |
1664 // Generally we only need to check the most derived concrete member, and | |
1665 // we record members that have been seen already in `seen`. However we do | |
1666 // report errors for every mixin member (unless it is overridden) by | |
1667 // the class itself. | |
1668 // | |
1669 // TODO(jmesserly): what should mixins be doing? This behavior does not | |
1670 // seem correct, but it is preserved for backwards compatibility. | |
1671 void checkType(InterfaceType type, Set<String> seen, AstNode location) { | |
1672 if (type == null || type.isObject || !visitedClasses.add(type)) return; | |
1673 | |
1674 // Check `member` against all `interfaces`. | |
1675 void checkOverride(ExecutableElement member, [AstNode loc]) { | |
1676 if (!seen.add(member.name)) return; | |
1677 for (var interface in interfaces) { | |
1678 if (_checkMemberOverride(member, interface, loc ?? location) == | |
1679 false) { | |
1680 // Only report one error per member for interfaces. | |
1681 // TODO(jmesserly): this is for backwards compatibility. Remove it? | |
1682 break; | |
1683 } | |
1684 } | |
1685 } | |
1686 | |
1687 // Check direct overrides on the class. | |
1688 var isRootClass = identical(location, node); | |
1689 if (isRootClass) { | |
1690 _checkClassMembers(node, checkOverride); | |
1691 } else { | |
1692 _checkTypeMembers(type, checkOverride); | |
1693 } | |
1694 | |
1695 // Check mixin members against interfaces. | |
1696 // | |
1697 // We want to check each mixin application class separately, so we report | |
1698 // errors for any invalid overrides, even if multiple mixins have a member | |
1699 // of the same name. | |
1700 for (int i = 0; i < type.mixins.length; i++) { | |
Siggi Cherem (dart-lang)
2017/07/24 18:45:06
After this CL landed, we noticed about 30 strong m
| |
1701 checkType(type.mixins[i], new Set.from(seen), | |
1702 isRootClass ? _withClause(node).mixinTypes[i] : location); | |
1703 } | |
1704 | |
1705 // Check members on the superclass. | |
1706 checkType(type.superclass, seen, | |
1707 isRootClass ? _extendsErrorLocation(node) : location); | |
1708 } | |
1709 | |
1710 checkType(element.type, new Set(), node); | |
1711 } | |
1712 | |
1713 /// Gets the set of all interfaces on [type] that should be checked to see | |
1714 /// if type's members are overriding them correctly. | |
1715 /// | |
1656 /// In particular, we need to check these overrides for the definitions in | 1716 /// In particular, we need to check these overrides for the definitions in |
1657 /// the class itself and each its superclasses. If a superclass is not | 1717 /// the class itself and each its superclasses (and mixins). |
1658 /// abstract, then we can skip its transitive interfaces. For example, in: | 1718 /// If a superclass (or mixin) is concrete, then we can skip its transitive |
1719 /// interfaces, but if it is abstract we must check them. For example, in: | |
1659 /// | 1720 /// |
1660 /// B extends C implements G | 1721 /// B extends C implements G |
1661 /// A extends B with E, F implements H, I | 1722 /// A extends B with E, F implements H, I |
1662 /// | 1723 /// |
1663 /// we check: | 1724 /// we need to check the following interfaces: |
1664 /// | 1725 /// |
1665 /// C against G, H, and I | 1726 /// C against G, H, and I |
1666 /// B against G, H, and I | 1727 /// B against G, H, and I |
1667 /// E against H and I // no check against G because B is a concrete class | 1728 /// E against H and I // no check against G because B is a concrete class |
1668 /// F against H and I | 1729 /// F against H and I |
1669 /// A against H and I | 1730 /// A against H and I |
1670 void _checkAllInterfaceOverrides(Declaration node, ClassElement element) { | 1731 Set<InterfaceType> _collectInterfacesToCheck(InterfaceType type) { |
1671 var seen = new Set<String>(); | 1732 var interfaces = new Set<InterfaceType>(); |
1672 // Helper function to collect all reachable interfaces. | 1733 void collectInterfaces(InterfaceType t) { |
1673 find(InterfaceType interfaceType, Set result) { | 1734 if (t == null || t.isObject) return; |
1674 if (interfaceType == null || interfaceType.isObject) return; | 1735 if (!interfaces.add(t)) return; |
1675 if (result.contains(interfaceType)) return; | 1736 collectInterfaces(t.superclass); |
1676 result.add(interfaceType); | 1737 t.mixins.forEach(collectInterfaces); |
1677 find(interfaceType.superclass, result); | 1738 t.interfaces.forEach(collectInterfaces); |
1678 interfaceType.mixins.forEach((i) => find(i, result)); | |
1679 interfaceType.interfaces.forEach((i) => find(i, result)); | |
1680 } | 1739 } |
1681 | 1740 |
1682 // Check all interfaces reachable from the `implements` clause in the | 1741 // Check all interfaces reachable from the `implements` clause in the |
1683 // current class against definitions here and in superclasses. | 1742 // current class against definitions here and in superclasses. |
1684 var localInterfaces = new Set<InterfaceType>(); | 1743 type.interfaces.forEach(collectInterfaces); |
1685 var type = element.type; | |
1686 type.interfaces.forEach((i) => find(i, localInterfaces)); | |
1687 _checkInterfacesOverrides(type, localInterfaces, seen, | |
1688 includeParents: true, classNode: node); | |
1689 | 1744 |
1690 // Check also how we override locally the interfaces from parent classes if | 1745 // Also collect interfaces from any abstract mixins or superclasses. |
1691 // the parent class is abstract. Otherwise, these will be checked as | 1746 // |
1692 // overrides on the concrete superclass. | 1747 // For a concrete mixin/superclass, we'll check that we override the |
1693 // We detect superclass circularities using the "tortoise and hare" | 1748 // concrete members in _checkSuperOverrides and |
1694 // algorithm. | 1749 // _checkMixinApplicationOverrides. But for abstract classes, we need to |
1695 var superInterfaces = new Set<InterfaceType>(); | 1750 // consider any abstract members it got from its interfaces. |
1696 var parent = type.superclass; | 1751 for (var s in _getSuperclasses(type, (t) => t.element.isAbstract)) { |
1697 var hare = type.superclass?.superclass; | 1752 s.interfaces.forEach(collectInterfaces); |
1698 // TODO(sigmund): we don't seem to be reporting the analyzer error that a | |
1699 // non-abstract class is not implementing an interface. See | |
1700 // https://github.com/dart-lang/dart-dev-compiler/issues/25 | |
1701 while (parent != null && parent.element.isAbstract) { | |
1702 if (identical(parent, hare)) break; | |
1703 parent.interfaces.forEach((i) => find(i, superInterfaces)); | |
1704 parent = parent.superclass; | |
1705 hare = hare?.superclass?.superclass; | |
1706 } | 1753 } |
1707 _checkInterfacesOverrides(type, superInterfaces, seen, | 1754 return interfaces; |
1708 includeParents: false, classNode: node); | |
1709 } | 1755 } |
1710 | 1756 |
1711 /// Check that individual methods and fields in [node] correctly override | 1757 /// Visits each member on the class [node] and calls [checkMember] with the |
1712 /// the declarations in [baseType]. | 1758 /// corresponding instance element and AST node (for error reporting). |
1713 /// | 1759 /// |
1714 /// The [errorLocation] node indicates where errors are reported, see | 1760 /// See also [_checkTypeMembers], which is used when the class AST node is not |
1715 /// [_checkSingleOverride] for more details. | 1761 /// available. |
1716 _checkIndividualOverridesFromClass(Declaration node, InterfaceType baseType, | 1762 void _checkClassMembers(Declaration node, |
1717 Set<String> seen, bool isSubclass) { | 1763 void checkMember(ExecutableElement member, ClassMember location)) { |
1718 for (var member in _classMembers(node)) { | 1764 for (var member in _classMembers(node)) { |
1719 if (member is FieldDeclaration) { | 1765 if (member is FieldDeclaration) { |
1720 if (member.isStatic) { | 1766 if (member.isStatic) { |
1721 continue; | 1767 continue; |
1722 } | 1768 } |
1723 for (var variable in member.fields.variables) { | 1769 for (var variable in member.fields.variables) { |
1724 var element = variable.element as PropertyInducingElement; | 1770 var element = variable.element as PropertyInducingElement; |
1725 var name = element.name; | 1771 checkMember(element.getter, member); |
1726 if (seen.contains(name)) { | 1772 if (!variable.isFinal && !variable.isConst) { |
1727 continue; | 1773 checkMember(element.setter, member); |
1728 } | |
1729 var getter = element.getter; | |
1730 var setter = element.setter; | |
1731 bool found = _checkSingleOverride( | |
1732 getter, baseType, variable.name, member, isSubclass); | |
1733 if (!variable.isFinal && | |
1734 !variable.isConst && | |
1735 _checkSingleOverride( | |
1736 setter, baseType, variable.name, member, isSubclass)) { | |
1737 found = true; | |
1738 } | |
1739 if (found) { | |
1740 seen.add(name); | |
1741 } | 1774 } |
1742 } | 1775 } |
1743 } else if (member is MethodDeclaration) { | 1776 } else if (member is MethodDeclaration) { |
1744 if (member.isStatic) { | 1777 if (member.isStatic) { |
1745 continue; | 1778 continue; |
1746 } | 1779 } |
1747 var method = resolutionMap.elementDeclaredByMethodDeclaration(member); | 1780 checkMember(member.element, member); |
1748 if (seen.contains(method.name)) { | |
1749 continue; | |
1750 } | |
1751 if (_checkSingleOverride( | |
1752 method, baseType, member.name, member, isSubclass)) { | |
1753 seen.add(method.name); | |
1754 } | |
1755 } else { | 1781 } else { |
1756 assert(member is ConstructorDeclaration); | 1782 assert(member is ConstructorDeclaration); |
1757 } | 1783 } |
1758 } | 1784 } |
1759 } | 1785 } |
1760 | 1786 |
1761 /// Check that individual methods and fields in [subType] correctly override | 1787 /// Visits the [type] and calls [checkMember] for each instance member. |
1762 /// the declarations in [baseType]. | |
1763 /// | 1788 /// |
1764 /// The [errorLocation] node indicates where errors are reported, see | 1789 /// See also [_checkClassMembers], which should be used when the class AST |
1765 /// [_checkSingleOverride] for more details. | 1790 /// node is available to allow for better error locations |
1766 /// | 1791 void _checkTypeMembers( |
1767 /// The set [seen] is used to avoid reporting overrides more than once. It | 1792 InterfaceType type, void checkMember(ExecutableElement member)) { |
1768 /// is used when invoking this function multiple times when checking several | |
1769 /// types in a class hierarchy. Errors are reported only the first time an | |
1770 /// invalid override involving a specific member is encountered. | |
1771 void _checkIndividualOverridesFromType( | |
1772 InterfaceType subType, | |
1773 InterfaceType baseType, | |
1774 AstNode errorLocation, | |
1775 Set<String> seen, | |
1776 bool isSubclass) { | |
1777 void checkHelper(ExecutableElement e) { | 1793 void checkHelper(ExecutableElement e) { |
1778 if (e.isStatic) return; | 1794 if (!e.isStatic) checkMember(e); |
1779 if (seen.contains(e.name)) return; | |
1780 if (_checkSingleOverride(e, baseType, null, errorLocation, isSubclass)) { | |
1781 seen.add(e.name); | |
1782 } | |
1783 } | 1795 } |
1784 | 1796 |
1785 subType.methods.forEach(checkHelper); | 1797 type.methods.forEach(checkHelper); |
1786 subType.accessors.forEach(checkHelper); | 1798 type.accessors.forEach(checkHelper); |
1787 } | |
1788 | |
1789 /// Checks that [cls] and its super classes (including mixins) correctly | |
1790 /// overrides each interface in [interfaces]. If [includeParents] is false, | |
1791 /// then mixins are still checked, but the base type and it's transitive | |
1792 /// supertypes are not. | |
1793 /// | |
1794 /// [cls] can be either a [ClassDeclaration] or a [InterfaceType]. For | |
1795 /// [ClassDeclaration]s errors are reported on the member that contains the | |
1796 /// invalid override, for [InterfaceType]s we use [errorLocation] instead. | |
1797 void _checkInterfacesOverrides( | |
1798 InterfaceType type, Iterable<InterfaceType> interfaces, Set<String> seen, | |
1799 {Set<InterfaceType> visited, | |
1800 bool includeParents: true, | |
1801 AstNode errorLocation, | |
1802 Declaration classNode}) { | |
1803 if (visited == null) { | |
1804 visited = new Set<InterfaceType>(); | |
1805 } else if (visited.contains(type)) { | |
1806 // Malformed type. | |
1807 return; | |
1808 } else { | |
1809 visited.add(type); | |
1810 } | |
1811 | |
1812 // Check direct overrides on [type] | |
1813 for (var interfaceType in interfaces) { | |
1814 if (classNode != null) { | |
1815 _checkIndividualOverridesFromClass( | |
1816 classNode, interfaceType, seen, false); | |
1817 } else { | |
1818 _checkIndividualOverridesFromType( | |
1819 type, interfaceType, errorLocation, seen, false); | |
1820 } | |
1821 } | |
1822 | |
1823 // Check overrides from its mixins | |
1824 for (int i = 0; i < type.mixins.length; i++) { | |
1825 var loc = errorLocation ?? _withClause(classNode).mixinTypes[i]; | |
1826 for (var interfaceType in interfaces) { | |
1827 // We copy [seen] so we can report separately if more than one mixin or | |
1828 // the base class have an invalid override. | |
1829 _checkIndividualOverridesFromType( | |
1830 type.mixins[i], interfaceType, loc, new Set.from(seen), false); | |
1831 } | |
1832 } | |
1833 | |
1834 // Check overrides from its superclasses | |
1835 if (includeParents) { | |
1836 var parent = type.superclass; | |
1837 if (parent.isObject) { | |
1838 return; | |
1839 } | |
1840 var loc = errorLocation ?? _extendsErrorLocation(classNode); | |
1841 // No need to copy [seen] here because we made copies above when reporting | |
1842 // errors on mixins. | |
1843 _checkInterfacesOverrides(parent, interfaces, seen, | |
1844 visited: visited, includeParents: true, errorLocation: loc); | |
1845 } | |
1846 } | 1799 } |
1847 | 1800 |
1848 /// Check overrides from mixin applications themselves. For example, in: | 1801 /// Check overrides from mixin applications themselves. For example, in: |
1849 /// | 1802 /// |
1850 /// A extends B with E, F | 1803 /// A extends B with E, F |
1851 /// | 1804 /// |
1852 /// we check: | 1805 /// we check: |
1853 /// | 1806 /// |
1854 /// B & E against B (equivalently how E overrides B) | 1807 /// B & E against B (equivalently how E overrides B) |
1855 /// B & E & F against B & E (equivalently how F overrides both B and E) | 1808 /// B & E & F against B & E (equivalently how F overrides both B and E) |
1856 void _checkMixinApplicationOverrides(Declaration node, ClassElement element) { | 1809 void _checkMixinApplicationOverrides(Declaration node, ClassElement element) { |
1857 var type = element.type; | 1810 var superclass = element.type.superclass; |
1858 var parent = type.superclass; | 1811 var mixins = element.type.mixins; |
1859 var mixins = type.mixins; | |
1860 | 1812 |
1861 // Check overrides from applying mixins | 1813 // Check overrides from applying mixins |
1862 for (int i = 0; i < mixins.length; i++) { | 1814 for (int i = 0; i < mixins.length; i++) { |
1863 var seen = new Set<String>(); | |
1864 var current = mixins[i]; | 1815 var current = mixins[i]; |
1865 var errorLocation = _withClause(node).mixinTypes[i]; | 1816 var location = _withClause(node).mixinTypes[i]; |
1866 for (int j = i - 1; j >= 0; j--) { | 1817 var superclasses = mixins.sublist(0, i).reversed.toList() |
1867 _checkIndividualOverridesFromType( | 1818 ..add(superclass); |
1868 current, mixins[j], errorLocation, seen, true); | 1819 |
1869 } | 1820 _checkTypeMembers(current, (m) { |
1870 _checkIndividualOverridesFromType( | 1821 for (var s in superclasses) { |
1871 current, parent, errorLocation, seen, true); | 1822 if (_checkConcreteMemberOverride(m, s, location)) break; |
1823 } | |
1824 }); | |
1872 } | 1825 } |
1873 } | 1826 } |
1874 | 1827 |
1875 /// Checks that [element] correctly overrides its corresponding member in | 1828 /// Gets the member corresponding to [member] on [type], and returns `null` |
1876 /// [type]. Returns `true` if an override was found, that is, if [element] has | 1829 /// if no member was found, or a boolean value to indicate whether the |
1877 /// a corresponding member in [type] that it overrides. | 1830 /// override is valid. |
1878 /// | 1831 /// |
1879 /// The [errorLocation] is a node where the error is reported. For example, a | 1832 /// The [location] is a node where the error is reported. For example, a |
1880 /// bad override of a method in a class with respect to its superclass is | 1833 /// bad override of a method in a class with respect to its superclass is |
1881 /// reported directly at the method declaration. However, invalid overrides | 1834 /// reported directly at the method declaration. However, invalid overrides |
1882 /// from base classes to interfaces, mixins to the base they are applied to, | 1835 /// from base classes to interfaces, mixins to the base they are applied to, |
1883 /// or mixins to interfaces are reported at the class declaration, since the | 1836 /// or mixins to interfaces are reported at the class declaration, since the |
1884 /// base class or members on their own were not incorrect, only combining them | 1837 /// base class or members on their own were not incorrect, only combining them |
1885 /// with the interface was problematic. For example, these are example error | 1838 /// with the interface was problematic. For example, these are example error |
1886 /// locations in these cases: | 1839 /// locations in these cases: |
1887 /// | 1840 /// |
1888 /// error: base class introduces an invalid override. The type of B.foo is | 1841 /// error: base class introduces an invalid override. The type of B.foo is |
1889 /// not a subtype of E.foo: | 1842 /// not a subtype of E.foo: |
1890 /// class A extends B implements E { ... } | 1843 /// class A extends B implements E { ... } |
1891 /// ^^^^^^^^^ | 1844 /// ^^^^^^^^^ |
1892 /// | 1845 /// |
1893 /// error: mixin introduces an invalid override. The type of C.foo is not | 1846 /// error: mixin introduces an invalid override. The type of C.foo is not |
1894 /// a subtype of E.foo: | 1847 /// a subtype of E.foo: |
1895 /// class A extends B with C implements E { ... } | 1848 /// class A extends B with C implements E { ... } |
1896 /// ^ | 1849 /// ^ |
1897 /// | 1850 /// |
1898 /// When checking for overrides from a type and it's super types, [node] is | 1851 /// When checking for overrides from a type and it's super types, [node] is |
1899 /// the AST node that defines [element]. This is used to determine whether the | 1852 /// the AST node that defines [member]. This is used to determine whether the |
1900 /// type of the element could be inferred from the types in the super classes. | 1853 /// type of the element could be inferred from the types in the super classes. |
1901 bool _checkSingleOverride(ExecutableElement element, InterfaceType type, | 1854 bool _checkMemberOverride( |
1902 AstNode node, AstNode errorLocation, bool isSubclass) { | 1855 ExecutableElement member, InterfaceType type, AstNode location) { |
1903 assert(!element.isStatic); | 1856 assert(!member.isStatic); |
1904 | 1857 |
1905 FunctionType subType = _elementType(element); | 1858 FunctionType subType = _elementType(member); |
1906 FunctionType baseType = _getMemberType(type, element); | 1859 FunctionType baseType = _getMemberType(type, member); |
1907 if (baseType == null) return false; | 1860 if (baseType == null) return null; |
1908 | |
1909 if (isSubclass && element is PropertyAccessorElement) { | |
1910 // Disallow any overriding if the base class defines this member | |
1911 // as a field. We effectively treat fields as final / non-virtual, | |
1912 // unless they are explicitly marked as @virtual | |
1913 var field = _getMemberField(type, element); | |
1914 if (field != null && !field.isVirtual) { | |
1915 _checker._recordMessage( | |
1916 errorLocation, StrongModeCode.INVALID_FIELD_OVERRIDE, [ | |
1917 element.enclosingElement.name, | |
1918 element.name, | |
1919 subType, | |
1920 type, | |
1921 baseType | |
1922 ]); | |
1923 } | |
1924 } | |
1925 | 1861 |
1926 if (!rules.isOverrideSubtypeOf(subType, baseType)) { | 1862 if (!rules.isOverrideSubtypeOf(subType, baseType)) { |
1927 ErrorCode errorCode; | 1863 ErrorCode errorCode; |
1928 var parent = errorLocation?.parent; | 1864 var parent = location?.parent; |
1929 if (errorLocation is ExtendsClause || | 1865 if (location is ExtendsClause || |
1930 parent is ClassTypeAlias && parent.superclass == errorLocation) { | 1866 parent is ClassTypeAlias && parent.superclass == location) { |
1931 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_BASE; | 1867 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_BASE; |
1932 } else if (parent is WithClause) { | 1868 } else if (parent is WithClause) { |
1933 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_MIXIN; | 1869 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_MIXIN; |
1934 } else { | 1870 } else { |
1935 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE; | 1871 errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE; |
1936 } | 1872 } |
1937 | 1873 |
1938 _checker._recordMessage(errorLocation, errorCode, [ | 1874 _checker._recordMessage(location, errorCode, |
1939 element.enclosingElement.name, | 1875 [member.enclosingElement.name, member.name, subType, type, baseType]); |
1940 element.name, | 1876 return false; |
1941 subType, | |
1942 type, | |
1943 baseType | |
1944 ]); | |
1945 } | 1877 } |
1878 return true; | |
1879 } | |
1946 | 1880 |
1947 // If we have any covariant parameters and we're comparing against a | 1881 /// Checks that a member override from a superclass (i.e. a concrete member) |
1948 // superclass, we check all superclasses instead of stopping the search. | 1882 /// is correct, reporting an error if needed, and returns `true` if we should |
1949 bool hasCovariant = element.parameters.any((p) => p.isCovariant); | 1883 /// keep searching up the superclass chain. |
1950 bool keepSearching = hasCovariant && isSubclass; | 1884 bool _checkConcreteMemberOverride( |
1951 return !keepSearching; | 1885 ExecutableElement member, InterfaceType type, AstNode location) { |
1886 _checkFieldOverride(member, type, location); | |
1887 // Stop if a member was found, and we have no covariant parameters. | |
1888 // If we have covariant parameters, we need to keep searching. | |
1889 return _checkMemberOverride(member, type, location) != null && | |
1890 member.parameters.every((p) => !p.isCovariant); | |
1891 } | |
1892 | |
1893 void _checkFieldOverride( | |
1894 Element member, InterfaceType type, AstNode location) { | |
1895 if (member is PropertyAccessorElement) { | |
1896 // Disallow overriding a non-virtual field. | |
1897 var field = _getMemberField(type, member); | |
1898 if (field != null && !field.isVirtual) { | |
1899 FunctionType subType = _elementType(member); | |
1900 FunctionType baseType = _getMemberType(type, member); | |
1901 _checker._recordMessage( | |
1902 location, StrongModeCode.INVALID_FIELD_OVERRIDE, [ | |
1903 member.enclosingElement.name, | |
1904 member.name, | |
1905 subType, | |
1906 type, | |
1907 baseType | |
1908 ]); | |
1909 } | |
1910 } | |
1952 } | 1911 } |
1953 | 1912 |
1954 /// Check overrides between a class and its superclasses and mixins. For | 1913 /// Check overrides between a class and its superclasses and mixins. For |
1955 /// example, in: | 1914 /// example, in: |
1956 /// | 1915 /// |
1957 /// A extends B with E, F | 1916 /// A extends B with E, F |
1958 /// | 1917 /// |
1959 /// we check A against B, B super classes, E, and F. | 1918 /// we check A against B, B super classes, E, and F. |
1960 /// | 1919 /// |
1961 /// Internally we avoid reporting errors twice and we visit classes bottom up | 1920 /// Internally we avoid reporting errors twice and we visit classes bottom up |
1962 /// to ensure we report the most immediate invalid override first. For | 1921 /// to ensure we report the most immediate invalid override first. For |
1963 /// example, in the following code we'll report that `Test` has an invalid | 1922 /// example, in the following code we'll report that `Test` has an invalid |
1964 /// override with respect to `Parent` (as opposed to an invalid override with | 1923 /// override with respect to `Parent` (as opposed to an invalid override with |
1965 /// respect to `Grandparent`): | 1924 /// respect to `Grandparent`): |
1966 /// | 1925 /// |
1967 /// class Grandparent { | 1926 /// class Grandparent { |
1968 /// m(A a) {} | 1927 /// m(A a) {} |
1969 /// } | 1928 /// } |
1970 /// class Parent extends Grandparent { | 1929 /// class Parent extends Grandparent { |
1971 /// m(A a) {} | 1930 /// m(A a) {} |
1972 /// } | 1931 /// } |
1973 /// class Test extends Parent { | 1932 /// class Test extends Parent { |
1974 /// m(B a) {} // invalid override | 1933 /// m(B a) {} // invalid override |
1975 /// } | 1934 /// } |
1976 void _checkSuperOverrides(Declaration node, ClassElement element) { | 1935 void _checkSuperOverrides(Declaration node, ClassElement element) { |
1977 var seen = new Set<String>(); | 1936 var superclasses = _getSuperclasses(element.type); |
1978 var current = element.type; | 1937 _checkClassMembers(node, (member, loc) { |
1979 var visited = new Set<InterfaceType>(); | 1938 for (var s in superclasses) { |
1980 do { | 1939 if (_checkConcreteMemberOverride(member, s, loc)) break; |
1981 visited.add(current); | 1940 } |
1982 current.mixins.reversed.forEach( | 1941 }); |
1983 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); | 1942 } |
1984 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); | 1943 |
1985 current = current.superclass; | 1944 /// Collects all superclasses of [type], including any mixin application |
1986 } while (!current.isObject && !visited.contains(current)); | 1945 /// classes. |
1946 /// | |
1947 /// The search can be pruned by passing a [visitSuperclasses] function and | |
1948 /// having it return `false` for types that should not be further explored. | |
1949 Iterable<InterfaceType> _getSuperclasses(InterfaceType type, | |
1950 [bool visitSuperclasses(InterfaceType t)]) { | |
1951 var superclasses = new Set<InterfaceType>(); | |
1952 visit(InterfaceType t) { | |
1953 if ((visitSuperclasses == null || visitSuperclasses(t)) && | |
1954 superclasses.add(t)) { | |
1955 t.mixins.reversed.forEach(visit); | |
1956 var s = t.superclass; | |
1957 if (s != null && !s.isObject) visit(s); | |
1958 } | |
1959 } | |
1960 | |
1961 type.mixins.reversed.forEach(visit); | |
1962 var s = type.superclass; | |
1963 if (s != null && !s.isObject) visit(s); | |
1964 | |
1965 // Make sure we record Object last, and not when we visit our mixins. | |
1966 if (!type.isObject) visit(rules.typeProvider.objectType); | |
1967 return superclasses; | |
1987 } | 1968 } |
1988 | 1969 |
1989 /// If node is a [ClassDeclaration] returns its members, otherwise if node is | 1970 /// If node is a [ClassDeclaration] returns its members, otherwise if node is |
1990 /// a [ClassTypeAlias] this returns an empty list. | 1971 /// a [ClassTypeAlias] this returns an empty list. |
1991 Iterable<ClassMember> _classMembers(Declaration node) { | 1972 Iterable<ClassMember> _classMembers(Declaration node) { |
1992 return node is ClassDeclaration ? node.members : []; | 1973 return node is ClassDeclaration ? node.members : []; |
1993 } | 1974 } |
1994 | 1975 |
1995 /// If node is a [ClassDeclaration] returns its members, otherwise if node is | 1976 /// If node is a [ClassDeclaration] returns its members, otherwise if node is |
1996 /// a [ClassTypeAlias] this returns an empty list. | 1977 /// a [ClassTypeAlias] this returns an empty list. |
1997 AstNode _extendsErrorLocation(Declaration node) { | 1978 AstNode _extendsErrorLocation(Declaration node) { |
1998 return node is ClassDeclaration | 1979 return node is ClassDeclaration |
1999 ? node.extendsClause | 1980 ? node.extendsClause |
2000 : (node as ClassTypeAlias).superclass; | 1981 : (node as ClassTypeAlias).superclass; |
2001 } | 1982 } |
2002 | 1983 |
2003 /// If node is a [ClassDeclaration] returns its members, otherwise if node is | 1984 /// If node is a [ClassDeclaration] returns its members, otherwise if node is |
2004 /// a [ClassTypeAlias] this returns an empty list. | 1985 /// a [ClassTypeAlias] this returns an empty list. |
2005 WithClause _withClause(Declaration node) { | 1986 WithClause _withClause(Declaration node) { |
2006 return node is ClassDeclaration | 1987 return node is ClassDeclaration |
2007 ? node.withClause | 1988 ? node.withClause |
2008 : (node as ClassTypeAlias).withClause; | 1989 : (node as ClassTypeAlias).withClause; |
2009 } | 1990 } |
2010 } | 1991 } |
OLD | NEW |