Skip to content

Commit 0922660

Browse files
authored
Frame for merging scoped lookups (#2661)
* Frame for merging scoped lookups * rebuild * Review comments
1 parent 8ec6844 commit 0922660

File tree

5 files changed

+102
-15
lines changed

5 files changed

+102
-15
lines changed

lib/src/element_type.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import 'package:dartdoc/src/render/element_type_renderer.dart';
1616
/// may link to a [ModelElement].
1717
abstract class ElementType extends Privacy with CommentReferable, Nameable {
1818
final DartType _type;
19+
@override
1920
final PackageGraph packageGraph;
2021
final ElementType returnedFrom;
2122
@override

lib/src/generator/templates.runtime_renderers.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2586,6 +2586,19 @@ class _Renderer_CommentReferable extends RendererBase<CommentReferable> {
25862586
parent: r);
25872587
},
25882588
),
2589+
'packageGraph': Property(
2590+
getValue: (CT_ c) => c.packageGraph,
2591+
renderVariable: (CT_ c, Property<CT_> self,
2592+
List<String> remainingNames) =>
2593+
self.renderSimpleVariable(
2594+
c, remainingNames, 'PackageGraph'),
2595+
isNullValue: (CT_ c) => c.packageGraph == null,
2596+
renderValue:
2597+
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
2598+
return renderSimple(c.packageGraph, ast, r.template,
2599+
parent: r);
2600+
},
2601+
),
25892602
'referenceChildren': Property(
25902603
getValue: (CT_ c) => c.referenceChildren,
25912604
renderVariable: (CT_ c, Property<CT_> self,
@@ -2611,6 +2624,17 @@ class _Renderer_CommentReferable extends RendererBase<CommentReferable> {
26112624
(e) => renderSimple(e, ast, r.template, parent: r));
26122625
},
26132626
),
2627+
'scope': Property(
2628+
getValue: (CT_ c) => c.scope,
2629+
renderVariable: (CT_ c, Property<CT_> self,
2630+
List<String> remainingNames) =>
2631+
self.renderSimpleVariable(c, remainingNames, 'Scope'),
2632+
isNullValue: (CT_ c) => c.scope == null,
2633+
renderValue:
2634+
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
2635+
return renderSimple(c.scope, ast, r.template, parent: r);
2636+
},
2637+
),
26142638
});
26152639

