@@ -100,15 +100,10 @@ abstract class InheritingContainer extends Container
100
100
late final List <LanguageFeature > displayedLanguageFeatures =
101
101
containerModifiers.asLanguageFeatureSet.toList ();
102
102
103
- late final List <ModelElement > _allModelElements = () {
104
- _inheritedElementsCache = _inheritedElements;
105
- var result = [
106
- ...super .allModelElements,
107
- ...typeParameters,
108
- ];
109
- _inheritedElementsCache = null ;
110
- return result;
111
- }();
103
+ late final List <ModelElement > _allModelElements = [
104
+ ...super .allModelElements,
105
+ ...typeParameters,
106
+ ];
112
107
113
108
Iterable <Method > get inheritedMethods {
114
109
var methodNames = declaredMethods.map ((m) => m.element.name).toSet ();
@@ -145,55 +140,69 @@ abstract class InheritingContainer extends Container
145
140
late final List <DefinedElementType > publicSuperChain =
146
141
model_utils.filterNonPublic (superChain).toList (growable: false );
147
142
148
- List <ExecutableElement >? _inheritedElementsCache;
149
- List <ExecutableElement > get _inheritedElements {
150
- if (_inheritedElementsCache != null ) return _inheritedElementsCache! ;
151
- if (element is ClassElement && (element as ClassElement ).isDartCoreObject) {
143
+ /// A list of the inherited executable elements, one element per inherited
144
+ /// `Name` .
145
+ ///
146
+ /// In this list, elements that are "closer" in the inheritance chain to
147
+ /// _this_ element are preferred over elements that are further away. In the
148
+ /// case of ties, concrete inherited elements are prefered to non-concrete
149
+ /// ones.
150
+ late final List <ExecutableElement > _inheritedElements = () {
151
+ if (element case ClassElement classElement
152
+ when classElement.isDartCoreObject) {
152
153
return const < ExecutableElement > [];
153
154
}
154
155
155
- final concreteInheritenceMap =
156
+ // The mapping of all of the inherited element names to their _concrete_
157
+ // implementation element.
158
+ var concreteInheritanceMap =
156
159
packageGraph.inheritanceManager.getInheritedConcreteMap2 (element);
157
- final inheritenceMap =
160
+ // The mapping of all inherited element names to the nearest inherited
161
+ // element that they resolve to.
162
+ var inheritanceMap =
158
163
packageGraph.inheritanceManager.getInheritedMap2 (element);
159
164
160
- List <InterfaceElement >? inheritanceChainElements;
165
+ var inheritanceChainElements =
166
+ inheritanceChain.map ((c) => c.element).toList (growable: false );
161
167
162
- final combinedMap = {
163
- for (final name in concreteInheritenceMap.keys)
164
- name.name: concreteInheritenceMap[name]! ,
168
+ // A combined map of names to inherited _concrete_ Elements, and other
169
+ // inherited Elements.
170
+ var combinedMap = {
171
+ for (var MapEntry (: key, : value) in concreteInheritanceMap.entries)
172
+ key.name: value,
165
173
};
166
- for (final name in inheritenceMap.keys) {
167
- final inheritenceElement = inheritenceMap[name] ! ;
168
- final combinedMapElement = combinedMap[name.name];
174
+ for (var MapEntry (key : name, value : inheritedElement)
175
+ in inheritanceMap.entries) {
176
+ var combinedMapElement = combinedMap[name.name];
169
177
if (combinedMapElement == null ) {
170
- combinedMap[name.name] = inheritenceElement ;
178
+ combinedMap[name.name] = inheritedElement ;
171
179
continue ;
172
180
}
173
181
174
- // Elements in the inheritance chain starting from `this.element` down to,
175
- // but not including, [Object].
176
- inheritanceChainElements ?? =
177
- inheritanceChain.map ((c) => c.element).toList (growable: false );
178
- final enclosingElement =
179
- inheritenceElement.enclosingElement as InterfaceElement ;
182
+ // Elements in the inheritance chain starting from `this.element` up to,
183
+ // but not including, `Object`.
184
+ var enclosingElement =
185
+ inheritedElement.enclosingElement as InterfaceElement ;
180
186
assert (inheritanceChainElements.contains (enclosingElement) ||
181
187
enclosingElement.isDartCoreObject);
182
188
183
- // If the concrete object from
184
- // [InheritanceManager3.getInheritedConcreteMap2] is farther from this
185
- // class in the inheritance chain than the one provided by
186
- // `inheritedMap2`, prefer `inheritedMap2`. This correctly accounts for
187
- // intermediate abstract classes that have method/field implementations.
188
- if (inheritanceChainElements.indexOf (
189
- combinedMapElement.enclosingElement as InterfaceElement ) <
189
+ // If the concrete element from `getInheritedConcreteMap2` is farther in
190
+ // the inheritance chain from this class than the (non-concrete) one
191
+ // provided by `getInheritedMap2`, prefer the latter. This correctly
192
+ // accounts for intermediate abstract classes that have method/field
193
+ // implementations.
194
+ var enclosingElementFromCombined =
195
+ combinedMapElement.enclosingElement as InterfaceElement ;
196
+ if (inheritanceChainElements.indexOf (enclosingElementFromCombined) <
190
197
inheritanceChainElements.indexOf (enclosingElement)) {
191
- combinedMap[name.name] = inheritenceElement ;
198
+ combinedMap[name.name] = inheritedElement ;
192
199
}
193
200
}
194
201
202
+ // Finally, return all of the elements ultimately collected in the combined
203
+ // map.
195
204
return combinedMap.values.toList (growable: false );
196
- }
205
+ }();
197
206
198
207
/// All fields defined on this container, _including inherited fields_.
199
208
late List <Field > allFields = () {
@@ -308,12 +317,13 @@ abstract class InheritingContainer extends Container
308
317
309
318
bool get hasPublicSuperChainReversed => publicSuperChainReversed.isNotEmpty;
310
319
311
- /// Not the same as [superChain] as it may include mixins.
320
+ /// A sorted list of [element] 's inheritance chain, including interfaces and
321
+ /// mixins.
312
322
///
313
- /// It's really not even the same as ordinary Dart inheritance, either ,
323
+ /// Note: this list is really not even the same as ordinary Dart inheritance,
314
324
/// because we pretend that interfaces are part of the inheritance chain
315
325
/// to include them in the set of things we might link to for documentation
316
- /// purposes in abstract classes .
326
+ /// purposes.
317
327
List <InheritingContainer > get inheritanceChain;
318
328
319
329
@visibleForTesting
@@ -376,19 +386,21 @@ abstract class InheritingContainer extends Container
376
386
Iterable <DefinedElementType > get publicSuperChainReversed =>
377
387
publicSuperChain.reversed;
378
388
389
+ /// The chain of super-types, starting with [supertype] , up to, but not
390
+ /// including, `Object` .
379
391
List <DefinedElementType > get superChain {
380
392
var typeChain = < DefinedElementType > [];
381
393
var parent = supertype;
382
394
while (parent != null ) {
383
395
typeChain.add (parent);
384
396
final parentType = parent.type;
385
397
if (parentType is ! InterfaceType ) {
386
- throw StateError (' ancestor of $this is $parent with model element '
387
- '${parent .modelElement }' );
398
+ throw StateError (" ancestor of ' $this ' is ' $parent ' with model element "
399
+ " '${parent .modelElement }'" );
388
400
}
389
401
390
402
var superclass = parentType.superclass;
391
- // Avoid adding [ Object] to the [ superChain] ([ _supertype] already has
403
+ // Avoid adding ` Object` to the ` superChain` (` _supertype` already has
392
404
// this check).
393
405
if (superclass == null || superclass.superclass == null ) {
394
406
break ;
0 commit comments