Skip to content

Commit

Permalink
Display the known 'implementers' of an extension type (#3682)
Browse files Browse the repository at this point in the history
Also, re-spell each instance of 'implementor' to 'implementer'
  • Loading branch information
srawlins authored Feb 26, 2024
1 parent 5ea87b2 commit 40c470e
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 69 deletions.
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

0 comments on commit 40c470e

Please sign in to comment.