Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1120)

Side by Side Diff: pkg/analyzer/lib/src/task/strong/checker.dart

Issue 2981183003: fix #29766, fix #29782 - fix override checker's interface checking (Closed)
Patch Set: fix Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « DEPS ('k') | pkg/analyzer/test/src/task/strong/checker_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 }
OLDNEW
« no previous file with comments | « DEPS ('k') | pkg/analyzer/test/src/task/strong/checker_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698