26162640
_Renderer_CommentReferable(

lib/src/model/comment_referable.dart

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,37 @@ library dartdoc.src.model.comment_reference;
1010
import 'dart:core';
1111

1212
import 'package:analyzer/dart/element/element.dart';
13+
import 'package:analyzer/dart/element/scope.dart';
1314
import 'package:dartdoc/dartdoc.dart';
1415
import 'package:meta/meta.dart';
1516

1617
class ReferenceChildrenLookup {
1718
final String lookup;
1819
final List<String> remaining;
20+
1921
ReferenceChildrenLookup(this.lookup, this.remaining);
22+
23+
@override
24+
String toString() => '$lookup.${remaining.join(".")}';
25+
}
26+
27+
extension on Scope {
28+
/// Prefer the getter for a bundled lookup if both exist.
29+
Element lookupPreferGetter(String id) {
30+
var result = lookup(id);
31+
return result.getter ?? result.setter;
32+
}
2033
}
2134

2235
/// Support comment reference lookups on a Nameable object.
2336
mixin CommentReferable implements Nameable {
37+
PackageGraph packageGraph;
38+
39+
/// For any [CommentReferable] where an analyzer [Scope] exists (or can
40+
/// be constructed), implement this. This will take priority over
41+
/// lookups via [referenceChildren]. Can be cached.
42+
Scope get scope => null;
43+
2444
/// Look up a comment reference by its component parts. If [tryParents] is
2545
/// true, try looking up the same reference in any parents of [this].
2646
/// Will skip over results that do not pass a given [filter] and keep
@@ -37,20 +57,14 @@ mixin CommentReferable implements Nameable {
3757

3858
/// Search for the reference.
3959
for (var referenceLookup in childLookups(reference)) {
60+
if (scope != null) {
61+
result = lookupViaScope(referenceLookup, filter);
62+
if (result != null) break;
63+
}
4064
if (referenceChildren.containsKey(referenceLookup.lookup)) {
41-
result = referenceChildren[referenceLookup.lookup];
42-
if (referenceLookup.remaining.isNotEmpty) {
43-
result = result?.referenceBy(referenceLookup.remaining,
44-
tryParents: false, filter: filter);
45-
} else if (!filter(result)) {
46-
result = result?.referenceBy([referenceLookup.lookup],
47-
tryParents: false, filter: filter);
48-
}
49-
if (!filter(result)) {
50-
result = null;
51-
}
65+
result = _lookupViaReferenceChildren(referenceLookup, filter);
66+
if (result != null) break;
5267
}
53-
if (result != null) break;
5468
}
5569
// If we can't find it in children, try searching parents if allowed.
5670
if (result == null && tryParents) {
@@ -62,6 +76,51 @@ mixin CommentReferable implements Nameable {
6276
return result;
6377
}
6478

79+
/// Looks up references by [scope], skipping over results that do not match
80+
/// the given filter.
81+
///
82+
/// Override if [Scope.lookup] may return a [PrefixElement] or other elements
83+
/// not corresponding to a [CommentReferable], but you still want to have
84+
/// an implementation of [scope].
85+
CommentReferable lookupViaScope(ReferenceChildrenLookup referenceLookup,
86+
bool Function(CommentReferable) filter) {
87+
var resultElement = scope.lookupPreferGetter(referenceLookup.lookup);
88+
if (resultElement is PrefixElement) {
89+
assert(false,
90+
'PrefixElement detected, override [lookupViaScope] in subclass');
91+
return null;
92+
}
93+
return recurseChildrenAndFilter(referenceLookup,
94+
ModelElement.fromElement(resultElement, packageGraph), filter);
95+
}
96+
97+
CommentReferable _lookupViaReferenceChildren(
98+
ReferenceChildrenLookup referenceLookup,
99+
bool Function(CommentReferable) filter) =>
100+
recurseChildrenAndFilter(
101+
referenceLookup, referenceChildren[referenceLookup.lookup], filter);
102+
103+
/// Given a [result] found in an implementation of [lookupViaScope] or
104+
/// [_lookupViaReferenceChildren], recurse through children, skipping over
105+
/// results that do not match the filter.
106+
CommentReferable recurseChildrenAndFilter(
107+
ReferenceChildrenLookup referenceLookup,
108+
CommentReferable result,
109+
bool Function(CommentReferable) filter) {
110+
assert(result != null);
111+
if (referenceLookup.remaining.isNotEmpty) {
112+
result = result.referenceBy(referenceLookup.remaining,
113+
tryParents: false, filter: filter);
114+
} else if (!filter(result)) {
115+
result = result.referenceBy([referenceLookup.lookup],
116+
tryParents: false, filter: filter);
117+
}
118+
if (!filter(result)) {
119+
result = null;
120+
}
121+
return result;
122+
}
123+
65124
/// A list of lookups that should be attempted on children based on
66125
/// [reference]. This allows us to deal with libraries that may have
67126
/// separators in them. [referenceBy] stops at the first one found.
@@ -71,8 +130,10 @@ mixin CommentReferable implements Nameable {
71130
];
72131

73132
/// Map of name to the elements that are a member of [this], but
74-
/// not this model element itself.
75-
/// Can be cached.
133+
/// not this model element itself. Can be cached.
134+
///
135+
/// There is no need to duplicate references here that can be found via
136+
/// [scope].
76137
Map<String, CommentReferable> get referenceChildren;
77138

78139
/// Iterable of immediate "parents" to try resolving component parts.

lib/src/model/package_graph.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ class PackageGraph with CommentReferable, Nameable {
267267

268268
bool get hasFooterVersion => !config.excludeFooterVersion;
269269

270+
@override
270271
PackageGraph get packageGraph => this;
271272

272273
/// Map of package name to Package.

test/comment_referable/comment_referable_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ abstract class Base extends Nameable with CommentReferable {
2525
Element get element => throw UnimplementedError();
2626
}
2727

28-
class Top extends Base with CommentReferable {
28+
class Top extends Base {
2929
@override
3030
final String name;
3131
final List<TopChild> children;

0 commit comments

Comments
 (0)