diff --git a/lib/src/generator/templates.runtime_renderers.dart b/lib/src/generator/templates.runtime_renderers.dart index d304457ec8..03d0ada28e 100644 --- a/lib/src/generator/templates.runtime_renderers.dart +++ b/lib/src/generator/templates.runtime_renderers.dart @@ -2734,34 +2734,6 @@ class _Renderer_Class extends RendererBase { ); }, ), - 'inheritanceChain': Property( - getValue: (CT_ c) => c.inheritanceChain, - renderVariable: - (CT_ c, Property self, List remainingNames) => - self.renderSimpleVariable( - c, - remainingNames, - 'List', - ), - - renderIterable: - ( - CT_ c, - RendererBase r, - List ast, - StringSink sink, - ) { - return c.inheritanceChain.map( - (e) => _render_InheritingContainer( - e, - ast, - r.template, - sink, - parent: r, - ), - ); - }, - ), 'isAbstract': Property( getValue: (CT_ c) => c.isAbstract, renderVariable: @@ -7213,34 +7185,6 @@ class _Renderer_Enum extends RendererBase { ); }, ), - 'inheritanceChain': Property( - getValue: (CT_ c) => c.inheritanceChain, - renderVariable: - (CT_ c, Property self, List remainingNames) => - self.renderSimpleVariable( - c, - remainingNames, - 'List', - ), - - renderIterable: - ( - CT_ c, - RendererBase r, - List ast, - StringSink sink, - ) { - return c.inheritanceChain.map( - (e) => _render_InheritingContainer( - e, - ast, - r.template, - sink, - parent: r, - ), - ); - }, - ), 'isAbstract': Property( getValue: (CT_ c) => c.isAbstract, renderVariable: @@ -8519,34 +8463,6 @@ class _Renderer_ExtensionType extends RendererBase { ); }, ), - 'inheritanceChain': Property( - getValue: (CT_ c) => c.inheritanceChain, - renderVariable: - (CT_ c, Property self, List remainingNames) => - self.renderSimpleVariable( - c, - remainingNames, - 'List', - ), - - renderIterable: - ( - CT_ c, - RendererBase r, - List ast, - StringSink sink, - ) { - return c.inheritanceChain.map( - (e) => _render_InheritingContainer( - e, - ast, - r.template, - sink, - parent: r, - ), - ); - }, - ), 'isAbstract': Property( getValue: (CT_ c) => c.isAbstract, renderVariable: @@ -11894,34 +11810,6 @@ class _Renderer_InheritingContainer extends RendererBase { getBool: (CT_ c) => c.hasPublicSuperChainReversed, ), - 'inheritanceChain': Property( - getValue: (CT_ c) => c.inheritanceChain, - renderVariable: - (CT_ c, Property self, List remainingNames) => - self.renderSimpleVariable( - c, - remainingNames, - 'List', - ), - - renderIterable: - ( - CT_ c, - RendererBase r, - List ast, - StringSink sink, - ) { - return c.inheritanceChain.map( - (e) => _render_InheritingContainer( - e, - ast, - r.template, - sink, - parent: r, - ), - ); - }, - ), 'instanceFields': Property( getValue: (CT_ c) => c.instanceFields, renderVariable: @@ -15922,34 +15810,6 @@ class _Renderer_Mixin extends RendererBase { getBool: (CT_ c) => c.hasPublicSuperclassConstraints, ), - 'inheritanceChain': Property( - getValue: (CT_ c) => c.inheritanceChain, - renderVariable: - (CT_ c, Property self, List remainingNames) => - self.renderSimpleVariable( - c, - remainingNames, - 'List', - ), - - renderIterable: - ( - CT_ c, - RendererBase r, - List ast, - StringSink sink, - ) { - return c.inheritanceChain.map( - (e) => _render_InheritingContainer( - e, - ast, - r.template, - sink, - parent: r, - ), - ); - }, - ), 'isAbstract': Property( getValue: (CT_ c) => c.isAbstract, renderVariable: @@ -25741,6 +25601,7 @@ const _invisibleGetters = { 'nonSynthetic2', 'runtimeType', 'session', + 'sinceSdkVersion', }, 'EnumElement2': { 'constants2', @@ -26192,6 +26053,7 @@ const _invisibleGetters = { 'baseElement', 'children', 'children2', + 'constantInitializer', 'constantInitializer2', 'context', 'declaration', diff --git a/lib/src/model/class.dart b/lib/src/model/class.dart index cbf60cb15c..8c206d77bb 100644 --- a/lib/src/model/class.dart +++ b/lib/src/model/class.dart @@ -14,8 +14,6 @@ import 'package:dartdoc/src/model/model.dart'; /// **instance**: As with [Container], but also includes inherited children. /// **inherited**: Filtered getters giving only inherited children. class Class extends InheritingContainer with Constructable, MixedInTypes { - @override - @override final ClassElement2 element; @@ -29,22 +27,6 @@ class Class extends InheritingContainer with Constructable, MixedInTypes { String get sidebarPath => '${canonicalLibraryOrThrow.dirName}/$name-class-sidebar.html'; - @override - late final List inheritanceChain = [ - this, - - // Caching should make this recursion a little less painful. - for (var container in mixedInTypes.modelElements.reversed) - ...container.inheritanceChain, - - for (var container in superChain.modelElements) - ...container.inheritanceChain, - - // Interfaces need to come last, because classes in the superChain might - // implement them even when they aren't mentioned. - ...interfaceElements.expandInheritanceChain, - ]; - Class(this.element, Library library, PackageGraph packageGraph) : super(library, packageGraph) { if (element.name3 == 'Object' && @@ -75,8 +57,7 @@ class Class extends InheritingContainer with Constructable, MixedInTypes { bool get isFinal => element.isFinal && !element.isSealed; @override - bool get isImplementableInterface => - element.isInterface && !element.isSealed; + bool get isImplementableInterface => element.isInterface && !element.isSealed; @override bool get isMixinClass => element.isMixinClass; diff --git a/lib/src/model/enum.dart b/lib/src/model/enum.dart index db78ea3186..9ec869294f 100644 --- a/lib/src/model/enum.dart +++ b/lib/src/model/enum.dart @@ -20,16 +20,6 @@ class Enum extends InheritingContainer with Constructable, MixedInTypes { ...constructors, ]; - @override - late final List inheritanceChain = [ - this, - for (var container in mixedInTypes.modelElements.reversed) - ...container.inheritanceChain, - for (var container in superChain.modelElements) - ...container.inheritanceChain, - ...interfaceElements.expandInheritanceChain, - ]; - @override // Prevent a collision with the library file. String get fileName => name == 'index' ? '$name-enum.html' : '$name.html'; diff --git a/lib/src/model/extension_type.dart b/lib/src/model/extension_type.dart index 71239eb687..c0771ce517 100644 --- a/lib/src/model/extension_type.dart +++ b/lib/src/model/extension_type.dart @@ -10,9 +10,8 @@ import 'package:dartdoc/src/model/model.dart'; import 'package:meta/meta.dart'; class ExtensionType extends InheritingContainer with Constructable { - @override - final ExtensionTypeElement2 element; + final ExtensionTypeElement2 element; late final ElementType representationType = getTypeFor(element.representation2.type, library); @@ -45,13 +44,11 @@ class ExtensionType extends InheritingContainer with Constructable { ContainerAccessor? getter, setter; final fieldGetter = field.getter2; if (fieldGetter != null) { - getter = ContainerAccessor( - fieldGetter, library, packageGraph, this); + getter = ContainerAccessor(fieldGetter, library, packageGraph, this); } final fieldSetter = field.setter2; if (fieldSetter != null) { - setter = ContainerAccessor( - fieldSetter, library, packageGraph, this); + setter = ContainerAccessor(fieldSetter, library, packageGraph, this); } return getModelForPropertyInducingElement(field, library, getter: getter, setter: setter) as Field; @@ -63,12 +60,6 @@ class ExtensionType extends InheritingContainer with Constructable { ...constructors, ]; - @override - late final List inheritanceChain = [ - this, - ...interfaceElements.expandInheritanceChain, - ]; - @override String get fileName => '$name-extension-type.html'; diff --git a/lib/src/model/inheritable.dart b/lib/src/model/inheritable.dart index d5eb337b47..17c72012b6 100644 --- a/lib/src/model/inheritable.dart +++ b/lib/src/model/inheritable.dart @@ -5,7 +5,6 @@ import 'package:analyzer/dart/element/element2.dart'; import 'package:collection/collection.dart' show IterableExtension; import 'package:dartdoc/src/model/attribute.dart'; -import 'package:dartdoc/src/model/comment_referable.dart'; import 'package:dartdoc/src/model/model.dart'; /// Mixin for subclasses of [ModelElement] representing elements that can be @@ -60,38 +59,20 @@ mixin Inheritable on ContainerMember { var searchElement = element.baseElement; // TODO(jcollins-g): generate warning if an inherited element's definition // is in an intermediate non-canonical class in the inheritance chain? - var reverseInheritance = _inheritance.reversed.toList(); - for (var i = 0; i < reverseInheritance.length; i++) { - var container = reverseInheritance[i]; + var candidates = _enclosingSuperTypes; + for (var i = 0; i < candidates.length; i++) { + var container = candidates[i]; if (container.containsElement(searchElement)) { - var previousIsHiddenAndNotDefining = i > 0 && - _isHiddenInterface(reverseInheritance[i - 1]) && - container != definingEnclosingContainer; var thisIsHiddenAndDefining = _isHiddenInterface(container) && container == definingEnclosingContainer; - // If the previous container in the search is one of the "hidden" - // interfaces, and it's not this member's defining container, OR if this - // container in the search is one of the "hidden" interfaces, and it is - // also this member's defining container, then we can immediately return - // the canonical enclosing container of the overridden member in the - // previous, non-hidden container in the inheritance. - if (previousIsHiddenAndNotDefining || thisIsHiddenAndDefining) { - var previousVisible = reverseInheritance - .take(i) - .lastWhere((e) => !_isHiddenInterface(e)); - var membersInPreviousVisible = previousVisible.allModelElements - .where((e) => e.name == name) - .whereType() - .whereNotType(); - assert( - membersInPreviousVisible.length == 1, - 'found multiple members named "$name" in ' - '"${previousVisible.name}": ' - '${membersInPreviousVisible.toList()}'); - return membersInPreviousVisible.first.canonicalEnclosingContainer; + + if (thisIsHiddenAndDefining) { + return container.supertype?.modelElement.canonicalModelElement + as Container?; } var canonicalContainer = packageGraph.findCanonicalModelElementFor(container) as Container?; + // TODO(jcollins-g): invert this lookup so traversal is recursive // starting from the ModelElement. if (canonicalContainer != null) { @@ -118,34 +99,57 @@ mixin Inheritable on ContainerMember { c.element.name3 == 'Interceptor' && c.element.library2?.name3 == '_interceptors'; - /// A roughly ordered list of this element's enclosing container's inheritance - /// chain. + /// All of the various supertypes of [enclosingElement], in a specific order. /// - /// See [InheritingContainer.inheritanceChain] for details. - List get _inheritance { - var inheritance = [ - ...(enclosingElement as InheritingContainer).inheritanceChain, - ]; - - assert( - definingEnclosingContainer.isDartCoreObject || - inheritance.contains(definingEnclosingContainer), () { - var inheritanceDescriptions = inheritance - .map((e) => - "'$e' (hashCode: ${e.hashCode}, in library '${e.library}')") - .toList(); - return "Given '$this', on '$enclosingElement' in library '$library', " - "the defining enclosing container, '$definingEnclosingContainer' " - '(hashCode: ${definingEnclosingContainer.hashCode}, ' - "in library '${definingEnclosingContainer.library}'), should have " - 'been Object or contained in: $inheritanceDescriptions'; - }()); - // Unless the code explicitly extends dart:core's Object, we won't get - // an entry here. So add it. - if (!inheritance.last.isDartCoreObject) { - inheritance.add(packageGraph.objectClass); + /// The first types are the interfaces, supertypes, and mixed-in types of + /// [enclosingElement]'s supertype. Next is [enclosingElement]'s supertype + /// itself. Next are the interfaces, supertypes, and mixed-in types of each + /// directly mixed-in type, followed by each directly mixed-in type. Next are + /// the interfaces, supertypes, and mixed-in types of each direct interface, + /// followed by each direct interface. Last is [enclosingElement]. + List get _enclosingSuperTypes { + var result = {}; + var processed = {}; + + void addSupertype(InheritingContainer container) { + if (processed.contains(container)) return; + processed.add(container); + for (var interface in container.interfaceElements) { + addSupertype(interface); + result.add(interface); + } + var supertype = container.supertype?.modelElement; + if (supertype is InheritingContainer) { + addSupertype(supertype); + result.add(supertype); + } + if (container case Class(:var mixedInTypes) || Enum(:var mixedInTypes)) { + for (var mixedIn in mixedInTypes.modelElements.reversed) { + addSupertype(mixedIn); + result.add(mixedIn); + } + } + result.add(container); } - return inheritance; + + var enclosingElement = this.enclosingElement as InheritingContainer; + if (enclosingElement.supertype?.modelElement + case InheritingContainer supertype) { + addSupertype(supertype); + } + if (enclosingElement + case Class(:var mixedInTypes) || Enum(:var mixedInTypes)) { + for (var mixedIn in mixedInTypes.modelElements.reversed) { + addSupertype(mixedIn); + result.add(mixedIn); + } + } + for (var interface in enclosingElement.interfaceElements) { + addSupertype(interface); + } + result.add(enclosingElement); + + return result.toList(); } Inheritable? get overriddenElement; diff --git a/lib/src/model/inheriting_container.dart b/lib/src/model/inheriting_container.dart index 550ae7301d..5457a5e2c0 100644 --- a/lib/src/model/inheriting_container.dart +++ b/lib/src/model/inheriting_container.dart @@ -72,8 +72,7 @@ abstract class InheritingContainer extends Container { DefinedElementType? get supertype { final elementSupertype = element.supertype; - return elementSupertype == null || - elementSupertype.element3.supertype == null + return elementSupertype == null ? null : getTypeFor(elementSupertype, library) as DefinedElementType; } @@ -256,15 +255,6 @@ abstract class InheritingContainer extends Container { bool get hasPublicSuperChainReversed => superChain.any((e) => e.isPublic); - /// A sorted list of [element]'s inheritance chain, including interfaces and - /// mixins. - /// - /// Note: this list is really not even the same as ordinary Dart inheritance, - /// because we pretend that interfaces are part of the inheritance chain - /// to include them in the set of things we might link to for documentation - /// purposes. - List get inheritanceChain; - @visibleForTesting Iterable get inheritedFields => _allFields.where((f) => f.isInherited); @@ -488,10 +478,8 @@ abstract class InheritingContainer extends Container { return interfaces; } - Iterable get publicInterfaceElements => [ - for (var interface in publicInterfaces) - interface.modelElement as InheritingContainer, - ]; + Iterable get publicInterfaceElements => + publicInterfaces.modelElements; Iterable get publicSuperChainReversed => [...superChain.wherePublic].reversed; @@ -502,6 +490,9 @@ abstract class InheritingContainer extends Container { var typeChain = []; var parent = supertype; while (parent != null) { + if ((parent.modelElement as Container).isDartCoreObject) { + break; + } typeChain.add(parent); final parentType = parent.type; if (parentType is! InterfaceType) { @@ -510,9 +501,7 @@ abstract class InheritingContainer extends Container { } var superclass = parentType.superclass; - // Avoid adding `Object` to the `superChain` (`_supertype` already has - // this check). - if (superclass == null || superclass.superclass == null) { + if (superclass == null) { break; } parent = getTypeFor(superclass, library) as DefinedElementType?; @@ -615,10 +604,3 @@ extension DefinedElementTypeIterableExtension on Iterable { List get modelElements => map((e) => e.modelElement as InheritingContainer).toList(); } - -extension InheritingContainerIterableExtension - on Iterable { - /// Expands each element to its inheritance chain. - Iterable get expandInheritanceChain => - expand((e) => e.inheritanceChain); -} diff --git a/lib/src/model/mixin.dart b/lib/src/model/mixin.dart index 139463626e..2d9227ebec 100644 --- a/lib/src/model/mixin.dart +++ b/lib/src/model/mixin.dart @@ -12,7 +12,6 @@ import 'package:dartdoc/src/model_utils.dart' as model_utils; import 'package:meta/meta.dart'; class Mixin extends InheritingContainer { - @override final MixinElement2 element; @@ -28,19 +27,6 @@ class Mixin extends InheritingContainer { String get sidebarPath => '${canonicalLibraryOrThrow.dirName}/$name-mixin-sidebar.html'; - @override - late final List inheritanceChain = [ - this, - ...superclassConstraints.modelElements.expandInheritanceChain, - - for (var container in superChain.modelElements) - ...container.inheritanceChain, - - // Interfaces need to come last, because classes in the `superChain` might - // implement them even when they aren't mentioned. - ...interfaceElements.expandInheritanceChain, - ]; - Mixin(this.element, super.library, super.packageGraph); @override diff --git a/test/templates/enum_test.dart b/test/templates/enum_test.dart index dd04d11df6..594714b50c 100644 --- a/test/templates/enum_test.dart +++ b/test/templates/enum_test.dart @@ -105,7 +105,6 @@ extension Ext on E {} path.join(packagePath, 'doc'), '--sdk-dir', packageMetaProvider.defaultSdkDir.path, - '--no-link-to-remote', ], packageMetaProvider); var packageConfigProvider = @@ -241,7 +240,7 @@ extension Ext on E {} eLines, containsAllInOrder([ matches('

Properties

'), - matches('hashCode'), + matches('hashCode'), ])); }); @@ -250,7 +249,7 @@ extension Ext on E {} eLines, containsAllInOrder([ matches('

Properties

'), - matches('index'), + matches('index'), matches('The integer index of this enum value.'), ])); }); @@ -363,7 +362,7 @@ extension Ext on E {} containsAllInOrder([ matches('Properties'), matches('f1'), - matches('index'), + matches('index'), ]), ); });