@@ -100,15 +100,10 @@ abstract class InheritingContainer extends Container
100100 late final List <LanguageFeature > displayedLanguageFeatures =
101101 containerModifiers.asLanguageFeatureSet.toList ();
102102
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+ ];
112107
113108 Iterable <Method > get inheritedMethods {
114109 var methodNames = declaredMethods.map ((m) => m.element.name).toSet ();
@@ -145,55 +140,69 @@ abstract class InheritingContainer extends Container
145140 late final List <DefinedElementType > publicSuperChain =
146141 model_utils.filterNonPublic (superChain).toList (growable: false );
147142
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) {
152153 return const < ExecutableElement > [];
153154 }
154155
155- final concreteInheritenceMap =
156+ // The mapping of all of the inherited element names to their _concrete_
157+ // implementation element.
158+ var concreteInheritanceMap =
156159 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 =
158163 packageGraph.inheritanceManager.getInheritedMap2 (element);
159164
160- List <InterfaceElement >? inheritanceChainElements;
165+ var inheritanceChainElements =
166+ inheritanceChain.map ((c) => c.element).toList (growable: false );
161167
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,
165173 };
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];
169177 if (combinedMapElement == null ) {
170- combinedMap[name.name] = inheritenceElement ;
178+ combinedMap[name.name] = inheritedElement ;
171179 continue ;
172180 }
173181
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 ;
180186 assert (inheritanceChainElements.contains (enclosingElement) ||
181187 enclosingElement.isDartCoreObject);
182188
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) <
190197 inheritanceChainElements.indexOf (enclosingElement)) {
191- combinedMap[name.name] = inheritenceElement ;
198+ combinedMap[name.name] = inheritedElement ;
192199 }
193200 }
194201
202+ // Finally, return all of the elements ultimately collected in the combined
203+ // map.
195204 return combinedMap.values.toList (growable: false );
196- }
205+ }();
197206
198207 /// All fields defined on this container, _including inherited fields_.
199208 late List <Field > allFields = () {
@@ -308,12 +317,13 @@ abstract class InheritingContainer extends Container
308317
309318 bool get hasPublicSuperChainReversed => publicSuperChainReversed.isNotEmpty;
310319
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.
312322 ///
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,
314324 /// because we pretend that interfaces are part of the inheritance chain
315325 /// to include them in the set of things we might link to for documentation
316- /// purposes in abstract classes .
326+ /// purposes.
317327 List <InheritingContainer > get inheritanceChain;
318328
319329 @visibleForTesting
@@ -376,19 +386,21 @@ abstract class InheritingContainer extends Container
376386 Iterable <DefinedElementType > get publicSuperChainReversed =>
377387 publicSuperChain.reversed;
378388
389+ /// The chain of super-types, starting with [supertype] , up to, but not
390+ /// including, `Object` .
379391 List <DefinedElementType > get superChain {
380392 var typeChain = < DefinedElementType > [];
381393 var parent = supertype;
382394 while (parent != null ) {
383395 typeChain.add (parent);
384396 final parentType = parent.type;
385397 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 }'" );
388400 }
389401
390402 var superclass = parentType.superclass;
391- // Avoid adding [ Object] to the [ superChain] ([ _supertype] already has
403+ // Avoid adding ` Object` to the ` superChain` (` _supertype` already has
392404 // this check).
393405 if (superclass == null || superclass.superclass == null ) {
394406 break ;
0 commit comments