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 |