Move renderer access behind a renderer factory (#2086)
Renderers are now accessed from a RendererFactory held by the package
graph. This allows for changing renderers based on the configuration
of DartDoc without models having to know anything about that.
diff --git a/lib/src/element_type.dart b/lib/src/element_type.dart
index e9f7139..fc0d5ef 100644
--- a/lib/src/element_type.dart
+++ b/lib/src/element_type.dart
@@ -132,8 +132,7 @@
@override
String get linkedName {
if (_linkedName == null) {
- _linkedName =
- FunctionTypeElementTypeRendererHtml().renderLinkedName(this);
+ _linkedName = _renderer.renderLinkedName(this);
}
return _linkedName;
}
@@ -146,8 +145,7 @@
@override
String get nameWithGenerics {
if (_nameWithGenerics == null) {
- _nameWithGenerics =
- FunctionTypeElementTypeRendererHtml().renderNameWithGenerics(this);
+ _nameWithGenerics = _renderer.renderNameWithGenerics(this);
}
return _nameWithGenerics;
}
@@ -162,6 +160,9 @@
@override
String get name => 'Function';
+
+ ElementTypeRenderer<FunctionTypeElementType> get _renderer =>
+ packageGraph.rendererFactory.functionTypeElementTypeRenderer;
}
class ParameterizedElementType extends DefinedElementType {
@@ -173,8 +174,7 @@
@override
String get linkedName {
if (_linkedName == null) {
- _linkedName =
- ParameterizedElementTypeRendererHtml().renderLinkedName(this);
+ _linkedName = _renderer.renderLinkedName(this);
}
return _linkedName;
}
@@ -183,11 +183,13 @@
@override
String get nameWithGenerics {
if (_nameWithGenerics == null) {
- _nameWithGenerics =
- ParameterizedElementTypeRendererHtml().renderNameWithGenerics(this);
+ _nameWithGenerics = _renderer.renderNameWithGenerics(this);
}
return _nameWithGenerics;
}
+
+ ElementTypeRenderer<ParameterizedElementType> get _renderer =>
+ packageGraph.rendererFactory.parameterizedElementTypeRenderer;
}
class TypeParameterElementType extends DefinedElementType {
@@ -362,12 +364,16 @@
@override
String get linkedName {
if (_linkedName == null) {
- _linkedName = CallableElementTypeRendererHtml().renderLinkedName(this);
+ _linkedName = _renderer.renderLinkedName(this);
}
return _linkedName;
}
String get superLinkedName => super.linkedName;
+
+ @override
+ ElementTypeRenderer<CallableElementType> get _renderer =>
+ packageGraph.rendererFactory.callableElementTypeRenderer;
}
/// Types backed by a [GenericTypeAliasElement] that may or may not be callable.
diff --git a/lib/src/model/category.dart b/lib/src/model/category.dart
index 8464d50..6c61162 100644
--- a/lib/src/model/category.dart
+++ b/lib/src/model/category.dart
@@ -124,13 +124,9 @@
String get href =>
isCanonical ? '${package.baseHref}topics/${name}-topic.html' : null;
- String get categorization {
- return CategoryRendererHtml().renderCategoryLabel(this);
- }
+ String get categorization => _renderer.renderCategoryLabel(this);
- String get linkedName {
- return CategoryRendererHtml().renderLinkedName(this);
- }
+ String get linkedName => _renderer.renderLinkedName(this);
int _categoryIndex;
@@ -201,4 +197,7 @@
@override
Iterable<Typedef> get typedefs => _typedefs;
+
+ CategoryRenderer get _renderer =>
+ packageGraph.rendererFactory.categoryRenderer;
}
diff --git a/lib/src/model/documentation.dart b/lib/src/model/documentation.dart
index b22fa09..8344fdd 100644
--- a/lib/src/model/documentation.dart
+++ b/lib/src/model/documentation.dart
@@ -53,7 +53,7 @@
_hasExtendedDocs = parseResult.item2;
Tuple2<String, String> renderResult =
- DocumentationRendererHtml().render(parseResult.item1, processAllDocs);
+ _renderer.render(parseResult.item1, processAllDocs);
if (processAllDocs) {
_asHtml = renderResult.item1;
@@ -71,4 +71,7 @@
MarkdownDocument.withElementLinkResolver(_element, commentRefs);
return document.parseMarkdownText(text, processFullDocs);
}
+
+ DocumentationRenderer get _renderer =>
+ _element.packageGraph.rendererFactory.documentationRenderer;
}
diff --git a/lib/src/model/enum.dart b/lib/src/model/enum.dart
index a534a36..017aca1 100644
--- a/lib/src/model/enum.dart
+++ b/lib/src/model/enum.dart
@@ -44,7 +44,7 @@
: super(element, library, packageGraph, getter, null);
@override
- String get constantValueBase => EnumFieldRendererHtml().renderValue(this);
+ String get constantValueBase => _fieldRenderer.renderValue(this);
@override
List<ModelElement> get documentationFrom {
@@ -104,4 +104,7 @@
@override
Inheritable get overriddenElement => null;
+
+ EnumFieldRenderer get _fieldRenderer =>
+ packageGraph.rendererFactory.enumFieldRenderer;
}
diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart
index 8bc6918..8d33b86 100644
--- a/lib/src/model/model_element.dart
+++ b/lib/src/model/model_element.dart
@@ -25,8 +25,8 @@
import 'package:dartdoc/src/logging.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/model_utils.dart' as utils;
-import 'package:dartdoc/src/render/parameter_renderer.dart';
import 'package:dartdoc/src/render/model_element_renderer.dart';
+import 'package:dartdoc/src/render/parameter_renderer.dart';
import 'package:dartdoc/src/source_linker.dart';
import 'package:dartdoc/src/tuple.dart';
import 'package:dartdoc/src/utils.dart';
@@ -784,7 +784,7 @@
/// does not exist.
String get extendedDocLink {
if (hasExtendedDocumentation) {
- return ModelElementRendererHtml().renderExtendedDocLink(this);
+ return _modelElementRenderer.renderExtendedDocLink(this);
}
return '';
}
@@ -916,18 +916,25 @@
return _linkedName;
}
- String get linkedParams =>
- ParameterRendererHtml().renderLinkedParams(parameters);
+ ModelElementRenderer get _modelElementRenderer =>
+ packageGraph.rendererFactory.modelElementRenderer;
+
+ ParameterRenderer get _parameterRenderer =>
+ packageGraph.rendererFactory.parameterRenderer;
+
+ ParameterRenderer get _parameterRendererDetailed =>
+ packageGraph.rendererFactory.parameterRendererDetailed;
+
+ String get linkedParams => _parameterRenderer.renderLinkedParams(parameters);
String get linkedParamsLines =>
- ParameterRendererHtmlList().renderLinkedParams(parameters).trim();
+ _parameterRendererDetailed.renderLinkedParams(parameters).trim();
String get linkedParamsNoMetadata =>
- ParameterRendererHtml(showMetadata: false).renderLinkedParams(parameters);
+ _parameterRenderer.renderLinkedParams(parameters, showMetadata: false);
- String get linkedParamsNoMetadataOrNames =>
- ParameterRendererHtml(showMetadata: false, showNames: false)
- .renderLinkedParams(parameters);
+ String get linkedParamsNoMetadataOrNames => _parameterRenderer
+ .renderLinkedParams(parameters, showMetadata: false, showNames: false);
ElementType get modelType {
if (_modelType == null) {
@@ -1120,7 +1127,7 @@
return htmlEscape.convert(name);
}
- return ModelElementRendererHtml().renderLinkedName(this);
+ return _modelElementRenderer.renderLinkedName(this);
}
/// Replace {@example ...} in API comments with the content of named file.
@@ -1351,8 +1358,7 @@
final String youTubeId = url.group(url.groupCount);
final String aspectRatio = (height / width * 100).toStringAsFixed(2);
- return ModelElementRendererHtml()
- .renderYoutubeUrl(youTubeId, aspectRatio);
+ return _modelElementRenderer.renderYoutubeUrl(youTubeId, aspectRatio);
});
}
@@ -1483,8 +1489,8 @@
'parameter)');
}
- return ModelElementRendererHtml()
- .renderAnimation(uniqueId, width, height, movieUrl, overlayId);
+ return _modelElementRenderer.renderAnimation(
+ uniqueId, width, height, movieUrl, overlayId);
});
}
diff --git a/lib/src/model/package_builder.dart b/lib/src/model/package_builder.dart
index 8d82ca1..ea728b6 100644
--- a/lib/src/model/package_builder.dart
+++ b/lib/src/model/package_builder.dart
@@ -27,6 +27,7 @@
import 'package:dartdoc/src/logging.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/package_meta.dart' show PackageMeta;
+import 'package:dartdoc/src/render/renderer_factory.dart';
import 'package:dartdoc/src/special_elements.dart';
import 'package:package_config/discovery.dart' as package_config;
import 'package:path/path.dart' as path;
@@ -42,13 +43,16 @@
if (config.topLevelPackageMeta.needsPubGet) {
config.topLevelPackageMeta.runPubGet();
}
+ // TODO(jdkoren): change factory for other formats based on config options
+ RendererFactory rendererFactory = HtmlRenderFactory();
PackageGraph newGraph = PackageGraph.UninitializedPackageGraph(
config,
driver,
await driver.currentSession.typeSystem,
sdk,
- hasEmbedderSdkFiles);
+ hasEmbedderSdkFiles,
+ rendererFactory);
await getLibraries(newGraph);
await newGraph.initializePackageGraph();
return newGraph;
diff --git a/lib/src/model/package_graph.dart b/lib/src/model/package_graph.dart
index 864ea31..30d6808 100644
--- a/lib/src/model/package_graph.dart
+++ b/lib/src/model/package_graph.dart
@@ -19,13 +19,14 @@
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/model_utils.dart' as utils;
import 'package:dartdoc/src/package_meta.dart' show PackageMeta;
+import 'package:dartdoc/src/render/renderer_factory.dart';
import 'package:dartdoc/src/special_elements.dart';
import 'package:dartdoc/src/tuple.dart';
import 'package:dartdoc/src/warnings.dart';
class PackageGraph {
- PackageGraph.UninitializedPackageGraph(
- this.config, this.driver, this.typeSystem, this.sdk, this.hasEmbedderSdk)
+ PackageGraph.UninitializedPackageGraph(this.config, this.driver,
+ this.typeSystem, this.sdk, this.hasEmbedderSdk, this.rendererFactory)
: packageMeta = config.topLevelPackageMeta,
session = driver.currentSession {
_packageWarningCounter = PackageWarningCounter(this);
@@ -207,6 +208,9 @@
/// Dartdoc's configuration flags.
final DartdocOptionContext config;
+ /// Factory for renderers
+ final RendererFactory rendererFactory;
+
Package _defaultPackage;
Package get defaultPackage {
diff --git a/lib/src/model/type_parameter.dart b/lib/src/model/type_parameter.dart
index 158095d..550c20b 100644
--- a/lib/src/model/type_parameter.dart
+++ b/lib/src/model/type_parameter.dart
@@ -76,16 +76,17 @@
bool get hasGenericParameters => typeParameters.isNotEmpty;
- String get genericParameters {
- return TypeParametersRendererHtml().renderGenericParameters(this);
- }
+ String get genericParameters =>
+ _typeParametersRenderer.renderGenericParameters(this);
- String get linkedGenericParameters {
- return TypeParametersRendererHtml().renderLinkedGenericParameters(this);
- }
+ String get linkedGenericParameters =>
+ _typeParametersRenderer.renderLinkedGenericParameters(this);
@override
DefinedElementType get modelType;
List<TypeParameter> get typeParameters;
+
+ TypeParametersRenderer get _typeParametersRenderer =>
+ packageGraph.rendererFactory.typeParametersRenderer;
}
diff --git a/lib/src/model/typedef.dart b/lib/src/model/typedef.dart
index 3a13447..b7e7424 100644
--- a/lib/src/model/typedef.dart
+++ b/lib/src/model/typedef.dart
@@ -21,8 +21,7 @@
String get nameWithGenerics => '$name${super.genericParameters}';
@override
- String get genericParameters =>
- TypedefRendererHtml().renderGenericParameters(this);
+ String get genericParameters => _renderer.renderGenericParameters(this);
List<TypeParameterElement> get genericTypeParameters {
if (element is GenericTypeAliasElement) {
@@ -59,4 +58,6 @@
List<TypeParameter> get typeParameters => _typedef.typeParameters.map((f) {
return ModelElement.from(f, library, packageGraph) as TypeParameter;
}).toList();
+
+ TypedefRenderer get _renderer => packageGraph.rendererFactory.typedefRenderer;
}
diff --git a/lib/src/render/element_type_renderer.dart b/lib/src/render/element_type_renderer.dart
index eb62710..cc4be7a 100644
--- a/lib/src/render/element_type_renderer.dart
+++ b/lib/src/render/element_type_renderer.dart
@@ -85,8 +85,8 @@
StringBuffer buf = StringBuffer();
buf.write(elementType.nameWithGenerics);
buf.write('(');
- buf.write(ParameterRendererHtml(showNames: false)
- .renderLinkedParams(elementType.element.parameters)
+ buf.write(ParameterRendererHtml()
+ .renderLinkedParams(elementType.element.parameters, showNames: false)
.trim());
buf.write(') → ');
buf.write(elementType.returnType.linkedName);
diff --git a/lib/src/render/parameter_renderer.dart b/lib/src/render/parameter_renderer.dart
index 4cf6bcd..3e7a895 100644
--- a/lib/src/render/parameter_renderer.dart
+++ b/lib/src/render/parameter_renderer.dart
@@ -8,8 +8,6 @@
/// Render HTML in an extended vertical format using <ol> tag.
class ParameterRendererHtmlList extends ParameterRendererHtml {
- ParameterRendererHtmlList({bool showMetadata = true, bool showNames = true})
- : super(showMetadata: showMetadata, showNames: showNames);
@override
String listItem(String listItem) => '<li>$listItem</li>\n';
@override
@@ -21,12 +19,6 @@
/// Render HTML suitable for a single, wrapped line.
class ParameterRendererHtml extends ParameterRenderer {
@override
- final bool showMetadata;
- @override
- final bool showNames;
- ParameterRendererHtml({this.showMetadata = true, this.showNames = true});
-
- @override
String listItem(String listItem) => '${listItem}<wbr>';
@override
String orderedList(String listItems) => listItems;
@@ -51,9 +43,6 @@
}
abstract class ParameterRenderer {
- bool get showMetadata;
- bool get showNames;
-
String listItem(String item);
String orderedList(String listItems);
String annotation(String annotation);
@@ -64,28 +53,8 @@
String typeName(String typeName);
String required(String required);
- String _linkedParameterSublist(List<Parameter> parameters, bool trailingComma,
- {String thisOpenBracket = '', String thisCloseBracket = ''}) {
- StringBuffer builder = StringBuffer();
- parameters.forEach((p) {
- String prefix = '';
- String suffix = '';
- if (identical(p, parameters.first)) {
- prefix = thisOpenBracket;
- }
- if (identical(p, parameters.last)) {
- suffix += thisCloseBracket;
- if (trailingComma) suffix += ', ';
- } else {
- suffix += ', ';
- }
- builder.write(
- listItem(parameter(prefix + renderParam(p) + suffix, p.htmlId)));
- });
- return builder.toString();
- }
-
- String renderLinkedParams(List<Parameter> parameters) {
+ String renderLinkedParams(List<Parameter> parameters,
+ {showMetadata = true, showNames = true}) {
List<Parameter> positionalParams =
parameters.where((Parameter p) => p.isRequiredPositional).toList();
List<Parameter> optionalPositionalParams =
@@ -96,21 +65,55 @@
String positional = '', optional = '', named = '';
if (positionalParams.isNotEmpty) {
positional = _linkedParameterSublist(positionalParams,
- optionalPositionalParams.isNotEmpty || namedParams.isNotEmpty);
+ optionalPositionalParams.isNotEmpty || namedParams.isNotEmpty,
+ showMetadata: showMetadata, showNames: showNames);
}
if (optionalPositionalParams.isNotEmpty) {
optional = _linkedParameterSublist(
optionalPositionalParams, namedParams.isNotEmpty,
- thisOpenBracket: '[', thisCloseBracket: ']');
+ openBracket: '[',
+ closeBracket: ']',
+ showMetadata: showMetadata,
+ showNames: showNames);
}
if (namedParams.isNotEmpty) {
named = _linkedParameterSublist(namedParams, false,
- thisOpenBracket: '{', thisCloseBracket: '}');
+ openBracket: '{',
+ closeBracket: '}',
+ showMetadata: showMetadata,
+ showNames: showNames);
}
return (orderedList(positional + optional + named));
}
- String renderParam(Parameter param) {
+ String _linkedParameterSublist(List<Parameter> parameters, bool trailingComma,
+ {String openBracket = '',
+ String closeBracket = '',
+ showMetadata = true,
+ showNames = true}) {
+ StringBuffer builder = StringBuffer();
+ parameters.forEach((p) {
+ String prefix = '';
+ String suffix = '';
+ if (identical(p, parameters.first)) {
+ prefix = openBracket;
+ }
+ if (identical(p, parameters.last)) {
+ suffix += closeBracket;
+ if (trailingComma) suffix += ', ';
+ } else {
+ suffix += ', ';
+ }
+ String renderedParam =
+ _renderParam(p, showMetadata: showMetadata, showNames: showNames);
+ builder.write(
+ listItem(parameter(prefix + renderedParam + suffix, p.htmlId)));
+ });
+ return builder.toString();
+ }
+
+ String _renderParam(Parameter param,
+ {showMetadata = true, showNames = true}) {
StringBuffer buf = StringBuffer();
ElementType paramModelType = param.modelType;
@@ -140,13 +143,16 @@
}
if (!paramModelType.isTypedef && paramModelType is DefinedElementType) {
buf.write('(');
- buf.write(renderLinkedParams(paramModelType.element.parameters));
+ buf.write(renderLinkedParams(paramModelType.element.parameters,
+ showMetadata: showMetadata, showNames: showNames));
buf.write(')');
}
if (!paramModelType.isTypedef && paramModelType.type is FunctionType) {
buf.write('(');
buf.write(renderLinkedParams(
- (paramModelType as UndefinedElementType).parameters));
+ (paramModelType as UndefinedElementType).parameters,
+ showMetadata: showMetadata,
+ showNames: showNames));
buf.write(')');
}
} else if (param.modelType != null) {
diff --git a/lib/src/render/renderer_factory.dart b/lib/src/render/renderer_factory.dart
new file mode 100644
index 0000000..7144c3f
--- /dev/null
+++ b/lib/src/render/renderer_factory.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:dartdoc/dartdoc.dart';
+import 'package:dartdoc/src/render/category_renderer.dart';
+import 'package:dartdoc/src/render/documentation_renderer.dart';
+import 'package:dartdoc/src/render/element_type_renderer.dart';
+import 'package:dartdoc/src/render/enum_field_renderer.dart';
+import 'package:dartdoc/src/render/model_element_renderer.dart';
+import 'package:dartdoc/src/render/parameter_renderer.dart';
+import 'package:dartdoc/src/render/type_parameters_renderer.dart';
+import 'package:dartdoc/src/render/typedef_renderer.dart';
+
+abstract class RendererFactory {
+ CategoryRenderer get categoryRenderer;
+
+ DocumentationRenderer get documentationRenderer;
+
+ ElementTypeRenderer<FunctionTypeElementType>
+ get functionTypeElementTypeRenderer;
+
+ ElementTypeRenderer<ParameterizedElementType>
+ get parameterizedElementTypeRenderer;
+
+ ElementTypeRenderer<CallableElementType> get callableElementTypeRenderer;
+
+ EnumFieldRenderer get enumFieldRenderer;
+
+ ModelElementRenderer get modelElementRenderer;
+
+ ParameterRenderer get parameterRenderer;
+
+ ParameterRenderer get parameterRendererDetailed;
+
+ TypeParametersRenderer get typeParametersRenderer;
+
+ TypedefRenderer get typedefRenderer;
+}
+
+class HtmlRenderFactory extends RendererFactory {
+ @override
+ CategoryRenderer get categoryRenderer => CategoryRendererHtml();
+
+ @override
+ DocumentationRenderer get documentationRenderer =>
+ DocumentationRendererHtml();
+
+ @override
+ ElementTypeRenderer<CallableElementType> get callableElementTypeRenderer =>
+ CallableElementTypeRendererHtml();
+
+ @override
+ ElementTypeRenderer<FunctionTypeElementType>
+ get functionTypeElementTypeRenderer =>
+ FunctionTypeElementTypeRendererHtml();
+
+ @override
+ ElementTypeRenderer<ParameterizedElementType>
+ get parameterizedElementTypeRenderer =>
+ ParameterizedElementTypeRendererHtml();
+
+ @override
+ EnumFieldRenderer get enumFieldRenderer => EnumFieldRendererHtml();
+
+ @override
+ ModelElementRenderer get modelElementRenderer => ModelElementRendererHtml();
+
+ @override
+ ParameterRenderer get parameterRenderer => ParameterRendererHtml();
+
+ @override
+ ParameterRenderer get parameterRendererDetailed =>
+ ParameterRendererHtmlList();
+
+ @override
+ TypeParametersRenderer get typeParametersRenderer =>
+ TypeParametersRendererHtml();
+
+ @override
+ TypedefRenderer get typedefRenderer => TypedefRendererHtml();
+}
diff --git a/test/model_test.dart b/test/model_test.dart
index 5f52a10..edae9ae 100644
--- a/test/model_test.dart
+++ b/test/model_test.dart
@@ -3270,8 +3270,8 @@
test('a function requiring a Future<void> parameter', () {
expect(
- ParameterRendererHtml(showMetadata: true, showNames: true)
- .renderLinkedParams(aVoidParameter.parameters),
+ ParameterRendererHtml().renderLinkedParams(aVoidParameter.parameters,
+ showMetadata: true, showNames: true),
equals(
'<span class="parameter" id="aVoidParameter-param-p1"><span class="type-annotation">Future<span class="signature"><<wbr><span class="type-parameter">void</span>></span></span> <span class="parameter-name">p1</span></span><wbr>'));
});