| 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 1619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1630 var interfaces = _collectInterfacesToCheck(element.type); | 1630 var interfaces = _collectInterfacesToCheck(element.type); |
| 1631 var visitedClasses = new Set<InterfaceType>(); | 1631 var visitedClasses = new Set<InterfaceType>(); |
| 1632 var visitedMembers = new HashSet<String>(); | 1632 var visitedMembers = new HashSet<String>(); |
| 1633 | 1633 |
| 1634 // Checks all most-derived concrete members on this `type`. We skip over | 1634 // Checks all most-derived concrete members on this `type`. We skip over |
| 1635 // members that are already `visitedMembers`, because they were overridden | 1635 // members that are already `visitedMembers`, because they were overridden |
| 1636 // and we've already checked that member. | 1636 // and we've already checked that member. |
| 1637 // | 1637 // |
| 1638 // Because of that, it is important we visit types in the order that they | 1638 // Because of that, it is important we visit types in the order that they |
| 1639 // will override members. | 1639 // will override members. |
| 1640 void checkType(InterfaceType type, AstNode location) { | 1640 // If checkingMixin is true, then we are checking [type] in a mixin position |
| 1641 // and hence should consider its own mixins and superclass as abstract. |
| 1642 void checkType(InterfaceType type, AstNode location, |
| 1643 {bool checkingMixin: false}) { |
| 1641 // Skip `Object` because we don't need to check those members here. | 1644 // Skip `Object` because we don't need to check those members here. |
| 1642 // (because `Object` is the root of everything, it will be checked in | 1645 // (because `Object` is the root of everything, it will be checked in |
| 1643 // _checkSuperOverrides for all classes). | 1646 // _checkSuperOverrides for all classes). |
| 1644 if (type == null || type.isObject || !visitedClasses.add(type)) return; | 1647 if (type == null || type.isObject || !visitedClasses.add(type)) return; |
| 1645 | 1648 |
| 1646 // Check `member` against all `interfaces`. | 1649 // Check `member` against all `interfaces`. |
| 1647 void checkOverride(ExecutableElement member, [AstNode loc]) { | 1650 void checkOverride(ExecutableElement member, [AstNode loc]) { |
| 1648 if (!visitedMembers.add(member.name)) return; | 1651 if (!visitedMembers.add(member.name)) return; |
| 1649 for (var interface in interfaces) { | 1652 for (var interface in interfaces) { |
| 1650 if (_checkMemberOverride(member, interface, loc ?? location) == | 1653 if (_checkMemberOverride(member, interface, loc ?? location) == |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1662 // Otherwise, we'll use the `extends` or `with` clause. | 1665 // Otherwise, we'll use the `extends` or `with` clause. |
| 1663 var isRootClass = identical(location, node); | 1666 var isRootClass = identical(location, node); |
| 1664 | 1667 |
| 1665 // Check direct overrides on the class. | 1668 // Check direct overrides on the class. |
| 1666 if (isRootClass) { | 1669 if (isRootClass) { |
| 1667 _checkClassMembers(node, checkOverride); | 1670 _checkClassMembers(node, checkOverride); |
| 1668 } else { | 1671 } else { |
| 1669 _checkTypeMembers(type, checkOverride); | 1672 _checkTypeMembers(type, checkOverride); |
| 1670 } | 1673 } |
| 1671 | 1674 |
| 1672 // Check mixin members against interfaces. | 1675 // If we are currently checking a mixin, then its own mixins and |
| 1673 // | 1676 // superclass are abstract, and we should not check their members. |
| 1674 // We visit mixins in reverse order to reflect how they override | 1677 // This should only happen when super mixins is enabled, and we |
| 1675 // eachother. | 1678 // don't do proper checking for super mixins (we don't check that |
| 1676 for (int i = type.mixins.length - 1; i >= 0; i--) { | 1679 // the contract implied by the mixin declaration is satisfied by |
| 1677 checkType(type.mixins[i], | 1680 // the mixin use), but this prevents us from erroneously |
| 1678 isRootClass ? _withClause(node).mixinTypes[i] : location); | 1681 // rejecting some super mixin patterns. |
| 1682 // If this is a mixin application (class A = Object with B) |
| 1683 // however, then we do still need to treat the mixin as concrete. |
| 1684 if (!checkingMixin || type.element.isMixinApplication) { |
| 1685 // Check mixin members against interfaces. |
| 1686 // |
| 1687 // We visit mixins in reverse order to reflect how they override |
| 1688 // eachother. |
| 1689 for (int i = type.mixins.length - 1; i >= 0; i--) { |
| 1690 checkType(type.mixins[i], |
| 1691 isRootClass ? _withClause(node).mixinTypes[i] : location, |
| 1692 checkingMixin: true); |
| 1693 } |
| 1694 |
| 1695 // Check members on the superclass. |
| 1696 checkType(type.superclass, |
| 1697 isRootClass ? _extendsErrorLocation(node) : location, |
| 1698 checkingMixin: checkingMixin); |
| 1679 } | 1699 } |
| 1680 | |
| 1681 // Check members on the superclass. | |
| 1682 checkType(type.superclass, | |
| 1683 isRootClass ? _extendsErrorLocation(node) : location); | |
| 1684 } | 1700 } |
| 1685 | 1701 |
| 1686 checkType(element.type, node); | 1702 checkType(element.type, node); |
| 1687 } | 1703 } |
| 1688 | 1704 |
| 1689 /// Gets the set of all interfaces on [type] that should be checked to see | 1705 /// Gets the set of all interfaces on [type] that should be checked to see |
| 1690 /// if type's members are overriding them correctly. | 1706 /// if type's members are overriding them correctly. |
| 1691 /// | 1707 /// |
| 1692 /// In particular, we need to check these overrides for the definitions in | 1708 /// In particular, we need to check these overrides for the definitions in |
| 1693 /// the class itself and each its superclasses (and mixins). | 1709 /// the class itself and each its superclasses (and mixins). |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1958 } | 1974 } |
| 1959 | 1975 |
| 1960 /// 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 |
| 1961 /// a [ClassTypeAlias] this returns an empty list. | 1977 /// a [ClassTypeAlias] this returns an empty list. |
| 1962 WithClause _withClause(Declaration node) { | 1978 WithClause _withClause(Declaration node) { |
| 1963 return node is ClassDeclaration | 1979 return node is ClassDeclaration |
| 1964 ? node.withClause | 1980 ? node.withClause |
| 1965 : (node as ClassTypeAlias).withClause; | 1981 : (node as ClassTypeAlias).withClause; |
| 1966 } | 1982 } |
| 1967 } | 1983 } |
| OLD | NEW |