Skip to content

Commit eb2d5e2

Browse files
authored
Add support for extension methods (dart-lang#2012)
* Add suport for extensions * Add options file to test package * remove path dependencies * Address review comments
1 parent f8c0b83 commit eb2d5e2

26 files changed

+961
-160
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.28.6-dev
2+
* Support for 0.38.2 version of `package:analyzer`.
3+
* Support generating docs for extension methods (#2001).
4+
15
## 0.28.5
26
* Support the latest version of `package:analyzer`.
37
* Fix hyperlinks to overriden methods (#1994).

analysis_options.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
include: package:pedantic/analysis_options.1.8.0.yaml
22

33
analyzer:
4+
# enable for analysis on test package sources.
5+
enable-experiment:
6+
- extension-methods
47
exclude:
58
- 'doc/**'
69
- 'lib/src/third_party/pkg/**'

dartdoc_options.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
dartdoc:
22
linkToSource:
33
root: '.'
4-
uriTemplate: 'https://github.com/dart-lang/dartdoc/blob/v0.28.5/%f%#L%l%'
4+
uriTemplate: 'https://github.com/dart-lang/dartdoc/blob/v0.28.6-dev/%f%#L%l%'

lib/src/element_type.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ abstract class DefinedElementType extends ElementType {
191191
/// would ordinarily do.
192192
@override
193193
bool get isPublic {
194-
Class canonicalClass =
194+
Container canonicalClass =
195195
element.packageGraph.findCanonicalModelElementFor(element.element) ??
196196
element;
197197
return canonicalClass.isPublic;

lib/src/html/html_generator_instance.dart

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,37 @@ class HtmlGeneratorInstance {
171171
}
172172
}
173173

174+
for (var extension in filterNonPublic(lib.extensions)) {
175+
generateExtension(_packageGraph, lib, extension);
176+
177+
for (var constant in filterNonDocumented(extension.constants)) {
178+
generateConstant(_packageGraph, lib, extension, constant);
179+
}
180+
181+
for (var property
182+
in filterNonDocumented(extension.staticProperties)) {
183+
generateProperty(_packageGraph, lib, extension, property);
184+
}
185+
186+
for (var method
187+
in filterNonDocumented(extension.allPublicInstanceMethods)) {
188+
generateMethod(_packageGraph, lib, extension, method);
189+
}
190+
191+
for (var method in filterNonDocumented(extension.staticMethods)) {
192+
generateMethod(_packageGraph, lib, extension, method);
193+
}
194+
195+
for (var operator in filterNonDocumented(extension.allOperators)) {
196+
generateMethod(_packageGraph, lib, extension, operator);
197+
}
198+
199+
for (var property
200+
in filterNonDocumented(extension.allInstanceFields)) {
201+
generateProperty(_packageGraph, lib, extension, property);
202+
}
203+
}
204+
174205
for (var mixin in filterNonDocumented(lib.mixins)) {
175206
generateMixins(_packageGraph, lib, mixin);
176207
for (var constructor in filterNonDocumented(mixin.constructors)) {
@@ -275,6 +306,13 @@ class HtmlGeneratorInstance {
275306
_build(path.joinAll(clazz.href.split('/')), _templates.classTemplate, data);
276307
}
277308

309+
void generateExtension(
310+
PackageGraph packageGraph, Library lib, Extension ext) {
311+
TemplateData data = ExtensionTemplateData(_options, packageGraph, lib, ext);
312+
_build(
313+
path.joinAll(ext.href.split('/')), _templates.extensionTemplate, data);
314+
}
315+
278316
void generateMixins(PackageGraph packageGraph, Library lib, Mixin mixin) {
279317
TemplateData data = MixinTemplateData(_options, packageGraph, lib, mixin);
280318
_build(path.joinAll(mixin.href.split('/')), _templates.mixinTemplate, data);
@@ -305,7 +343,7 @@ class HtmlGeneratorInstance {
305343
}
306344

307345
void generateMethod(
308-
PackageGraph packageGraph, Library lib, Class clazz, Method method) {
346+
PackageGraph packageGraph, Library lib, Container clazz, Method method) {
309347
TemplateData data =
310348
MethodTemplateData(_options, packageGraph, lib, clazz, method);
311349

@@ -314,7 +352,7 @@ class HtmlGeneratorInstance {
314352
}
315353

316354
void generateConstant(
317-
PackageGraph packageGraph, Library lib, Class clazz, Field property) {
355+
PackageGraph packageGraph, Library lib, Container clazz, Field property) {
318356
TemplateData data =
319357
ConstantTemplateData(_options, packageGraph, lib, clazz, property);
320358

@@ -323,7 +361,7 @@ class HtmlGeneratorInstance {
323361
}
324362

325363
void generateProperty(
326-
PackageGraph packageGraph, Library lib, Class clazz, Field property) {
364+
PackageGraph packageGraph, Library lib, Container clazz, Field property) {
327365
TemplateData data =
328366
PropertyTemplateData(_options, packageGraph, lib, clazz, property);
329367

lib/src/html/template_data.dart

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,34 @@ class ClassTemplateData<T extends Class> extends TemplateData<T> {
185185
}
186186
}
187187

188+
/// Base template data class for [Extension].
189+
class ExtensionTemplateData<T extends Extension> extends TemplateData<T> {
190+
final T extension;
191+
final Library library;
192+
193+
ExtensionTemplateData(HtmlOptions htmlOptions, PackageGraph packageGraph,
194+
this.library, this.extension)
195+
: super(htmlOptions, packageGraph);
196+
197+
@override
198+
T get self => extension;
199+
200+
@override
201+
String get title =>
202+
'${extension.name} ${extension.kind} - ${library.name} library - Dart API';
203+
@override
204+
String get metaDescription =>
205+
'API docs for the ${extension.name} ${extension.kind} from the '
206+
'${library.name} library, for the Dart programming language.';
207+
208+
@override
209+
String get layoutTitle => _layoutTitle(extension.name, extension.kind, false);
210+
@override
211+
List get navLinks => [packageGraph.defaultPackage, library];
212+
@override
213+
String get htmlBase => '..';
214+
}
215+
188216
class ConstructorTemplateData extends TemplateData<Constructor> {
189217
final Library library;
190218
final Class clazz;
@@ -255,23 +283,26 @@ class FunctionTemplateData extends TemplateData<ModelFunction> {
255283
class MethodTemplateData extends TemplateData<Method> {
256284
final Library library;
257285
final Method method;
258-
final Class clazz;
286+
final Container clazz;
287+
String container;
259288

260289
MethodTemplateData(HtmlOptions htmlOptions, PackageGraph packageGraph,
261290
this.library, this.clazz, this.method)
262-
: super(htmlOptions, packageGraph);
291+
: super(htmlOptions, packageGraph) {
292+
container = clazz.isClass ? 'class' : 'extension';
293+
}
263294

264295
@override
265296
Method get self => method;
266297
@override
267-
String get title => '${method.name} method - ${clazz.name} class - '
298+
String get title => '${method.name} method - ${clazz.name} ${container} - '
268299
'${library.name} library - Dart API';
269300
@override
270301
String get layoutTitle => _layoutTitle(
271302
method.nameWithGenerics, method.fullkind, method.isDeprecated);
272303
@override
273304
String get metaDescription =>
274-
'API docs for the ${method.name} method from the ${clazz.name} class, '
305+
'API docs for the ${method.name} method from the ${clazz.name} ${container}, '
275306
'for the Dart programming language.';
276307
@override
277308
List get navLinks => [packageGraph.defaultPackage, library];
@@ -283,25 +314,28 @@ class MethodTemplateData extends TemplateData<Method> {
283314

284315
class PropertyTemplateData extends TemplateData<Field> {
285316
final Library library;
286-
final Class clazz;
317+
final Container clazz;
287318
final Field property;
319+
String container;
288320

289321
PropertyTemplateData(HtmlOptions htmlOptions, PackageGraph packageGraph,
290322
this.library, this.clazz, this.property)
291-
: super(htmlOptions, packageGraph);
323+
: super(htmlOptions, packageGraph) {
324+
container = clazz.isClass ? 'class' : 'extension';
325+
}
292326

293327
@override
294328
Field get self => property;
295329

296330
@override
297-
String get title => '${property.name} $type - ${clazz.name} class - '
331+
String get title => '${property.name} $type - ${clazz.name} ${container} - '
298332
'${library.name} library - Dart API';
299333
@override
300334
String get layoutTitle =>
301335
_layoutTitle(property.name, type, property.isDeprecated);
302336
@override
303337
String get metaDescription =>
304-
'API docs for the ${property.name} $type from the ${clazz.name} class, '
338+
'API docs for the ${property.name} $type from the ${clazz.name} ${container}, '
305339
'for the Dart programming language.';
306340
@override
307341
List get navLinks => [packageGraph.defaultPackage, library];
@@ -315,7 +349,7 @@ class PropertyTemplateData extends TemplateData<Field> {
315349

316350
class ConstantTemplateData extends PropertyTemplateData {
317351
ConstantTemplateData(HtmlOptions htmlOptions, PackageGraph packageGraph,
318-
Library library, Class clazz, Field property)
352+
Library library, Container clazz, Field property)
319353
: super(htmlOptions, packageGraph, library, clazz, property);
320354

321355
@override

lib/src/html/templates.dart

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const _partials = <String>[
1818
'categorization',
1919
'class',
2020
'constant',
21+
'extension',
2122
'footer',
2223
'head',
2324
'library',
@@ -31,6 +32,7 @@ const _partials = <String>[
3132
'sidebar_for_class',
3233
'sidebar_for_category',
3334
'sidebar_for_enum',
35+
'sidebar_for_extension',
3436
'source_code',
3537
'source_link',
3638
'sidebar_for_library',
@@ -45,6 +47,7 @@ const _requiredTemplates = <String>[
4547
'constant.html',
4648
'constructor.html',
4749
'enum.html',
50+
'extension.html',
4851
'function.html',
4952
'index.html',
5053
'library.html',
@@ -65,7 +68,6 @@ Future<Map<String, String>> _loadPartials(
6568
List<String> headerPaths,
6669
List<String> footerPaths,
6770
List<String> footerTextPaths) async {
68-
6971
headerPaths ??= [];
7072
footerPaths ??= [];
7173
footerTextPaths ??= [];
@@ -75,8 +77,8 @@ Future<Map<String, String>> _loadPartials(
7577
void replacePlaceholder(String key, String placeholder, List<String> paths) {
7678
var template = partials[key];
7779
if (template != null && paths != null && paths.isNotEmpty) {
78-
String replacement = paths.map((p) => File(p).readAsStringSync())
79-
.join('\n');
80+
String replacement =
81+
paths.map((p) => File(p).readAsStringSync()).join('\n');
8082
template = template.replaceAll(placeholder, replacement);
8183
partials[key] = template;
8284
}
@@ -140,6 +142,7 @@ class _DirectoryTemplatesLoader extends _TemplatesLoader {
140142
class Templates {
141143
final Template categoryTemplate;
142144
final Template classTemplate;
145+
final Template extensionTemplate;
143146
final Template enumTemplate;
144147
final Template constantTemplate;
145148
final Template constructorTemplate;
@@ -164,8 +167,7 @@ class Templates {
164167
footerTextPaths: footerTextPaths);
165168
}
166169

167-
static Future<Templates> fromDirectory(
168-
Directory dir,
170+
static Future<Templates> fromDirectory(Directory dir,
169171
{List<String> headerPaths,
170172
List<String> footerPaths,
171173
List<String> footerTextPaths}) async {
@@ -185,13 +187,12 @@ class Templates {
185187
}
186188
}
187189

188-
static Future<Templates> _create(
189-
_TemplatesLoader templatesLoader,
190+
static Future<Templates> _create(_TemplatesLoader templatesLoader,
190191
{List<String> headerPaths,
191192
List<String> footerPaths,
192193
List<String> footerTextPaths}) async {
193-
var partials =
194-
await _loadPartials(templatesLoader, headerPaths, footerPaths, footerTextPaths);
194+
var partials = await _loadPartials(
195+
templatesLoader, headerPaths, footerPaths, footerTextPaths);
195196

196197
Template _partial(String name) {
197198
String partial = partials[name];
@@ -202,14 +203,16 @@ class Templates {
202203
}
203204

204205
Future<Template> _loadTemplate(String templatePath) async {
205-
String templateContents = await templatesLoader.loadTemplate(templatePath);
206+
String templateContents =
207+
await templatesLoader.loadTemplate(templatePath);
206208
return Template(templateContents, partialResolver: _partial);
207209
}
208210

209211
var indexTemplate = await _loadTemplate('index.html');
210212
var libraryTemplate = await _loadTemplate('library.html');
211213
var categoryTemplate = await _loadTemplate('category.html');
212214
var classTemplate = await _loadTemplate('class.html');
215+
var extensionTemplate = await _loadTemplate('extension.html');
213216
var enumTemplate = await _loadTemplate('enum.html');
214217
var functionTemplate = await _loadTemplate('function.html');
215218
var methodTemplate = await _loadTemplate('method.html');
@@ -229,6 +232,7 @@ class Templates {
229232
categoryTemplate,
230233
libraryTemplate,
231234
classTemplate,
235+
extensionTemplate,
232236
enumTemplate,
233237
functionTemplate,
234238
methodTemplate,
@@ -247,6 +251,7 @@ class Templates {
247251
this.categoryTemplate,
248252
this.libraryTemplate,
249253
this.classTemplate,
254+
this.extensionTemplate,
250255
this.enumTemplate,
251256
this.functionTemplate,
252257
this.methodTemplate,

lib/src/markdown_processor.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ class IterableBlockParser extends md.BlockParser {
183183
// Calculate a class hint for findCanonicalModelElementFor.
184184
ModelElement _getPreferredClass(ModelElement modelElement) {
185185
if (modelElement is EnclosedElement &&
186-
(modelElement as EnclosedElement).enclosingElement is Class) {
186+
(modelElement as EnclosedElement).enclosingElement is Container) {
187187
return (modelElement as EnclosedElement).enclosingElement;
188188
} else if (modelElement is Class) {
189189
return modelElement;
@@ -204,7 +204,7 @@ MatchingLinkResult _getMatchingLinkElement(
204204

205205
// Try expensive not-scoped lookup.
206206
if (refModelElement == null && element is ModelElement) {
207-
Class preferredClass = _getPreferredClass(element);
207+
Container preferredClass = _getPreferredClass(element);
208208
refModelElement =
209209
_MarkdownCommentReference(codeRef, element, commentRefs, preferredClass)
210210
.computeReferredElement();
@@ -692,7 +692,7 @@ class _MarkdownCommentReference {
692692
}
693693

694694
// Add a result, but make it canonical.
695-
void _addCanonicalResult(ModelElement modelElement, Class tryClass) {
695+
void _addCanonicalResult(ModelElement modelElement, Container tryClass) {
696696
results.add(packageGraph.findCanonicalModelElementFor(modelElement.element,
697697
preferredClass: tryClass));
698698
}

0 commit comments

Comments
 (0)