Skip to content
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

Display the known 'implementers' of an extension type #3682

Merged
merged 2 commits into from
Feb 26, 2024
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
32 changes: 25 additions & 7 deletions lib/src/generator/templates.aot_renderers_for_html.dart
Original file line number Diff line number Diff line change
Expand Up @@ -322,12 +322,12 @@ String renderClass(ClassTemplateData context0) {
buffer.write('\n ');
buffer.write(_renderClass_partial_mixed_in_types_7(context2));
buffer.writeln();
if (context2.hasPublicImplementors) {
if (context2.hasPublicImplementers) {
buffer.writeln();
buffer.write('''
<dt>Implementers</dt>
<dd><ul class="comma-separated clazz-relationships">''');
var context3 = context2.publicImplementorsSorted;
var context3 = context2.publicImplementersSorted;
for (var context4 in context3) {
buffer.writeln();
buffer.write('''
Expand Down Expand Up @@ -865,6 +865,24 @@ String renderExtensionType<T extends ExtensionType>(
''');
buffer.write(_renderExtensionType_partial_interfaces_5(context2));
buffer.writeln();
if (context2.hasPublicImplementers) {
buffer.writeln();
buffer.write('''
<dt>Implementers</dt>
<dd><ul class="comma-separated clazz-relationships">''');
var context4 = context2.publicImplementersSorted;
for (var context5 in context4) {
buffer.writeln();
buffer.write('''
<li>''');
buffer.write(context5.linkedName);
buffer.write('''</li>''');
}
buffer.writeln();
buffer.write('''
</ul></dd>''');
}
buffer.writeln();
buffer.write('''
</dl>
''');
Expand All @@ -883,10 +901,10 @@ String renderExtensionType<T extends ExtensionType>(
<h2>Properties</h2>

<dl class="properties">''');
var context4 = context2.publicInstanceFieldsSorted;
for (var context5 in context4) {
var context6 = context2.publicInstanceFieldsSorted;
for (var context7 in context6) {
buffer.write('\n ');
buffer.write(_renderExtensionType_partial_property_8(context5));
buffer.write(_renderExtensionType_partial_property_8(context7));
}
buffer.writeln();
buffer.write('''
Expand Down Expand Up @@ -1528,13 +1546,13 @@ String renderMixin(MixinTemplateData context0) {
buffer.write('\n ');
buffer.write(_renderMixin_partial_interfaces_6(context2));
buffer.writeln();
if (context2.hasPublicImplementors) {
if (context2.hasPublicImplementers) {
buffer.writeln();
buffer.write('''
<dt>Mixin Applications</dt>
<dd>
<ul class="comma-separated mixin-relationships">''');
var context5 = context2.publicImplementorsSorted;
var context5 = context2.publicImplementersSorted;
for (var context6 in context5) {
buffer.writeln();
buffer.write('''
Expand Down
22 changes: 11 additions & 11 deletions lib/src/generator/templates.runtime_renderers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15225,12 +15225,12 @@ class _Renderer_TypeImplementing extends RendererBase<TypeImplementing> {
self.renderSimpleVariable(c, remainingNames, 'bool'),
getBool: (CT_ c) => c.hasModifiers,
),
'hasPublicImplementors': Property(
getValue: (CT_ c) => c.hasPublicImplementors,
'hasPublicImplementers': Property(
getValue: (CT_ c) => c.hasPublicImplementers,
renderVariable: (CT_ c, Property<CT_> self,
List<String> remainingNames) =>
self.renderSimpleVariable(c, remainingNames, 'bool'),
getBool: (CT_ c) => c.hasPublicImplementors,
getBool: (CT_ c) => c.hasPublicImplementers,
),
'hasPublicInterfaces': Property(
getValue: (CT_ c) => c.hasPublicInterfaces,
Expand Down Expand Up @@ -15265,28 +15265,28 @@ class _Renderer_TypeImplementing extends RendererBase<TypeImplementing> {
parent: r));
},
),
'publicImplementors': Property(
getValue: (CT_ c) => c.publicImplementors,
'publicImplementers': Property(
getValue: (CT_ c) => c.publicImplementers,
renderVariable: (CT_ c, Property<CT_> self,
List<String> remainingNames) =>
self.renderSimpleVariable(
c, remainingNames, 'Iterable<InheritingContainer>'),
renderIterable: (CT_ c, RendererBase<CT_> r,
List<MustachioNode> ast, StringSink sink) {
return c.publicImplementors.map((e) =>
return c.publicImplementers.map((e) =>
_render_InheritingContainer(e, ast, r.template, sink,
parent: r));
},
),
'publicImplementorsSorted': Property(
getValue: (CT_ c) => c.publicImplementorsSorted,
'publicImplementersSorted': Property(
getValue: (CT_ c) => c.publicImplementersSorted,
renderVariable: (CT_ c, Property<CT_> self,
List<String> remainingNames) =>
self.renderSimpleVariable(
c, remainingNames, 'List<InheritingContainer>'),
renderIterable: (CT_ c, RendererBase<CT_> r,
List<MustachioNode> ast, StringSink sink) {
return c.publicImplementorsSorted.map((e) =>
return c.publicImplementersSorted.map((e) =>
_render_InheritingContainer(e, ast, r.template, sink,
parent: r));
},
Expand Down Expand Up @@ -16846,7 +16846,7 @@ const _invisibleGetters = {
'allConstructedModelElements',
'allExtensionsAdded',
'allHrefs',
'allImplementorsAdded',
'allImplementersAdded',
'allInheritableElements',
'allLibraries',
'allLibrariesAdded',
Expand All @@ -16862,7 +16862,7 @@ const _invisibleGetters = {
'hasEmbedderSdk',
'hasFooterVersion',
'hashCode',
'implementors',
'implementers',
'inheritThrough',
'inheritanceManager',
'libraries',
Expand Down
42 changes: 21 additions & 21 deletions lib/src/model/inheriting_container.dart
Original file line number Diff line number Diff line change
Expand Up @@ -503,14 +503,14 @@ mixin TypeImplementing on InheritingContainer {
getTypeFor(interface, library) as DefinedElementType
];

late final List<InheritingContainer> publicImplementorsSorted =
publicImplementors.toList(growable: false)..sort(byName);
late final List<InheritingContainer> publicImplementersSorted =
publicImplementers.toList(growable: false)..sort(byName);

@override
bool get hasModifiers =>
super.hasModifiers || hasPublicInterfaces || hasPublicImplementors;
super.hasModifiers || hasPublicInterfaces || hasPublicImplementers;

bool get hasPublicImplementors => publicImplementors.isNotEmpty;
bool get hasPublicImplementers => publicImplementers.isNotEmpty;

bool get hasPublicInterfaces => publicInterfaces.isNotEmpty;

Expand All @@ -522,34 +522,34 @@ mixin TypeImplementing on InheritingContainer {
interface.modelElement as InheritingContainer,
];

/// All the "immediate" public implementors of this [TypeImplementing].
/// All the "immediate" public implementers of this [TypeImplementing].
///
/// For a [Mixin], this is actually the mixin applications using the [Mixin].
///
/// If this [InheritingContainer] has a private implementor, then that is
/// counted as a proxy for any public implementors of that private container.
Iterable<InheritingContainer> get publicImplementors {
/// If this [InheritingContainer] has a private implementer, then that is
/// counted as a proxy for any public implementers of that private container.
Iterable<InheritingContainer> get publicImplementers {
var result = <InheritingContainer>{};
var seen = <InheritingContainer>{};

// Recursively adds [implementor] if public, or the implementors of
// [implementor] if not.
void addToResult(InheritingContainer implementor) {
if (seen.contains(implementor)) return;
seen.add(implementor);
if (implementor.isPublicAndPackageDocumented) {
result.add(implementor);
// Recursively adds [implementer] if public, or the implementers of
// [implementer] if not.
void addToResult(InheritingContainer implementer) {
if (seen.contains(implementer)) return;
seen.add(implementer);
if (implementer.isPublicAndPackageDocumented) {
result.add(implementer);
} else {
var implementors = packageGraph.implementors[implementor];
if (implementors != null) {
model_utils.findCanonicalFor(implementors).forEach(addToResult);
var implementers = packageGraph.implementers[implementer];
if (implementers != null) {
model_utils.findCanonicalFor(implementers).forEach(addToResult);
}
}
}

var immediateImplementors = packageGraph.implementors[this];
if (immediateImplementors != null) {
model_utils.findCanonicalFor(immediateImplementors).forEach(addToResult);
var immediateImplementers = packageGraph.implementers[this];
if (immediateImplementers != null) {
model_utils.findCanonicalFor(immediateImplementers).forEach(addToResult);
}
return result;
}
Expand Down
24 changes: 14 additions & 10 deletions lib/src/model/package_graph.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class PackageGraph with CommentReferable, Nameable {
package.warn(PackageWarning.noDocumentableLibrariesInPackage);
}
}
allImplementorsAdded = true;
allImplementersAdded = true;
allExtensionsAdded = true;

// We should have found all special classes by now.
Expand Down Expand Up @@ -280,17 +280,17 @@ class PackageGraph with CommentReferable, Nameable {

ModelNode? getModelNodeFor(Element element) => _modelNodes[element];

/// It is safe to cache values derived from the [_implementors] table if this
/// It is safe to cache values derived from the [_implementers] table if this
/// is true.
bool allImplementorsAdded = false;
bool allImplementersAdded = false;

/// It is safe to cache values derived from the [_extensions] table if this
/// is true.
bool allExtensionsAdded = false;

Map<InheritingContainer, List<InheritingContainer>> get implementors {
assert(allImplementorsAdded);
return _implementors;
Map<InheritingContainer, List<InheritingContainer>> get implementers {
assert(allImplementersAdded);
return _implementers;
}

Iterable<Extension> get documentedExtensions =>
Expand Down Expand Up @@ -323,8 +323,12 @@ class PackageGraph with CommentReferable, Nameable {
final Map<InheritableElementsKey, Set<ModelElement>> allInheritableElements =
{};

/// A mapping of the list of classes which implement each class.
final Map<InheritingContainer, List<InheritingContainer>> _implementors =
/// A mapping of the list of classes, enums, mixins, and extension types which
/// "implement" each class, mixin, and extension type.
///
/// For the purposes of the "Implementers" section in the output, this
/// includes elements that "implement" or "extend" another element.
final Map<InheritingContainer, List<InheritingContainer>> _implementers =
LinkedHashMap<InheritingContainer, List<InheritingContainer>>(
equals: (InheritingContainer a, InheritingContainer b) =>
a.definingContainer == b.definingContainer,
Expand Down Expand Up @@ -575,7 +579,7 @@ class PackageGraph with CommentReferable, Nameable {
}

void _addToImplementers(Iterable<InheritingContainer> containers) {
assert(!allImplementorsAdded);
assert(!allImplementersAdded);

// Private containers may not be included in documentation, but may still be
// necessary links in the implementation chain. They are added here as they
Expand All @@ -589,7 +593,7 @@ class PackageGraph with CommentReferable, Nameable {
}
implemented = implemented.canonicalModelElement as InheritingContainer? ??
implemented;
var list = _implementors.putIfAbsent(implemented, () => []);
var list = _implementers.putIfAbsent(implemented, () => []);
// TODO(srawlins): This would be more efficient if we created a
// SplayTreeSet keyed off of `.element`.
if (!list.any((l) => l.element == implementer.element)) {
Expand Down
8 changes: 4 additions & 4 deletions lib/templates/class.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
{{ >interfaces }}
{{ >mixed_in_types }}

{{ #hasPublicImplementors }}
{{ #hasPublicImplementers }}
<dt>Implementers</dt>
<dd><ul class="comma-separated clazz-relationships">
{{ #publicImplementorsSorted }}
{{ #publicImplementersSorted }}
<li>{{{ linkedName }}}</li>
{{ /publicImplementorsSorted }}
{{ /publicImplementersSorted }}
</ul></dd>
{{ /hasPublicImplementors }}
{{ /hasPublicImplementers }}

{{ #hasPotentiallyApplicableExtensions }}
<dt>Available Extensions</dt>
Expand Down
9 changes: 9 additions & 0 deletions lib/templates/extension_type.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@
</ul>
</dd>
{{ >interfaces }}

{{ #hasPublicImplementers }}
<dt>Implementers</dt>
<dd><ul class="comma-separated clazz-relationships">
{{ #publicImplementersSorted }}
<li>{{{ linkedName }}}</li>
{{ /publicImplementersSorted }}
</ul></dd>
{{ /hasPublicImplementers }}
</dl>
{{ >container_annotations }}
</section>
Expand Down
8 changes: 4 additions & 4 deletions lib/templates/mixin.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@
{{ >super_chain }}
{{ >interfaces }}

{{ #hasPublicImplementors }}
{{ #hasPublicImplementers }}
<dt>Mixin Applications</dt>
<dd>
<ul class="comma-separated mixin-relationships">
{{ #publicImplementorsSorted }}
{{ #publicImplementersSorted }}
<li>{{{ linkedName }}}</li>
{{ /publicImplementorsSorted }}
{{ /publicImplementersSorted }}
</ul>
</dd>
{{ /hasPublicImplementors }}
{{ /hasPublicImplementers }}

{{ >annotations }}
</dl>
Expand Down
Loading