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 |