Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library kernel.class_hierarchy; | 4 library kernel.class_hierarchy; |
| 5 | 5 |
| 6 import 'ast.dart'; | 6 import 'ast.dart'; |
| 7 import 'dart:math'; | 7 import 'dart:math'; |
| 8 import 'dart:typed_data'; | 8 import 'dart:typed_data'; |
| 9 import 'src/heap.dart'; | 9 import 'src/heap.dart'; |
| 10 import 'type_algebra.dart'; | 10 import 'type_algebra.dart'; |
| 11 | 11 |
| 12 /// Interface for answering various subclassing queries. | |
| 13 /// TODO(scheglov) Several methods are not used, or used only in tests. | |
| 14 /// Check if these methods are not useful and should be removed . | |
| 15 abstract class ClassHierarchy { | |
| 16 factory ClassHierarchy(Program program) => new ClassHierarchyImpl(program); | |
| 17 | |
| 18 /// All classes in the program. | |
| 19 /// | |
| 20 /// The iterable is ordered so that classes occur after their super classes. | |
| 21 Iterable<Class> get classes; | |
| 22 | |
| 23 Class get rootClass; | |
| 24 | |
| 25 /// Returns the index of [class_] in the [classes] list. | |
| 26 int getClassIndex(Class class_); | |
| 27 | |
| 28 /// True if the program contains another class that is a subtype of given one. | |
| 29 bool hasProperSubtypes(Class class_); | |
| 30 | |
| 31 /// Returns the number of steps in the longest inheritance path from [class_] | |
| 32 /// to [rootClass]. | |
| 33 int getClassDepth(Class class_); | |
| 34 | |
| 35 /// Returns a list of classes appropriate for use in calculating a least upper | |
| 36 /// bound. | |
| 37 /// | |
| 38 /// The returned list is a list of all classes that [class_] is a subtype of | |
| 39 /// (including itself), sorted first by depth (deepest first) and then by | |
| 40 /// class index. | |
| 41 List<Class> getRankedSuperclasses(Class class_); | |
| 42 | |
| 43 /// Returns the least upper bound of two interface types, as defined by Dart | |
| 44 /// 1.0. | |
| 45 /// | |
| 46 /// Given two interfaces I and J, let S_I be the set of superinterfaces of I, | |
| 47 /// let S_J be the set of superinterfaces of J, and let | |
| 48 /// S = (I union S_I) intersect (J union S_J). Furthermore, we define | |
| 49 /// S_n = {T | T in S and depth(T) = n} for any finite n where depth(T) is | |
| 50 /// the number of steps in the longest inheritance path from T to Object. Let | |
| 51 /// q be the largest number such that S_q has cardinality one. The least | |
| 52 /// upper bound of I and J is the sole element of S_q. | |
| 53 /// | |
| 54 /// This is called the "classic" least upper bound to distinguish it from the | |
| 55 /// strong mode least upper bound, which has special behaviors in the case | |
| 56 /// where one type is a subtype of the other, or where both types are based on | |
| 57 /// the same class. | |
| 58 InterfaceType getClassicLeastUpperBound( | |
| 59 InterfaceType type1, InterfaceType type2); | |
| 60 | |
| 61 /// Returns the instantiation of [superclass] that is implemented by [class_], | |
| 62 /// or `null` if [class_] does not implement [superclass] at all. | |
| 63 Supertype getClassAsInstanceOf(Class class_, Class superclass); | |
| 64 | |
| 65 /// Returns the instantiation of [superclass] that is implemented by [type], | |
| 66 /// or `null` if [type] does not implement [superclass] at all. | |
| 67 InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass); | |
| 68 | |
| 69 /// Returns the instance member that would respond to a dynamic dispatch of | |
| 70 /// [name] to an instance of [class_], or `null` if no such member exists. | |
| 71 /// | |
| 72 /// If [setter] is `false`, the name is dispatched as a getter or call, | |
| 73 /// and will return a field, getter, method, or operator (or null). | |
| 74 /// | |
| 75 /// If [setter] is `true`, the name is dispatched as a setter, roughly | |
| 76 /// corresponding to `name=` in the Dart specification, but note that the | |
| 77 /// returned member will not have a name ending with `=`. In this case, | |
| 78 /// a non-final field or setter (or null) will be returned. | |
| 79 /// | |
| 80 /// If the class is abstract, abstract members are ignored and the dispatch | |
| 81 /// is resolved if the class was not abstract. | |
| 82 Member getDispatchTarget(Class class_, Name name, {bool setter: false}); | |
| 83 | |
| 84 /// Returns the possibly abstract interface member of [class_] with the given | |
| 85 /// [name]. | |
| 86 /// | |
| 87 /// If [setter] is `false`, only fields, methods, and getters with that name | |
| 88 /// will be found. If [setter] is `true`, only non-final fields and setters | |
| 89 /// will be found. | |
| 90 /// | |
| 91 /// If multiple members with that name are inherited and not overridden, the | |
| 92 /// member from the first declared supertype is returned. | |
| 93 Member getInterfaceMember(Class class_, Name name, {bool setter: false}); | |
| 94 | |
| 95 /// Invokes [callback] for every member declared in or inherited by [class_] | |
| 96 /// that overrides or implements a member in a supertype of [class_] | |
| 97 /// (or in rare cases, overrides a member declared in [class_]). | |
| 98 /// | |
| 99 /// We use the term "inheritable" for members that are candidates for | |
| 100 /// inheritance but may have been overridden. The "declared" members of a | |
| 101 /// mixin application are those declared in the mixed-in type. The callback is | |
| 102 /// invoked in the following cases: | |
| 103 /// | |
| 104 /// 1. A member declared in the class overrides a member inheritable through | |
| 105 /// one of the supertypes of the class. | |
| 106 /// | |
| 107 /// 2. A non-abstract member is inherited from a superclass, and in the | |
| 108 /// context of this class, it overrides an abstract member inheritable through | |
| 109 /// one of its superinterfaces. | |
| 110 /// | |
| 111 /// 3. A non-abstract member is inherited from a superclass, and it overrides | |
| 112 /// an abstract member declared in this class. | |
| 113 /// | |
| 114 /// This method will not report that a member overrides itself. A given pair | |
| 115 /// may be reported multiple times when there are multiple inheritance paths | |
| 116 /// to the overridden member. | |
| 117 /// | |
| 118 /// It is possible for two methods to override one another in both directions. | |
| 119 /// | |
| 120 /// Getters and setters are overridden separately. The [isSetter] callback | |
| 121 /// parameter determines which type of access is being overridden. | |
| 122 void forEachOverridePair(Class class_, | |
| 123 callback(Member declaredMember, Member interfaceMember, bool isSetter)); | |
| 124 } | |
| 125 | |
| 12 /// Data structure for answering various subclassing queries. | 126 /// Data structure for answering various subclassing queries. |
| 13 class ClassHierarchy { | 127 class ClassHierarchyImpl implements ClassHierarchy { |
|
ahe
2017/05/29 13:56:18
I suggest that this class is renamed to, for examp
scheglov
2017/05/30 01:18:18
Good idea.
Done.
| |
| 14 /// All classes in the program. | 128 /// All classes in the program. |
| 15 /// | 129 /// |
| 16 /// The list is ordered so that classes occur after their super classes. | 130 /// The list is ordered so that classes occur after their super classes. |
| 17 final List<Class> classes; | 131 final List<Class> classes; |
| 18 | 132 |
| 19 final Map<Class, _ClassInfo> _infoFor = <Class, _ClassInfo>{}; | 133 final Map<Class, _ClassInfo> _infoFor = <Class, _ClassInfo>{}; |
| 20 | 134 |
| 21 ClassHierarchy(Program program) | 135 ClassHierarchyImpl(Program program) |
| 22 : this._internal(program, _countClasses(program)); | 136 : this._internal(program, _countClasses(program)); |
| 23 | 137 |
| 24 Class get rootClass => classes[0]; | 138 Class get rootClass => classes[0]; |
| 25 | 139 |
| 26 /// Returns the index of [class_] in the [classes] list. | 140 @override |
| 27 int getClassIndex(Class class_) => _infoFor[class_].topologicalIndex; | 141 int getClassIndex(Class class_) => _infoFor[class_].topologicalIndex; |
| 28 | 142 |
| 29 /// True if [subclass] inherits from [superclass] though zero or more | 143 /// True if [subclass] inherits from [superclass] though zero or more |
| 30 /// `extends` relationships. | 144 /// `extends` relationships. |
| 31 bool isSubclassOf(Class subclass, Class superclass) { | 145 bool isSubclassOf(Class subclass, Class superclass) { |
| 32 if (identical(subclass, superclass)) return true; | 146 if (identical(subclass, superclass)) return true; |
| 33 return _infoFor[subclass].isSubclassOf(_infoFor[superclass]); | 147 return _infoFor[subclass].isSubclassOf(_infoFor[superclass]); |
| 34 } | 148 } |
| 35 | 149 |
| 36 /// True if [submixture] inherits from [superclass] though zero or more | 150 /// True if [submixture] inherits from [superclass] though zero or more |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 56 /// mixin application (i.e. [Class.mixedInType]). | 170 /// mixin application (i.e. [Class.mixedInType]). |
| 57 bool isUsedAsMixin(Class class_) { | 171 bool isUsedAsMixin(Class class_) { |
| 58 return _infoFor[class_].directMixers.isNotEmpty; | 172 return _infoFor[class_].directMixers.isNotEmpty; |
| 59 } | 173 } |
| 60 | 174 |
| 61 /// True if the given class is used in an `implements` clause. | 175 /// True if the given class is used in an `implements` clause. |
| 62 bool isUsedAsSuperInterface(Class class_) { | 176 bool isUsedAsSuperInterface(Class class_) { |
| 63 return _infoFor[class_].directImplementers.isNotEmpty; | 177 return _infoFor[class_].directImplementers.isNotEmpty; |
| 64 } | 178 } |
| 65 | 179 |
| 66 /// Returns the number of steps in the longest inheritance path from [class_] | 180 @override |
| 67 /// to [rootClass]. | |
| 68 int getClassDepth(Class class_) => _infoFor[class_].depth; | 181 int getClassDepth(Class class_) => _infoFor[class_].depth; |
| 69 | 182 |
| 70 /// Returns a list of classes appropriate for use in calculating a least upper | 183 @override |
| 71 /// bound. | |
| 72 /// | |
| 73 /// The returned list is a list of all classes that [class_] is a subtype of | |
| 74 /// (including itself), sorted first by depth (deepest first) and then by | |
| 75 /// class index. | |
| 76 List<Class> getRankedSuperclasses(Class class_) { | 184 List<Class> getRankedSuperclasses(Class class_) { |
| 77 return _getRankedSuperclassInfos(_infoFor[class_]) | 185 return _getRankedSuperclassInfos(_infoFor[class_]) |
| 78 .map((info) => info.classNode) | 186 .map((info) => info.classNode) |
| 79 .toList(); | 187 .toList(); |
| 80 } | 188 } |
| 81 | 189 |
| 82 List<_ClassInfo> _getRankedSuperclassInfos(_ClassInfo info) { | 190 List<_ClassInfo> _getRankedSuperclassInfos(_ClassInfo info) { |
| 83 if (info.leastUpperBoundInfos != null) return info.leastUpperBoundInfos; | 191 if (info.leastUpperBoundInfos != null) return info.leastUpperBoundInfos; |
| 84 var heap = new _LubHeap()..add(info); | 192 var heap = new _LubHeap()..add(info); |
| 85 var chain = <_ClassInfo>[]; | 193 var chain = <_ClassInfo>[]; |
| 86 info.leastUpperBoundInfos = chain; | 194 info.leastUpperBoundInfos = chain; |
| 87 _ClassInfo lastInfo = null; | 195 _ClassInfo lastInfo = null; |
| 88 while (heap.isNotEmpty) { | 196 while (heap.isNotEmpty) { |
| 89 var nextInfo = heap.remove(); | 197 var nextInfo = heap.remove(); |
| 90 if (identical(nextInfo, lastInfo)) continue; | 198 if (identical(nextInfo, lastInfo)) continue; |
| 91 chain.add(nextInfo); | 199 chain.add(nextInfo); |
| 92 lastInfo = nextInfo; | 200 lastInfo = nextInfo; |
| 93 var classNode = nextInfo.classNode; | 201 var classNode = nextInfo.classNode; |
| 94 void addToHeap(Supertype supertype) { | 202 void addToHeap(Supertype supertype) { |
| 95 heap.add(_infoFor[supertype.classNode]); | 203 heap.add(_infoFor[supertype.classNode]); |
| 96 } | 204 } |
| 97 | 205 |
| 98 if (classNode.supertype != null) addToHeap(classNode.supertype); | 206 if (classNode.supertype != null) addToHeap(classNode.supertype); |
| 99 if (classNode.mixedInType != null) addToHeap(classNode.mixedInType); | 207 if (classNode.mixedInType != null) addToHeap(classNode.mixedInType); |
| 100 classNode.implementedTypes.forEach(addToHeap); | 208 classNode.implementedTypes.forEach(addToHeap); |
| 101 } | 209 } |
| 102 return chain; | 210 return chain; |
| 103 } | 211 } |
| 104 | 212 |
| 105 /// Returns the least upper bound of two interface types, as defined by Dart | 213 @override |
| 106 /// 1.0. | |
| 107 /// | |
| 108 /// Given two interfaces I and J, let S_I be the set of superinterfaces of I, | |
| 109 /// let S_J be the set of superinterfaces of J, and let | |
| 110 /// S = (I union S_I) intersect (J union S_J). Furthermore, we define | |
| 111 /// S_n = {T | T in S and depth(T) = n} for any finite n where depth(T) is | |
| 112 /// the number of steps in the longest inheritance path from T to Object. Let | |
| 113 /// q be the largest number such that S_q has cardinality one. The least | |
| 114 /// upper bound of I and J is the sole element of S_q. | |
| 115 /// | |
| 116 /// This is called the "classic" least upper bound to distinguish it from the | |
| 117 /// strong mode least upper bound, which has special behaviors in the case | |
| 118 /// where one type is a subtype of the other, or where both types are based on | |
| 119 /// the same class. | |
| 120 InterfaceType getClassicLeastUpperBound( | 214 InterfaceType getClassicLeastUpperBound( |
| 121 InterfaceType type1, InterfaceType type2) { | 215 InterfaceType type1, InterfaceType type2) { |
| 122 // The algorithm is: first we compute a list of superclasses for both types, | 216 // The algorithm is: first we compute a list of superclasses for both types, |
| 123 // ordered from greatest to least depth, and ordered by topological sort | 217 // ordered from greatest to least depth, and ordered by topological sort |
| 124 // index within each depth. Due to the sort order, we can find the | 218 // index within each depth. Due to the sort order, we can find the |
| 125 // intersection of these lists by a simple walk. | 219 // intersection of these lists by a simple walk. |
| 126 // | 220 // |
| 127 // Then, for each class in the intersection, determine the exact type that | 221 // Then, for each class in the intersection, determine the exact type that |
| 128 // is implemented by type1 and type2. If the types match, that type is a | 222 // is implemented by type1 and type2. If the types match, that type is a |
| 129 // candidate (it's a member of S_n). As soon as we find a candidate which | 223 // candidate (it's a member of S_n). As soon as we find a candidate which |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 205 : Substitution.fromInterfaceType(type2).substituteType( | 299 : Substitution.fromInterfaceType(type2).substituteType( |
| 206 info2.genericSuperTypes[next.classNode].asInterfaceType); | 300 info2.genericSuperTypes[next.classNode].asInterfaceType); |
| 207 if (superType1 == superType2) { | 301 if (superType1 == superType2) { |
| 208 candidate = superType1; | 302 candidate = superType1; |
| 209 ++numCandidatesAtThisDepth; | 303 ++numCandidatesAtThisDepth; |
| 210 } | 304 } |
| 211 } | 305 } |
| 212 } | 306 } |
| 213 } | 307 } |
| 214 | 308 |
| 215 /// Returns the instantiation of [superclass] that is implemented by [class_], | 309 @override |
| 216 /// or `null` if [class_] does not implement [superclass] at all. | |
| 217 Supertype getClassAsInstanceOf(Class class_, Class superclass) { | 310 Supertype getClassAsInstanceOf(Class class_, Class superclass) { |
| 218 if (identical(class_, superclass)) return class_.asThisSupertype; | 311 if (identical(class_, superclass)) return class_.asThisSupertype; |
| 219 _ClassInfo info = _infoFor[class_]; | 312 _ClassInfo info = _infoFor[class_]; |
| 220 _ClassInfo superInfo = _infoFor[superclass]; | 313 _ClassInfo superInfo = _infoFor[superclass]; |
| 221 if (!info.isSubtypeOf(superInfo)) return null; | 314 if (!info.isSubtypeOf(superInfo)) return null; |
| 222 if (superclass.typeParameters.isEmpty) return superclass.asRawSupertype; | 315 if (superclass.typeParameters.isEmpty) return superclass.asRawSupertype; |
| 223 return info.genericSuperTypes[superclass]; | 316 return info.genericSuperTypes[superclass]; |
| 224 } | 317 } |
| 225 | 318 |
| 226 /// Returns the instantiation of [superclass] that is implemented by [type], | 319 @override |
| 227 /// or `null` if [type] does not implement [superclass] at all. | |
| 228 InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) { | 320 InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) { |
| 229 Supertype castedType = getClassAsInstanceOf(type.classNode, superclass); | 321 Supertype castedType = getClassAsInstanceOf(type.classNode, superclass); |
| 230 if (castedType == null) return null; | 322 if (castedType == null) return null; |
| 231 return Substitution | 323 return Substitution |
| 232 .fromInterfaceType(type) | 324 .fromInterfaceType(type) |
| 233 .substituteType(castedType.asInterfaceType); | 325 .substituteType(castedType.asInterfaceType); |
| 234 } | 326 } |
| 235 | 327 |
| 236 /// Returns the instance member that would respond to a dynamic dispatch of | 328 @override |
| 237 /// [name] to an instance of [class_], or `null` if no such member exists. | |
| 238 /// | |
| 239 /// If [setter] is `false`, the name is dispatched as a getter or call, | |
| 240 /// and will return a field, getter, method, or operator (or null). | |
| 241 /// | |
| 242 /// If [setter] is `true`, the name is dispatched as a setter, roughly | |
| 243 /// corresponding to `name=` in the Dart specification, but note that the | |
| 244 /// returned member will not have a name ending with `=`. In this case, | |
| 245 /// a non-final field or setter (or null) will be returned. | |
| 246 /// | |
| 247 /// If the class is abstract, abstract members are ignored and the dispatch | |
| 248 /// is resolved if the class was not abstract. | |
| 249 Member getDispatchTarget(Class class_, Name name, {bool setter: false}) { | 329 Member getDispatchTarget(Class class_, Name name, {bool setter: false}) { |
| 250 _ClassInfo info = _infoFor[class_]; | 330 _ClassInfo info = _infoFor[class_]; |
| 251 List<Member> list = | 331 List<Member> list = |
| 252 setter ? info.implementedSetters : info.implementedGettersAndCalls; | 332 setter ? info.implementedSetters : info.implementedGettersAndCalls; |
| 253 return _findMemberByName(list, name); | 333 return _findMemberByName(list, name); |
| 254 } | 334 } |
| 255 | 335 |
| 256 /// Returns the list of potential targets of dynamic dispatch to an instance | 336 /// Returns the list of potential targets of dynamic dispatch to an instance |
| 257 /// of [class_]. | 337 /// of [class_]. |
| 258 /// | 338 /// |
| 259 /// If [setters] is `false`, only potential targets of a getter or call | 339 /// If [setters] is `false`, only potential targets of a getter or call |
| 260 /// dispatch are returned. If [setters] is `true`, only potential targets | 340 /// dispatch are returned. If [setters] is `true`, only potential targets |
| 261 /// of a setter dispatch are returned. | 341 /// of a setter dispatch are returned. |
| 262 /// | 342 /// |
| 263 /// See [getDispatchTarget] for more details. | 343 /// See [getDispatchTarget] for more details. |
| 264 /// | 344 /// |
| 265 /// The returned list should not be modified. | 345 /// The returned list should not be modified. |
| 266 List<Member> getDispatchTargets(Class class_, {bool setters: false}) { | 346 List<Member> getDispatchTargets(Class class_, {bool setters: false}) { |
| 267 _ClassInfo info = _infoFor[class_]; | 347 _ClassInfo info = _infoFor[class_]; |
| 268 return setters ? info.implementedSetters : info.implementedGettersAndCalls; | 348 return setters ? info.implementedSetters : info.implementedGettersAndCalls; |
| 269 } | 349 } |
| 270 | 350 |
| 271 /// Returns the possibly abstract interface member of [class_] with the given | 351 @override |
| 272 /// [name]. | |
| 273 /// | |
| 274 /// If [setters] is `false`, only fields, methods, and getters with that name | |
| 275 /// will be found. If [setters] is `true`, only non-final fields and setters | |
| 276 /// will be found. | |
| 277 /// | |
| 278 /// If multiple members with that name are inherited and not overidden, the | |
| 279 /// member from the first declared supertype is returned. | |
| 280 Member getInterfaceMember(Class class_, Name name, {bool setter: false}) { | 352 Member getInterfaceMember(Class class_, Name name, {bool setter: false}) { |
| 281 List<Member> list = getInterfaceMembers(class_, setters: setter); | 353 List<Member> list = getInterfaceMembers(class_, setters: setter); |
| 282 return _findMemberByName(list, name); | 354 return _findMemberByName(list, name); |
| 283 } | 355 } |
| 284 | 356 |
| 285 /// Returns the list of members denoting the interface for [class_], which | 357 /// Returns the list of members denoting the interface for [class_], which |
| 286 /// may include abstract members. | 358 /// may include abstract members. |
| 287 /// | 359 /// |
| 288 /// The list may contain multiple members with a given name. This happens | 360 /// The list may contain multiple members with a given name. This happens |
| 289 /// when members are inherited through different supertypes and not overridden | 361 /// when members are inherited through different supertypes and not overridden |
| 290 /// in the class. | 362 /// in the class. |
| 291 /// | 363 /// |
| 292 /// Also see [getInterfaceMember]. | 364 /// Also see [getInterfaceMember]. |
| 293 List<Member> getInterfaceMembers(Class class_, {bool setters: false}) { | 365 List<Member> getInterfaceMembers(Class class_, {bool setters: false}) { |
| 294 return _buildInterfaceMembers(class_, _infoFor[class_], setters: setters); | 366 return _buildInterfaceMembers(class_, _infoFor[class_], setters: setters); |
| 295 } | 367 } |
| 296 | 368 |
| 297 /// Invokes [callback] for every member declared in or inherited by [class_] | 369 @override |
| 298 /// that overrides or implements a member in a supertype of [class_] | |
| 299 /// (or in rare cases, overrides a member declared in [class_]). | |
| 300 /// | |
| 301 /// We use the term "inheritable" for members that are candidates for | |
| 302 /// inheritance but may have been overridden. The "declared" members of a | |
| 303 /// mixin application are those declared in the mixed-in type. The callback is | |
| 304 /// invoked in the following cases: | |
| 305 /// | |
| 306 /// 1. A member declared in the class overrides a member inheritable through | |
| 307 /// one of the supertypes of the class. | |
| 308 /// | |
| 309 /// 2. A non-abstract member is inherited from a superclass, and in the | |
| 310 /// context of this class, it overrides an abstract member inheritable through | |
| 311 /// one of its superinterfaces. | |
| 312 /// | |
| 313 /// 3. A non-abstract member is inherited from a superclass, and it overrides | |
| 314 /// an abstract member declared in this class. | |
| 315 /// | |
| 316 /// This method will not report that a member overrides itself. A given pair | |
| 317 /// may be reported multiple times when there are multiple inheritance paths | |
| 318 /// to the overridden member. | |
| 319 /// | |
| 320 /// It is possible for two methods to override one another in both directions. | |
| 321 /// | |
| 322 /// Getters and setters are overridden separately. The [isSetter] callback | |
| 323 /// parameter determines which type of access is being overridden. | |
| 324 void forEachOverridePair(Class class_, | 370 void forEachOverridePair(Class class_, |
| 325 callback(Member declaredMember, Member interfaceMember, bool isSetter)) { | 371 callback(Member declaredMember, Member interfaceMember, bool isSetter)) { |
| 326 _ClassInfo info = _infoFor[class_]; | 372 _ClassInfo info = _infoFor[class_]; |
| 327 for (var supertype in class_.supers) { | 373 for (var supertype in class_.supers) { |
| 328 var superclass = supertype.classNode; | 374 var superclass = supertype.classNode; |
| 329 var superGetters = getInterfaceMembers(superclass); | 375 var superGetters = getInterfaceMembers(superclass); |
| 330 var superSetters = getInterfaceMembers(superclass, setters: true); | 376 var superSetters = getInterfaceMembers(superclass, setters: true); |
| 331 _reportOverrides(info.implementedGettersAndCalls, superGetters, callback); | 377 _reportOverrides(info.implementedGettersAndCalls, superGetters, callback); |
| 332 _reportOverrides(info.declaredGettersAndCalls, superGetters, callback, | 378 _reportOverrides(info.declaredGettersAndCalls, superGetters, callback, |
| 333 onlyAbstract: true); | 379 onlyAbstract: true); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 if (!identical(declared, inherited)) { | 421 if (!identical(declared, inherited)) { |
| 376 callback(declared, inherited, isSetter); | 422 callback(declared, inherited, isSetter); |
| 377 } | 423 } |
| 378 // A given declared member may override multiple interface members, | 424 // A given declared member may override multiple interface members, |
| 379 // so only move past the interface member. | 425 // so only move past the interface member. |
| 380 ++j; | 426 ++j; |
| 381 } | 427 } |
| 382 } | 428 } |
| 383 } | 429 } |
| 384 | 430 |
| 385 /// True if the program contains another class that is a subtype of given one. | 431 @override |
| 386 bool hasProperSubtypes(Class class_) { | 432 bool hasProperSubtypes(Class class_) { |
| 387 // If there are no subtypes then the subtype set contains the class itself. | 433 // If there are no subtypes then the subtype set contains the class itself. |
| 388 return !getSubtypesOf(class_).isSingleton; | 434 return !getSubtypesOf(class_).isSingleton; |
| 389 } | 435 } |
| 390 | 436 |
| 391 /// Returns the subtypes of [class_] as an interval list. | 437 /// Returns the subtypes of [class_] as an interval list. |
| 392 ClassSet getSubtypesOf(Class class_) { | 438 ClassSet getSubtypesOf(Class class_) { |
| 393 return new ClassSet(this, _infoFor[class_].subtypeIntervalList); | 439 return new ClassSet(this, _infoFor[class_].subtypeIntervalList); |
| 394 } | 440 } |
| 395 | 441 |
| 396 /// Returns the subclasses of [class_] as an interval list. | 442 /// Returns the subclasses of [class_] as an interval list. |
| 397 ClassSet getSubclassesOf(Class class_) { | 443 ClassSet getSubclassesOf(Class class_) { |
| 398 return new ClassSet(this, _infoFor[class_].subclassIntervalList); | 444 return new ClassSet(this, _infoFor[class_].subclassIntervalList); |
| 399 } | 445 } |
| 400 | 446 |
| 401 ClassHierarchy._internal(Program program, int numberOfClasses) | 447 ClassHierarchyImpl._internal(Program program, int numberOfClasses) |
| 402 : classes = new List<Class>(numberOfClasses) { | 448 : classes = new List<Class>(numberOfClasses) { |
| 403 // Build the class ordering based on a topological sort. | 449 // Build the class ordering based on a topological sort. |
| 404 for (var library in program.libraries) { | 450 for (var library in program.libraries) { |
| 405 for (var classNode in library.classes) { | 451 for (var classNode in library.classes) { |
| 406 _topologicalSortVisit(classNode); | 452 _topologicalSortVisit(classNode); |
| 407 } | 453 } |
| 408 } | 454 } |
| 409 | 455 |
| 410 // Build index of direct children. Do this after the topological sort so | 456 // Build index of direct children. Do this after the topological sort so |
| 411 // that super types always occur before subtypes. | 457 // that super types always occur before subtypes. |
| (...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1027 List<Member> implementedSetters; | 1073 List<Member> implementedSetters; |
| 1028 | 1074 |
| 1029 List<Member> interfaceGettersAndCalls; | 1075 List<Member> interfaceGettersAndCalls; |
| 1030 List<Member> interfaceSetters; | 1076 List<Member> interfaceSetters; |
| 1031 | 1077 |
| 1032 _ClassInfo(this.classNode); | 1078 _ClassInfo(this.classNode); |
| 1033 } | 1079 } |
| 1034 | 1080 |
| 1035 /// An immutable set of classes, internally represented as an interval list. | 1081 /// An immutable set of classes, internally represented as an interval list. |
| 1036 class ClassSet { | 1082 class ClassSet { |
| 1037 final ClassHierarchy _hierarchy; | 1083 final ClassHierarchyImpl _hierarchy; |
| 1038 final Uint32List _intervalList; | 1084 final Uint32List _intervalList; |
| 1039 | 1085 |
| 1040 ClassSet(this._hierarchy, this._intervalList); | 1086 ClassSet(this._hierarchy, this._intervalList); |
| 1041 | 1087 |
| 1042 bool get isEmpty => _intervalList.isEmpty; | 1088 bool get isEmpty => _intervalList.isEmpty; |
| 1043 | 1089 |
| 1044 bool get isSingleton { | 1090 bool get isSingleton { |
| 1045 var list = _intervalList; | 1091 var list = _intervalList; |
| 1046 return list.length == 2 && list[0] + 1 == list[1]; | 1092 return list.length == 2 && list[0] + 1 == list[1]; |
| 1047 } | 1093 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1069 class _LubHeap extends Heap<_ClassInfo> { | 1115 class _LubHeap extends Heap<_ClassInfo> { |
| 1070 @override | 1116 @override |
| 1071 bool sortsBefore(_ClassInfo a, _ClassInfo b) => sortsBeforeStatic(a, b); | 1117 bool sortsBefore(_ClassInfo a, _ClassInfo b) => sortsBeforeStatic(a, b); |
| 1072 | 1118 |
| 1073 static bool sortsBeforeStatic(_ClassInfo a, _ClassInfo b) { | 1119 static bool sortsBeforeStatic(_ClassInfo a, _ClassInfo b) { |
| 1074 if (a.depth > b.depth) return true; | 1120 if (a.depth > b.depth) return true; |
| 1075 if (a.depth < b.depth) return false; | 1121 if (a.depth < b.depth) return false; |
| 1076 return a.topologicalIndex < b.topologicalIndex; | 1122 return a.topologicalIndex < b.topologicalIndex; |
| 1077 } | 1123 } |
| 1078 } | 1124 } |
| OLD | NEW |