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