diff --git a/lib/src/element_type.dart b/lib/src/element_type.dart
index 5f026fa287..a3a8b853df 100644
--- a/lib/src/element_type.dart
+++ b/lib/src/element_type.dart
@@ -11,7 +11,7 @@ import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:dartdoc/src/model/model.dart';
-import 'package:dartdoc/src/model_utils.dart';
+import 'package:dartdoc/src/render/parameter_renderer.dart';
/// Base class representing a type in Dartdoc. It wraps a [DartType], and
/// may link to a [ModelElement].
@@ -147,7 +147,7 @@ class FunctionTypeElementType extends UndefinedElementType {
buf.write('${returnType.linkedName} ');
buf.write('${nameWithGenerics}');
buf.write('');
- buf.write('(${linkedParams(parameters)})');
+ buf.write('(${ParameterRendererHtml().renderLinkedParams(parameters)})');
buf.write('');
_linkedName = buf.toString();
}
@@ -418,7 +418,7 @@ class CallableElementType extends ParameterizedElementType
@override
String get linkedName {
if (name != null && name.isNotEmpty) return super.linkedName;
- return '${nameWithGenerics}(${linkedParams(element.parameters, showNames: false).trim()}) → ${returnType.linkedName}';
+ return '${nameWithGenerics}(${ParameterRendererHtml(showNames: false).renderLinkedParams(element.parameters).trim()}) → ${returnType.linkedName}';
}
}
@@ -435,7 +435,7 @@ class CallableAnonymousElementType extends CallableElementType {
String get linkedName {
if (_linkedName == null) {
_linkedName =
- '${returnType.linkedName} ${super.linkedName}(${linkedParams(element.parameters)})';
+ '${returnType.linkedName} ${super.linkedName}(${ParameterRendererHtml().renderLinkedParams(element.parameters)})';
}
return _linkedName;
}
diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart
index 29e54b5dfd..e09ba79d4f 100644
--- a/lib/src/model/model_element.dart
+++ b/lib/src/model/model_element.dart
@@ -26,6 +26,7 @@ import 'package:dartdoc/src/logging.dart';
import 'package:dartdoc/src/markdown_processor.dart' show Documentation;
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/source_linker.dart';
import 'package:dartdoc/src/tuple.dart';
import 'package:dartdoc/src/utils.dart';
@@ -928,18 +929,18 @@ abstract class ModelElement extends Canonicalization
return _linkedName;
}
- String get linkedParams => utils.linkedParams(parameters);
+ String get linkedParams =>
+ ParameterRendererHtml().renderLinkedParams(parameters);
String get linkedParamsLines =>
- utils.linkedParams(parameters, asList: true).trim();
+ ParameterRendererHtmlList().renderLinkedParams(parameters).trim();
String get linkedParamsNoMetadata =>
- utils.linkedParams(parameters, showMetadata: false);
+ ParameterRendererHtml(showMetadata: false).renderLinkedParams(parameters);
- String get linkedParamsNoMetadataOrNames {
- return utils.linkedParams(parameters,
- showMetadata: false, showNames: false);
- }
+ String get linkedParamsNoMetadataOrNames =>
+ ParameterRendererHtml(showMetadata: false, showNames: false)
+ .renderLinkedParams(parameters);
ElementType get modelType {
if (_modelType == null) {
diff --git a/lib/src/model_utils.dart b/lib/src/model_utils.dart
index 22d9afe794..8c88c724ea 100644
--- a/lib/src/model_utils.dart
+++ b/lib/src/model_utils.dart
@@ -9,193 +9,11 @@ import 'dart:io';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:dartdoc/src/model/model.dart';
-import 'package:dartdoc/src/element_type.dart';
final Map _fileContents = {};
-/// Render HTML in an extended vertical format using tag.
-class ParameterRendererHtmlList extends ParameterRendererHtml {
- ParameterRendererHtmlList({bool showMetadata = true, bool showNames = true})
- : super(showMetadata: showMetadata, showNames: showNames);
- @override
- String listItem(String listItem) => '- $listItem
\n';
- @override
- // TODO(jcollins-g): consider comma separated lists and more advanced css.
- String orderedList(String listItems) =>
- '$listItems
\n';
-}
-
-/// 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}';
- @override
- String orderedList(String listItems) => listItems;
- @override
- String annotation(String annotation) => '$annotation';
- @override
- String covariant(String covariant) => '$covariant';
- @override
- String defaultValue(String defaultValue) =>
- '$defaultValue';
- @override
- String parameter(String parameter, String htmlId) =>
- '$parameter';
- @override
- String parameterName(String parameterName) =>
- '$parameterName';
- @override
- String typeName(String typeName) =>
- '$typeName';
- @override
- String required(String required) => '$required';
-}
-
-abstract class ParameterRenderer {
- bool get showMetadata;
- bool get showNames;
-
- String listItem(String item);
- String orderedList(String listItems);
- String annotation(String annotation);
- String covariant(String covariant);
- String defaultValue(String defaultValue);
- String parameter(String parameter, String id);
- String parameterName(String parameterName);
- String typeName(String typeName);
- String required(String required);
-
- String _linkedParameterSublist(List 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 linkedParams(List parameters) {
- List positionalParams =
- parameters.where((Parameter p) => p.isRequiredPositional).toList();
- List optionalPositionalParams =
- parameters.where((Parameter p) => p.isOptionalPositional).toList();
- List namedParams =
- parameters.where((Parameter p) => p.isNamed).toList();
-
- String positional = '', optional = '', named = '';
- if (positionalParams.isNotEmpty) {
- positional = _linkedParameterSublist(positionalParams,
- optionalPositionalParams.isNotEmpty || namedParams.isNotEmpty);
- }
- if (optionalPositionalParams.isNotEmpty) {
- optional = _linkedParameterSublist(
- optionalPositionalParams, namedParams.isNotEmpty,
- thisOpenBracket: '[', thisCloseBracket: ']');
- }
- if (namedParams.isNotEmpty) {
- named = _linkedParameterSublist(namedParams, false,
- thisOpenBracket: '{', thisCloseBracket: '}');
- }
- return (orderedList(positional + optional + named));
- }
-
- String renderParam(Parameter param) {
- StringBuffer buf = StringBuffer();
- ElementType paramModelType = param.modelType;
-
- if (showMetadata && param.hasAnnotations) {
- buf.write(param.annotations.map(annotation).join(' ') + ' ');
- }
- if (param.isRequiredNamed) {
- buf.write(required('required') + ' ');
- }
- if (param.isCovariant) {
- buf.write(covariant('covariant') + ' ');
- }
- if (paramModelType is CallableElementTypeMixin ||
- paramModelType.type is FunctionType) {
- String returnTypeName;
- if (paramModelType.isTypedef) {
- returnTypeName = paramModelType.linkedName;
- } else {
- returnTypeName = paramModelType.createLinkedReturnTypeName();
- }
- buf.write(typeName(returnTypeName));
- if (showNames) {
- buf.write(' ${parameterName(param.name)}');
- } else if (paramModelType.isTypedef ||
- paramModelType is CallableAnonymousElementType ||
- paramModelType.type is FunctionType) {
- buf.write(' ${parameterName(paramModelType.name)}');
- }
- if (!paramModelType.isTypedef && paramModelType is DefinedElementType) {
- buf.write('(');
- buf.write(linkedParams(paramModelType.element.parameters));
- buf.write(')');
- }
- if (!paramModelType.isTypedef && paramModelType.type is FunctionType) {
- buf.write('(');
- buf.write(
- linkedParams((paramModelType as UndefinedElementType).parameters));
- buf.write(')');
- }
- } else if (param.modelType != null) {
- String linkedTypeName = paramModelType.linkedName;
- if (linkedTypeName.isNotEmpty) {
- buf.write(typeName(linkedTypeName));
- if (showNames && param.name.isNotEmpty) {
- buf.write(' ');
- }
- }
- if (showNames && param.name.isNotEmpty) {
- buf.write(parameterName(param.name));
- }
- }
-
- if (param.hasDefaultValue) {
- if (param.isNamed) {
- buf.write(': ');
- } else {
- buf.write(' = ');
- }
- buf.write(defaultValue(param.defaultValue));
- }
- return buf.toString();
- }
-}
-
-String linkedParams(List parameters,
- {showMetadata = true, showNames = true, asList = false}) {
- if (asList) {
- return ParameterRendererHtmlList(
- showMetadata: showMetadata, showNames: showNames)
- .linkedParams(parameters);
- }
- return ParameterRendererHtml(showMetadata: showMetadata, showNames: showNames)
- .linkedParams(parameters);
-}
-
/// Returns the [AstNode] for a given [Element].
///
/// Uses a precomputed map of [element.source.fullName] to [CompilationUnit]
diff --git a/lib/src/render/parameter_renderer.dart b/lib/src/render/parameter_renderer.dart
new file mode 100644
index 0000000000..f4998c9f41
--- /dev/null
+++ b/lib/src/render/parameter_renderer.dart
@@ -0,0 +1,176 @@
+// 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:analyzer/dart/element/type.dart';
+import 'package:dartdoc/src/element_type.dart';
+import 'package:dartdoc/src/model/parameter.dart';
+
+/// Render HTML in an extended vertical format using tag.
+class ParameterRendererHtmlList extends ParameterRendererHtml {
+ ParameterRendererHtmlList({bool showMetadata = true, bool showNames = true})
+ : super(showMetadata: showMetadata, showNames: showNames);
+ @override
+ String listItem(String listItem) => '- $listItem
\n';
+ @override
+ // TODO(jcollins-g): consider comma separated lists and more advanced css.
+ String orderedList(String listItems) =>
+ '$listItems
\n';
+}
+
+/// 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}';
+ @override
+ String orderedList(String listItems) => listItems;
+ @override
+ String annotation(String annotation) => '$annotation';
+ @override
+ String covariant(String covariant) => '$covariant';
+ @override
+ String defaultValue(String defaultValue) =>
+ '$defaultValue';
+ @override
+ String parameter(String parameter, String htmlId) =>
+ '$parameter';
+ @override
+ String parameterName(String parameterName) =>
+ '$parameterName';
+ @override
+ String typeName(String typeName) =>
+ '$typeName';
+ @override
+ String required(String required) => '$required';
+}
+
+abstract class ParameterRenderer {
+ bool get showMetadata;
+ bool get showNames;
+
+ String listItem(String item);
+ String orderedList(String listItems);
+ String annotation(String annotation);
+ String covariant(String covariant);
+ String defaultValue(String defaultValue);
+ String parameter(String parameter, String id);
+ String parameterName(String parameterName);
+ String typeName(String typeName);
+ String required(String required);
+
+ String _linkedParameterSublist(List 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 parameters) {
+ List positionalParams =
+ parameters.where((Parameter p) => p.isRequiredPositional).toList();
+ List optionalPositionalParams =
+ parameters.where((Parameter p) => p.isOptionalPositional).toList();
+ List namedParams =
+ parameters.where((Parameter p) => p.isNamed).toList();
+
+ String positional = '', optional = '', named = '';
+ if (positionalParams.isNotEmpty) {
+ positional = _linkedParameterSublist(positionalParams,
+ optionalPositionalParams.isNotEmpty || namedParams.isNotEmpty);
+ }
+ if (optionalPositionalParams.isNotEmpty) {
+ optional = _linkedParameterSublist(
+ optionalPositionalParams, namedParams.isNotEmpty,
+ thisOpenBracket: '[', thisCloseBracket: ']');
+ }
+ if (namedParams.isNotEmpty) {
+ named = _linkedParameterSublist(namedParams, false,
+ thisOpenBracket: '{', thisCloseBracket: '}');
+ }
+ return (orderedList(positional + optional + named));
+ }
+
+ String renderParam(Parameter param) {
+ StringBuffer buf = StringBuffer();
+ ElementType paramModelType = param.modelType;
+
+ if (showMetadata && param.hasAnnotations) {
+ buf.write(param.annotations.map(annotation).join(' ') + ' ');
+ }
+ if (param.isRequiredNamed) {
+ buf.write(required('required') + ' ');
+ }
+ if (param.isCovariant) {
+ buf.write(covariant('covariant') + ' ');
+ }
+ if (paramModelType is CallableElementTypeMixin ||
+ paramModelType.type is FunctionType) {
+ String returnTypeName;
+ if (paramModelType.isTypedef) {
+ returnTypeName = paramModelType.linkedName;
+ } else {
+ returnTypeName = paramModelType.createLinkedReturnTypeName();
+ }
+ buf.write(typeName(returnTypeName));
+ if (showNames) {
+ buf.write(' ${parameterName(param.name)}');
+ } else if (paramModelType.isTypedef ||
+ paramModelType is CallableAnonymousElementType ||
+ paramModelType.type is FunctionType) {
+ buf.write(' ${parameterName(paramModelType.name)}');
+ }
+ if (!paramModelType.isTypedef && paramModelType is DefinedElementType) {
+ buf.write('(');
+ buf.write(renderLinkedParams(paramModelType.element.parameters));
+ buf.write(')');
+ }
+ if (!paramModelType.isTypedef && paramModelType.type is FunctionType) {
+ buf.write('(');
+ buf.write(renderLinkedParams(
+ (paramModelType as UndefinedElementType).parameters));
+ buf.write(')');
+ }
+ } else if (param.modelType != null) {
+ String linkedTypeName = paramModelType.linkedName;
+ if (linkedTypeName.isNotEmpty) {
+ buf.write(typeName(linkedTypeName));
+ if (showNames && param.name.isNotEmpty) {
+ buf.write(' ');
+ }
+ }
+ if (showNames && param.name.isNotEmpty) {
+ buf.write(parameterName(param.name));
+ }
+ }
+
+ if (param.hasDefaultValue) {
+ if (param.isNamed) {
+ buf.write(': ');
+ } else {
+ buf.write(' = ');
+ }
+ buf.write(defaultValue(param.defaultValue));
+ }
+ return buf.toString();
+ }
+}
diff --git a/test/model_test.dart b/test/model_test.dart
index 55fc10e654..ccc39702a8 100644
--- a/test/model_test.dart
+++ b/test/model_test.dart
@@ -8,8 +8,8 @@ import 'dart:io';
import 'package:dartdoc/dartdoc.dart';
import 'package:dartdoc/src/model/model.dart';
-import 'package:dartdoc/src/model_utils.dart';
import 'package:dartdoc/src/render/category_renderer.dart';
+import 'package:dartdoc/src/render/parameter_renderer.dart';
import 'package:dartdoc/src/warnings.dart';
import 'package:test/test.dart';
@@ -2084,7 +2084,8 @@ void main() {
});
test('handles dynamic parameters correctly', () {
- expect(linkedParams(f1.parameters), contains('lastParam'));
+ expect(ParameterRendererHtml().renderLinkedParams(f1.parameters),
+ contains('lastParam'));
});
test('async function', () {
@@ -2123,7 +2124,8 @@ void main() {
test('function with a parameter having type FutureOr', () {
expect(
- linkedParams(paramOfFutureOrNull.parameters),
+ ParameterRendererHtml()
+ .renderLinkedParams(paramOfFutureOrNull.parameters),
equals(
'FutureOr<Null> future'));
});
@@ -2151,7 +2153,8 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans,
test('typedef params have proper signature', () {
ModelFunction function =
fakeLibrary.functions.firstWhere((f) => f.name == 'addCallback');
- String params = linkedParams(function.parameters);
+ String params =
+ ParameterRendererHtml().renderLinkedParams(function.parameters);
expect(
params,
''
@@ -2160,7 +2163,7 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans,
function =
fakeLibrary.functions.firstWhere((f) => f.name == 'addCallback2');
- params = linkedParams(function.parameters);
+ params = ParameterRendererHtml().renderLinkedParams(function.parameters);
expect(
params,
''
@@ -2174,7 +2177,8 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans,
});
test('can resolve functions as parameters', () {
- String params = linkedParams(doAComplicatedThing.parameters);
+ String params = ParameterRendererHtml()
+ .renderLinkedParams(doAComplicatedThing.parameters);
expect(params,
'int x, {void doSomething(int aThingParameter, String anotherThing), void doSomethingElse(int aThingParameter, double somethingElse)}');
});
@@ -2292,7 +2296,9 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans,
.singleWhere((m) => m.name == 'operator +');
expect(aInheritedAdditionOperator.linkedReturnType,
'ParameterizedClass<List<int>>');
- expect(linkedParams(aInheritedAdditionOperator.parameters),
+ expect(
+ ParameterRendererHtml()
+ .renderLinkedParams(aInheritedAdditionOperator.parameters),
'ParameterizedClass<List<int>> other');
});
@@ -3258,8 +3264,8 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans,
test('a function requiring a Future parameter', () {
expect(
- linkedParams(aVoidParameter.parameters,
- showMetadata: true, showNames: true),
+ ParameterRendererHtml(showMetadata: true, showNames: true)
+ .renderLinkedParams(aVoidParameter.parameters),
equals(
'Future<void> p1'));
});
@@ -3341,7 +3347,7 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans,
() {
Constructor theConstructor = TypedefUsingClass.constructors.first;
expect(
- linkedParams(theConstructor.parameters),
+ ParameterRendererHtml().renderLinkedParams(theConstructor.parameters),
equals(
'ParameterizedTypedef<double> x'));
});
@@ -3488,21 +3494,24 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans,
});
test('param with generics', () {
- var params = linkedParams(methodWithGenericParam.parameters);
+ var params = ParameterRendererHtml()
+ .renderLinkedParams(methodWithGenericParam.parameters);
expect(params.contains('List') && params.contains('Apple'), isTrue);
});
test('commas on same param line', () {
ModelFunction method =
fakeLibrary.functions.firstWhere((f) => f.name == 'paintImage1');
- String params = linkedParams(method.parameters);
+ String params =
+ ParameterRendererHtml().renderLinkedParams(method.parameters);
expect(params, contains(', '));
});
test('param with annotations', () {
ModelFunction method =
fakeLibrary.functions.firstWhere((f) => f.name == 'paintImage1');
- String params = linkedParams(method.parameters);
+ String params =
+ ParameterRendererHtml().renderLinkedParams(method.parameters);
expect(params, contains('@required'));
});
@@ -3513,7 +3522,8 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans,
});
test('typedef param is linked and does not include types', () {
- var params = linkedParams(methodWithTypedefParam.parameters);
+ var params = ParameterRendererHtml()
+ .renderLinkedParams(methodWithTypedefParam.parameters);
expect(
params,
equals(