Chromium Code Reviews| 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 library dart2js.world.class_set; | 5 library dart2js.world.class_set; |
| 6 | 6 |
| 7 import 'dart:collection' show IterableBase; | 7 import 'dart:collection' show IterableBase; |
| 8 | 8 |
| 9 import '../elements/elements.dart' show ClassElement; | 9 import '../elements/elements.dart' show ClassElement; |
| 10 import '../elements/entities.dart' show ClassEntity; | |
| 10 import '../util/enumset.dart' show EnumSet; | 11 import '../util/enumset.dart' show EnumSet; |
| 11 import '../util/util.dart' show Link; | 12 import '../util/util.dart' show Link; |
| 12 | 13 |
| 13 /// Enum for the different kinds of instantiation of a class. | 14 /// Enum for the different kinds of instantiation of a class. |
| 14 enum Instantiation { | 15 enum Instantiation { |
| 15 UNINSTANTIATED, | 16 UNINSTANTIATED, |
| 16 DIRECTLY_INSTANTIATED, | 17 DIRECTLY_INSTANTIATED, |
| 17 INDIRECTLY_INSTANTIATED, | 18 INDIRECTLY_INSTANTIATED, |
| 18 ABSTRACTLY_INSTANTIATED, | 19 ABSTRACTLY_INSTANTIATED, |
| 19 } | 20 } |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 if (includeUninstantiated) { | 88 if (includeUninstantiated) { |
| 88 mask.add(Instantiation.UNINSTANTIATED); | 89 mask.add(Instantiation.UNINSTANTIATED); |
| 89 } | 90 } |
| 90 if (includeAbstractlyInstantiated) { | 91 if (includeAbstractlyInstantiated) { |
| 91 mask.add(Instantiation.ABSTRACTLY_INSTANTIATED); | 92 mask.add(Instantiation.ABSTRACTLY_INSTANTIATED); |
| 92 } | 93 } |
| 93 return mask; | 94 return mask; |
| 94 } | 95 } |
| 95 | 96 |
| 96 final ClassHierarchyNode parentNode; | 97 final ClassHierarchyNode parentNode; |
| 97 final ClassElement cls; | 98 final ClassEntity cls; |
| 98 final EnumSet<Instantiation> _mask = new EnumSet<Instantiation>.fromValues( | 99 final EnumSet<Instantiation> _mask = new EnumSet<Instantiation>.fromValues( |
| 99 const <Instantiation>[Instantiation.UNINSTANTIATED]); | 100 const <Instantiation>[Instantiation.UNINSTANTIATED]); |
| 100 | 101 |
| 102 final int hierarchyDepth; | |
| 103 | |
| 101 ClassElement _leastUpperInstantiatedSubclass; | 104 ClassElement _leastUpperInstantiatedSubclass; |
| 102 int _instantiatedSubclassCount = 0; | 105 int _instantiatedSubclassCount = 0; |
| 103 | 106 |
| 104 /// `true` if [cls] has been directly instantiated. | 107 /// `true` if [cls] has been directly instantiated. |
| 105 /// | 108 /// |
| 106 /// For instance `C` but _not_ `B` in: | 109 /// For instance `C` but _not_ `B` in: |
| 107 /// class B {} | 110 /// class B {} |
| 108 /// class C extends B {} | 111 /// class C extends B {} |
| 109 /// main() => new C(); | 112 /// main() => new C(); |
| 110 /// | 113 /// |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 192 if (_mask.isEmpty) { | 195 if (_mask.isEmpty) { |
| 193 _mask.add(Instantiation.UNINSTANTIATED); | 196 _mask.add(Instantiation.UNINSTANTIATED); |
| 194 } | 197 } |
| 195 } | 198 } |
| 196 } | 199 } |
| 197 } | 200 } |
| 198 | 201 |
| 199 /// The nodes for the direct subclasses of [cls]. | 202 /// The nodes for the direct subclasses of [cls]. |
| 200 Link<ClassHierarchyNode> _directSubclasses = const Link<ClassHierarchyNode>(); | 203 Link<ClassHierarchyNode> _directSubclasses = const Link<ClassHierarchyNode>(); |
| 201 | 204 |
| 202 ClassHierarchyNode(this.parentNode, this.cls) { | 205 ClassHierarchyNode(this.parentNode, this.cls, this.hierarchyDepth) { |
|
Emily Fortuna
2017/04/11 19:45:48
why not make a getter for hierarchyDepth:
int get
Johnni Winther
2017/04/12 07:19:28
Because ClassEntity doesn't have a .hierarchyDepth
| |
| 203 if (parentNode != null) { | 206 if (parentNode != null) { |
| 204 parentNode.addDirectSubclass(this); | 207 parentNode.addDirectSubclass(this); |
| 205 } | 208 } |
| 206 } | 209 } |
| 207 | 210 |
| 208 /// Adds [subclass] as a direct subclass of [cls]. | 211 /// Adds [subclass] as a direct subclass of [cls]. |
| 209 void addDirectSubclass(ClassHierarchyNode subclass) { | 212 void addDirectSubclass(ClassHierarchyNode subclass) { |
| 210 assert(subclass.cls.superclass == cls); | |
| 211 assert(!_directSubclasses.contains(subclass)); | 213 assert(!_directSubclasses.contains(subclass)); |
| 212 _directSubclasses = _directSubclasses.prepend(subclass); | 214 _directSubclasses = _directSubclasses.prepend(subclass); |
| 213 } | 215 } |
| 214 | 216 |
| 215 Iterable<ClassHierarchyNode> get directSubclasses => _directSubclasses; | 217 Iterable<ClassHierarchyNode> get directSubclasses => _directSubclasses; |
| 216 | 218 |
| 217 /// Returns `true` if [other] is contained in the subtree of this node. | 219 /// Returns `true` if [other] is contained in the subtree of this node. |
| 218 /// | 220 /// |
| 219 /// This means that [other] is a subclass of [cls]. | 221 /// This means that [other] is a subclass of [cls]. |
| 220 bool contains(ClassElement other) { | 222 bool contains(ClassHierarchyNode other) { |
| 221 while (other != null) { | 223 while (other != null) { |
| 222 if (cls == other) return true; | 224 if (cls == other.cls) return true; |
| 223 if (cls.hierarchyDepth >= other.hierarchyDepth) return false; | 225 if (hierarchyDepth >= other.hierarchyDepth) return false; |
| 224 other = other.superclass; | 226 other = other.parentNode; |
| 225 } | 227 } |
| 226 return false; | 228 return false; |
| 227 } | 229 } |
| 228 | 230 |
| 229 /// `true` if [cls] has been directly, indirectly, or abstractly instantiated. | 231 /// `true` if [cls] has been directly, indirectly, or abstractly instantiated. |
| 230 bool get isInstantiated => | 232 bool get isInstantiated => |
| 231 isExplicitlyInstantiated || isIndirectlyInstantiated; | 233 isExplicitlyInstantiated || isIndirectlyInstantiated; |
| 232 | 234 |
| 233 /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls]. | 235 /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls]. |
| 234 /// | 236 /// |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 626 return subForEach; | 628 return subForEach; |
| 627 } | 629 } |
| 628 } | 630 } |
| 629 } | 631 } |
| 630 assert(nextStep != IterationStep.SKIP_SUBCLASSES); | 632 assert(nextStep != IterationStep.SKIP_SUBCLASSES); |
| 631 return nextStep; | 633 return nextStep; |
| 632 } | 634 } |
| 633 | 635 |
| 634 /// Adds [subtype] as a subtype of [cls]. | 636 /// Adds [subtype] as a subtype of [cls]. |
| 635 void addSubtype(ClassHierarchyNode subtype) { | 637 void addSubtype(ClassHierarchyNode subtype) { |
| 636 if (node.contains(subtype.cls)) { | 638 if (node.contains(subtype)) { |
| 637 return; | 639 return; |
| 638 } | 640 } |
| 639 if (_subtypes == null) { | 641 if (_subtypes == null) { |
| 640 _subtypes = <ClassHierarchyNode>[subtype]; | 642 _subtypes = <ClassHierarchyNode>[subtype]; |
| 641 } else { | 643 } else { |
| 642 int hierarchyDepth = subtype.cls.hierarchyDepth; | 644 int hierarchyDepth = subtype.hierarchyDepth; |
| 643 List<ClassHierarchyNode> newSubtypes = <ClassHierarchyNode>[]; | 645 List<ClassHierarchyNode> newSubtypes = <ClassHierarchyNode>[]; |
| 644 bool added = false; | 646 bool added = false; |
| 645 for (ClassHierarchyNode otherSubtype in _subtypes) { | 647 for (ClassHierarchyNode otherSubtype in _subtypes) { |
| 646 int otherHierarchyDepth = otherSubtype.cls.hierarchyDepth; | 648 int otherHierarchyDepth = otherSubtype.hierarchyDepth; |
| 647 if (hierarchyDepth == otherHierarchyDepth) { | 649 if (hierarchyDepth == otherHierarchyDepth) { |
| 648 if (subtype == otherSubtype) { | 650 if (subtype == otherSubtype) { |
| 649 return; | 651 return; |
| 650 } else { | 652 } else { |
| 651 // [otherSubtype] is unrelated to [subtype]. | 653 // [otherSubtype] is unrelated to [subtype]. |
| 652 newSubtypes.add(otherSubtype); | 654 newSubtypes.add(otherSubtype); |
| 653 } | 655 } |
| 654 } else if (hierarchyDepth > otherSubtype.cls.hierarchyDepth) { | 656 } else if (hierarchyDepth > otherSubtype.hierarchyDepth) { |
| 655 // [otherSubtype] could be a superclass of [subtype]. | 657 // [otherSubtype] could be a superclass of [subtype]. |
| 656 if (otherSubtype.contains(subtype.cls)) { | 658 if (otherSubtype.contains(subtype)) { |
| 657 // [subtype] is already in this set. | 659 // [subtype] is already in this set. |
| 658 return; | 660 return; |
| 659 } else { | 661 } else { |
| 660 // [otherSubtype] is unrelated to [subtype]. | 662 // [otherSubtype] is unrelated to [subtype]. |
| 661 newSubtypes.add(otherSubtype); | 663 newSubtypes.add(otherSubtype); |
| 662 } | 664 } |
| 663 } else { | 665 } else { |
| 664 if (!added) { | 666 if (!added) { |
| 665 // Insert [subtype] before other subtypes of higher hierarchy depth. | 667 // Insert [subtype] before other subtypes of higher hierarchy depth. |
| 666 newSubtypes.add(subtype); | 668 newSubtypes.add(subtype); |
| 667 added = true; | 669 added = true; |
| 668 } | 670 } |
| 669 // [subtype] could be a superclass of [otherSubtype]. | 671 // [subtype] could be a superclass of [otherSubtype]. |
| 670 if (subtype.contains(otherSubtype.cls)) { | 672 if (subtype.contains(otherSubtype)) { |
| 671 // Replace [otherSubtype]. | 673 // Replace [otherSubtype]. |
| 672 } else { | 674 } else { |
| 673 newSubtypes.add(otherSubtype); | 675 newSubtypes.add(otherSubtype); |
| 674 } | 676 } |
| 675 } | 677 } |
| 676 } | 678 } |
| 677 if (!added) { | 679 if (!added) { |
| 678 newSubtypes.add(subtype); | 680 newSubtypes.add(subtype); |
| 679 } | 681 } |
| 680 _subtypes = newSubtypes; | 682 _subtypes = newSubtypes; |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 899 STOP, | 901 STOP, |
| 900 | 902 |
| 901 /// Iteration skips the subclasses of the current class. | 903 /// Iteration skips the subclasses of the current class. |
| 902 SKIP_SUBCLASSES, | 904 SKIP_SUBCLASSES, |
| 903 } | 905 } |
| 904 | 906 |
| 905 /// Visiting function used for the `forEachX` functions of [ClassHierarchyNode] | 907 /// Visiting function used for the `forEachX` functions of [ClassHierarchyNode] |
| 906 /// and [ClassSet]. The return value controls the continued iteration. If `null` | 908 /// and [ClassSet]. The return value controls the continued iteration. If `null` |
| 907 /// is returned, iteration continues to the end. | 909 /// is returned, iteration continues to the end. |
| 908 typedef IterationStep ForEachFunction(ClassElement cls); | 910 typedef IterationStep ForEachFunction(ClassElement cls); |
| OLD | NEW |