Skip to content

Simplify InheritingContainer wrt inherited elements #4059

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 4 additions & 86 deletions lib/src/generator/templates.runtime_renderers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7213,14 +7213,6 @@ class _Renderer_Enum extends RendererBase<Enum> {
);
},
),
'hasPublicEnumValues': Property(
getValue: (CT_ c) => c.hasPublicEnumValues,
renderVariable:
(CT_ c, Property<CT_> self, List<String> remainingNames) =>
self.renderSimpleVariable(c, remainingNames, 'bool'),

getBool: (CT_ c) => c.hasPublicEnumValues,
),
'inheritanceChain': Property(
getValue: (CT_ c) => c.inheritanceChain,
renderVariable:
Expand Down Expand Up @@ -11498,29 +11490,6 @@ class _Renderer_InheritingContainer extends RendererBase<InheritingContainer> {
CT_,
() => {
..._Renderer_Container.propertyMap<CT_>(),
'allFields': Property(
getValue: (CT_ c) => c.allFields,
renderVariable:
(CT_ c, Property<CT_> self, List<String> remainingNames) =>
self.renderSimpleVariable(
c,
remainingNames,
'List<Field>',
),

renderIterable:
(
CT_ c,
RendererBase<CT_> r,
List<MustachioNode> ast,
StringSink sink,
) {
return c.allFields.map(
(e) =>
_render_Field(e, ast, r.template, sink, parent: r),
);
},
),
'allModelElements': Property(
getValue: (CT_ c) => c.allModelElements,
renderVariable:
Expand Down Expand Up @@ -11953,57 +11922,6 @@ class _Renderer_InheritingContainer extends RendererBase<InheritingContainer> {
);
},
),
'inheritedMethods': Property(
getValue: (CT_ c) => c.inheritedMethods,
renderVariable:
(CT_ c, Property<CT_> self, List<String> remainingNames) =>
self.renderSimpleVariable(
c,
remainingNames,
'Iterable<Method>',
),

renderIterable:
(
CT_ c,
RendererBase<CT_> r,
List<MustachioNode> ast,
StringSink sink,
) {
return c.inheritedMethods.map(
(e) =>
_render_Method(e, ast, r.template, sink, parent: r),
);
},
),
'inheritedOperators': Property(
getValue: (CT_ c) => c.inheritedOperators,
renderVariable:
(CT_ c, Property<CT_> self, List<String> remainingNames) =>
self.renderSimpleVariable(
c,
remainingNames,
'List<Operator>',
),

renderIterable:
(
CT_ c,
RendererBase<CT_> r,
List<MustachioNode> ast,
StringSink sink,
) {
return c.inheritedOperators.map(
(e) => _render_Operator(
e,
ast,
r.template,
sink,
parent: r,
),
);
},
),
'instanceFields': Property(
getValue: (CT_ c) => c.instanceFields,
renderVariable:
Expand Down Expand Up @@ -14263,7 +14181,7 @@ class _Renderer_LibraryContainer extends RendererBase<LibraryContainer> {
}
}

String renderLibraryRedirect(LibraryTemplateData context, Template template) {
String renderLibrary(LibraryTemplateData context, Template template) {
var buffer = StringBuffer();
_render_LibraryTemplateData(context, template.ast, template, buffer);
return buffer.toString();
Expand Down Expand Up @@ -14501,7 +14419,7 @@ class _Renderer_LibraryTemplateData extends RendererBase<LibraryTemplateData> {
}
}

String renderLibrary(LibraryTemplateData context, Template template) {
String renderLibraryRedirect(LibraryTemplateData context, Template template) {
var buffer = StringBuffer();
_render_LibraryTemplateData(context, template.ast, template, buffer);
return buffer.toString();
Expand Down Expand Up @@ -20021,7 +19939,7 @@ class _Renderer_Package extends RendererBase<Package> {
}
}

String renderSearchPage(PackageTemplateData context, Template template) {
String renderIndex(PackageTemplateData context, Template template) {
var buffer = StringBuffer();
_render_PackageTemplateData(context, template.ast, template, buffer);
return buffer.toString();
Expand Down Expand Up @@ -20379,7 +20297,7 @@ class _Renderer_PackageTemplateData extends RendererBase<PackageTemplateData> {
}
}

String renderIndex(PackageTemplateData context, Template template) {
String renderSearchPage(PackageTemplateData context, Template template) {
var buffer = StringBuffer();
_render_PackageTemplateData(context, template.ast, template, buffer);
return buffer.toString();
Expand Down
14 changes: 6 additions & 8 deletions lib/src/model/enum.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:dartdoc/src/model/kind.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/model_utils.dart' as model_utils;
import 'package:meta/meta.dart';

class Enum extends InheritingContainer with Constructable, MixedInTypes {

@override
final EnumElement2 element;

Expand Down Expand Up @@ -51,12 +49,12 @@ class Enum extends InheritingContainer with Constructable, MixedInTypes {
declaredFields.where((f) => f is! EnumField && f.isConst);

@override
late final List<Field> publicEnumValues =
allFields.whereType<EnumField>().wherePublic.toList(growable: false);

@override
bool get hasPublicEnumValues =>
allFields.whereType<EnumField>().any((e) => e.isPublic);
late final List<Field> publicEnumValues = [
for (var value in element.constants2)
getModelForPropertyInducingElement(value, library,
getter: getModelFor(value.getter2!, library) as ContainerAccessor,
setter: null) as Field
];

@override
bool get isAbstract => false;
Expand Down
104 changes: 16 additions & 88 deletions lib/src/model/inheriting_container.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,29 +99,28 @@ abstract class InheritingContainer extends Container {
...typeParameters,
];

@visibleForTesting
Iterable<Method> get inheritedMethods {
var methodNames = declaredMethods.map((m) => m.element.name3).toSet();
var inheritedMethodElements = _inheritedElements
var inheritedMethodElements = element.inheritedMembers.values
.whereType<MethodElement2>()
.where((e) =>
!e.isOperator &&
e is! PropertyAccessorElement2 &&
!methodNames.contains(e.name3))
.toSet();
.where((e) => !e.isOperator)
.where((e) => !methodNames.contains(e.name3));

return [
for (var e in inheritedMethodElements)
getModelFor(e, library, enclosingContainer: this) as Method,
];
}

@visibleForTesting
List<Operator> get inheritedOperators {
var operatorNames =
declaredOperators.map((o) => o.element.lookupName).toSet();
var inheritedOperatorElements = _inheritedElements
var inheritedOperatorElements = element.inheritedMembers.values
.whereType<MethodElement2>()
.where((e) => e.isOperator && !operatorNames.contains(e.lookupName))
.toSet();
.where((e) => e.isOperator)
.where((e) => !operatorNames.contains(e.name3));

return [
for (var e in inheritedOperatorElements)
Expand All @@ -132,74 +131,10 @@ abstract class InheritingContainer extends Container {
late final DefinedElementType modelType =
getTypeFor(element.thisType, library) as DefinedElementType;

/// A list of the inherited executable elements, one element per inherited
/// `Name`.
///
/// In this list, elements that are "closer" in the inheritance chain to
/// _this_ element are preferred over elements that are further away. In the
/// case of ties, concrete inherited elements are prefered to non-concrete
/// ones.
late final List<ExecutableElement2> _inheritedElements = () {
if (element case ClassElement2 classElement
when classElement.isDartCoreObject) {
return const <ExecutableElement2>[];
}

// The mapping of all of the inherited element names to their _concrete_
// implementation element.
var concreteInheritanceMap =
packageGraph.inheritanceManager.getInheritedConcreteMap(element);
// The mapping of all inherited element names to the nearest inherited
// element that they resolve to.
var inheritanceMap =
packageGraph.inheritanceManager.getInheritedMap(element);

var inheritanceChainElements =
inheritanceChain.map((c) => c.element).toList(growable: false);

// A combined map of names to inherited _concrete_ Elements, and other
// inherited Elements.
var combinedMap = {
for (var MapEntry(:key, :value) in concreteInheritanceMap.entries)
key.name: value,
};
for (var MapEntry(key: name, value: inheritedElement)
in inheritanceMap.entries) {
var combinedMapElement = combinedMap[name.name];
if (combinedMapElement == null) {
combinedMap[name.name] = inheritedElement;
continue;
}

// Elements in the inheritance chain starting from `this.element` up to,
// but not including, `Object`.
var enclosingElement =
inheritedElement.enclosingElement2 as InterfaceElement2;
assert(inheritanceChainElements.contains(enclosingElement) ||
enclosingElement.isDartCoreObject);

// If the concrete element from `getInheritedConcreteMap2` is farther in
// the inheritance chain from this class than the (non-concrete) one
// provided by `getInheritedMap2`, prefer the latter. This correctly
// accounts for intermediate abstract classes that have method/field
// implementations.
var enclosingElementFromCombined =
combinedMapElement.enclosingElement2 as InterfaceElement2;
if (inheritanceChainElements.indexOf(enclosingElementFromCombined) <
inheritanceChainElements.indexOf(enclosingElement)) {
combinedMap[name.name] = inheritedElement;
}
}

// Finally, return all of the elements ultimately collected in the combined
// map.
return combinedMap.values.toList(growable: false);
}();

/// All fields defined on this container, _including inherited fields_.
late List<Field> allFields = () {
late final List<Field> _allFields = () {
var inheritedAccessorElements = {
..._inheritedElements.whereType<PropertyAccessorElement2>()
...element.inheritedMembers.values.whereType<PropertyAccessorElement2>()
};

// This structure keeps track of inherited accessors, allowing lookup
Expand Down Expand Up @@ -285,17 +220,15 @@ abstract class InheritingContainer extends Container {
List<ModelElement> get allModelElements => _allModelElements;

@override
Iterable<Field> get constantFields => allFields.where((f) => f.isConst);
Iterable<Field> get constantFields => _allFields.where((f) => f.isConst);

@override
Iterable<Field> get declaredFields => allFields.where((f) => !f.isInherited);
Iterable<Field> get declaredFields => _allFields.where((f) => !f.isInherited);

/// The [InheritingContainer] with the library in which [element] is defined.
InheritingContainer get definingContainer =>
getModelFor(element, library) as InheritingContainer;

@override

@override
InterfaceElement2 get element;

Expand Down Expand Up @@ -333,10 +266,10 @@ abstract class InheritingContainer extends Container {
List<InheritingContainer> get inheritanceChain;

@visibleForTesting
Iterable<Field> get inheritedFields => allFields.where((f) => f.isInherited);
Iterable<Field> get inheritedFields => _allFields.where((f) => f.isInherited);

@override
Iterable<Field> get instanceFields => allFields.where((f) => !f.isStatic);
Iterable<Field> get instanceFields => _allFields.where((f) => !f.isStatic);

@override
late final List<Field> availableInstanceFieldsSorted = [
Expand Down Expand Up @@ -371,8 +304,8 @@ abstract class InheritingContainer extends Container {
List<Method> get _extensionInstanceMethods => [
for (var extension in potentiallyApplicableExtensionsSorted)
for (var method in extension.instanceMethods)
getModelFor(method.element, library,
enclosingContainer: extension) as Method,
getModelFor(method.element, library, enclosingContainer: extension)
as Method,
];

@override
Expand Down Expand Up @@ -677,11 +610,6 @@ mixin MixedInTypes on InheritingContainer {
mixedInTypes.wherePublic;
}

extension on InterfaceElement2 {
bool get isDartCoreObject =>
name3 == 'Object' && library2.name3 == 'dart.core';
}

extension DefinedElementTypeIterableExtension on Iterable<DefinedElementType> {
/// The [ModelElement] for each element.
List<InheritingContainer> get modelElements =>
Expand Down
Loading