Skip to content

Commit

Permalink
Merge 7e9f0bf into 34d371f
Browse files Browse the repository at this point in the history
  • Loading branch information
jcollins-g committed May 18, 2021
2 parents 34d371f + 7e9f0bf commit da7bbfc
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 160 deletions.
68 changes: 12 additions & 56 deletions lib/src/element_type.dart
Expand Up @@ -383,8 +383,10 @@ abstract class DefinedElementType extends ElementType {
}

/// Any callable ElementType will mix-in this class, whether anonymous or not.
abstract class CallableElementTypeMixin implements ElementType {
Iterable<ElementType> _typeArguments;
mixin CallableElementTypeMixin implements ElementType {
@override
// TODO(jcollins-g): remove after dart-lang/dartdoc#2648 is fixed.
String get linkedName;

ModelElement get returnElement => returnType is DefinedElementType
? (returnType as DefinedElementType).modelElement
Expand All @@ -400,50 +402,12 @@ abstract class CallableElementTypeMixin implements ElementType {
@override
FunctionType get type => _type;

// TODO(jcollins-g): Rewrite this and improve object model so this doesn't
// require type checking everywhere.
Iterable<ElementType> get typeArguments {
if (_typeArguments == null) {
Iterable<DartType> dartTypeArguments;
if (returnedFrom is FunctionTypeElementType) {
if (type.typeFormals.isEmpty) {
dartTypeArguments = type.aliasArguments;
} else {
dartTypeArguments = type.typeFormals.map(_legacyTypeParameterType);
}
} else {
if (type.typeFormals.isEmpty) {
dartTypeArguments = type.aliasArguments;
} else if (returnedFrom != null &&
returnedFrom.type.element is GenericFunctionTypeElement) {
_typeArguments = (returnedFrom as DefinedElementType).typeArguments;
} else {
dartTypeArguments = type.typeFormals.map(_legacyTypeParameterType);
}
}
if (dartTypeArguments != null) {
_typeArguments = dartTypeArguments
.map((f) => ElementType.from(f, library, packageGraph))
.toList();
}
}
return _typeArguments;
}

/// Return the [TypeParameterType] with the legacy nullability for the given
/// type parameter [element].
///
/// TODO(scheglov): This method is a work around that fact that DartDoc
/// currently represents both type formals and uses of them as actual types,
/// as [TypeParameterType]s. This was not perfect, but worked before Null
/// safety. With Null safety, types have nullability suffixes, but type
/// formals should not. Eventually we should separate models for type formals
/// and types.
static TypeParameterType _legacyTypeParameterType(
TypeParameterElement element,
) {
return element.instantiate(nullabilitySuffix: NullabilitySuffix.star);
}
Iterable<ElementType> _typeArguments;
Iterable<ElementType> get typeArguments =>
_typeArguments ??= type.aliasArguments
?.map((f) => ElementType.from(f, library, packageGraph))
?.toList() ??
[];
}

/// A callable type that may or may not be backed by a declaration using the generic
Expand All @@ -455,16 +419,8 @@ class CallableElementType extends ParameterizedElementType
: super(t, library, packageGraph, element, returnedFrom);

@override
String get linkedName {
if (_linkedName == null) {
if (name != null && name.isNotEmpty) {
_linkedName = super.linkedName;
} else {
_linkedName = _renderer.renderLinkedName(this);
}
}
return _linkedName;
}
String get name =>
super.name != null && super.name.isNotEmpty ? super.name : 'Function';

@override
ElementTypeRenderer<CallableElementType> get _renderer =>
Expand Down
137 changes: 70 additions & 67 deletions lib/src/generator/templates.renderers.dart
Expand Up @@ -500,7 +500,26 @@ class _Renderer_CallableElementTypeMixin
_propertyMapCache.putIfAbsent(
CT_,
() => {
..._Renderer_Object.propertyMap<CT_>(),
'linkedName': Property(
getValue: (CT_ c) => c.linkedName,
renderVariable:
(CT_ c, Property<CT_> self, List<String> remainingNames) {
if (remainingNames.isEmpty) {
return self.getValue(c).toString();
}
var name = remainingNames.first;
var nextProperty =
_Renderer_String.propertyMap().getValue(name);
return nextProperty.renderVariable(self.getValue(c),
nextProperty, [...remainingNames.skip(1)]);
},
isNullValue: (CT_ c) => c.linkedName == null,
renderValue:
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
return _render_String(c.linkedName, ast, r.template,
parent: r);
},
),
'returnElement': Property(
getValue: (CT_ c) => c.returnElement,
renderVariable:
Expand Down Expand Up @@ -6042,60 +6061,35 @@ String _render_FunctionTypedef(

class _Renderer_FunctionTypedef extends RendererBase<FunctionTypedef> {
static final Map<Type, Object> _propertyMapCache = {};
static Map<String, Property<CT_>> propertyMap<
CT_ extends FunctionTypedef>() =>
_propertyMapCache.putIfAbsent(
CT_,
() => {
..._Renderer_Typedef.propertyMap<CT_>(),
'aliasedType': Property(
getValue: (CT_ c) => c.aliasedType,
renderVariable: (CT_ c, Property<CT_> self,
List<String> remainingNames) =>
self.renderSimpleVariable(
c, remainingNames, 'FunctionType'),
isNullValue: (CT_ c) => c.aliasedType == null,
renderValue:
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
return renderSimple(c.aliasedType, ast, r.template,
parent: r);
},
),
'genericTypeParameters': Property(
getValue: (CT_ c) => c.genericTypeParameters,
renderVariable: (CT_ c, Property<CT_> self,
List<String> remainingNames) =>
self.renderSimpleVariable(
c, remainingNames, 'List<TypeParameterElement>'),
renderIterable:
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
return c.genericTypeParameters.map(
(e) => renderSimple(e, ast, r.template, parent: r));
},
),
'modelType': Property(
getValue: (CT_ c) => c.modelType,
renderVariable:
(CT_ c, Property<CT_> self, List<String> remainingNames) {
if (remainingNames.isEmpty) {
return self.getValue(c).toString();
}
var name = remainingNames.first;
var nextProperty =
_Renderer_CallableElementTypeMixin.propertyMap()
.getValue(name);
return nextProperty.renderVariable(self.getValue(c),
nextProperty, [...remainingNames.skip(1)]);
},
isNullValue: (CT_ c) => c.modelType == null,
renderValue:
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
return _render_CallableElementTypeMixin(
c.modelType, ast, r.template,
parent: r);
},
),
});
static Map<String, Property<CT_>>
propertyMap<CT_ extends FunctionTypedef>() =>
_propertyMapCache.putIfAbsent(
CT_,
() => {
..._Renderer_Typedef.propertyMap<CT_>(),
'modelType': Property(
getValue: (CT_ c) => c.modelType,
renderVariable: (CT_ c, Property<CT_> self,
List<String> remainingNames) {
if (remainingNames.isEmpty) {
return self.getValue(c).toString();
}
var name = remainingNames.first;
var nextProperty =
_Renderer_CallableElementTypeMixin.propertyMap()
.getValue(name);
return nextProperty.renderVariable(self.getValue(c),
nextProperty, [...remainingNames.skip(1)]);
},
isNullValue: (CT_ c) => c.modelType == null,
renderValue: (CT_ c, RendererBase<CT_> r,
List<MustachioNode> ast) {
return _render_CallableElementTypeMixin(
c.modelType, ast, r.template,
parent: r);
},
),
});

_Renderer_FunctionTypedef(
FunctionTypedef context, RendererBase<Object> parent, Template template)
Expand Down Expand Up @@ -13914,18 +13908,6 @@ class _Renderer_Typedef extends RendererBase<Typedef> {
parent: r);
},
),
'genericTypeParameters': Property(
getValue: (CT_ c) => c.genericTypeParameters,
renderVariable: (CT_ c, Property<CT_> self,
List<String> remainingNames) =>
self.renderSimpleVariable(
c, remainingNames, 'List<TypeParameterElement>'),
renderIterable:
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
return c.genericTypeParameters.map(
(e) => renderSimple(e, ast, r.template, parent: r));
},
),
'href': Property(
getValue: (CT_ c) => c.href,
renderVariable:
Expand Down Expand Up @@ -13971,6 +13953,27 @@ class _Renderer_Typedef extends RendererBase<Typedef> {
return _render_String(c.kind, ast, r.template, parent: r);
},
),
'linkedGenericParameters': Property(
getValue: (CT_ c) => c.linkedGenericParameters,
renderVariable:
(CT_ c, Property<CT_> self, List<String> remainingNames) {
if (remainingNames.isEmpty) {
return self.getValue(c).toString();
}
var name = remainingNames.first;
var nextProperty =
_Renderer_String.propertyMap().getValue(name);
return nextProperty.renderVariable(self.getValue(c),
nextProperty, [...remainingNames.skip(1)]);
},
isNullValue: (CT_ c) => c.linkedGenericParameters == null,
renderValue:
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
return _render_String(
c.linkedGenericParameters, ast, r.template,
parent: r);
},
),
'modelType': Property(
getValue: (CT_ c) => c.modelType,
renderVariable:
Expand Down
20 changes: 3 additions & 17 deletions lib/src/model/typedef.dart
Expand Up @@ -33,8 +33,9 @@ class Typedef extends ModelElement
@override
String get genericParameters => _renderer.renderGenericParameters(this);

List<TypeParameterElement> get genericTypeParameters =>
element.typeParameters;
@override
String get linkedGenericParameters =>
_renderer.renderLinkedGenericParameters(this);

@override
String get filePath => '${library.dirName}/$fileName';
Expand Down Expand Up @@ -87,21 +88,6 @@ class FunctionTypedef extends Typedef {
TypeAliasElement element, Library library, PackageGraph packageGraph)
: super(element, library, packageGraph);

@override
FunctionType get aliasedType => super.aliasedType;

@override
List<TypeParameterElement> get genericTypeParameters {
var aliasedTypeElement = aliasedType.aliasElement;
if (aliasedTypeElement is FunctionTypedElement) {
return aliasedTypeElement.typeParameters;
}
if (aliasedType.typeFormals.isNotEmpty == true) {
return aliasedType.typeFormals;
}
return super.genericTypeParameters;
}

@override
CallableElementTypeMixin get modelType => super.modelType;
}
32 changes: 32 additions & 0 deletions lib/src/render/element_type_renderer.dart
Expand Up @@ -141,6 +141,22 @@ class CallableElementTypeRendererHtml
buf.write(elementType.returnType.linkedName);
return wrapNullabilityParens(elementType, buf.toString());
}

@override
String renderNameWithGenerics(CallableElementType elementType) {
var buf = StringBuffer();
buf.write(elementType.name);
if (elementType.typeArguments != null) {
if (elementType.typeArguments.isNotEmpty &&
!elementType.typeArguments.every((t) => t.name == 'dynamic')) {
buf.write('&lt;');
buf.writeAll(
elementType.typeArguments.map((t) => t.nameWithGenerics), ', ');
buf.write('>');
}
}
return wrapNullability(elementType, buf.toString());
}
}

// Markdown implementations
Expand Down Expand Up @@ -255,4 +271,20 @@ class CallableElementTypeRendererMd
buf.write(elementType.returnType.linkedName);
return wrapNullabilityParens(elementType, buf.toString());
}

@override
String renderNameWithGenerics(CallableElementType elementType) {
var buf = StringBuffer();
buf.write(elementType.name);
if (elementType.typeArguments != null) {
if (elementType.typeArguments.isNotEmpty &&
!elementType.typeArguments.every((t) => t.name == 'dynamic')) {
buf.write('&lt;');
buf.writeAll(
elementType.typeArguments.map((t) => t.nameWithGenerics), ', ');
buf.write('>');
}
}
return wrapNullability(elementType, buf.toString());
}
}
25 changes: 20 additions & 5 deletions lib/src/render/type_parameters_renderer.dart
Expand Up @@ -5,6 +5,8 @@
import 'package:dartdoc/src/model/type_parameter.dart';

abstract class TypeParametersRenderer {
const TypeParametersRenderer();

String renderGenericParameters(TypeParameters typeParameters);

String renderLinkedGenericParameters(TypeParameters typeParameters);
Expand All @@ -19,7 +21,10 @@ class TypeParametersRendererHtml implements TypeParametersRenderer {
return '';
}
var joined = typeParameters.typeParameters
.map((t) => t.name)
.map((t) => [
...t.annotations.map((a) => a.linkedNameWithParameters),
t.name
].join(' '))
.join('</span>, <span class="type-parameter">');
return '&lt;<wbr><span class="type-parameter">$joined</span>&gt;';
}
Expand All @@ -30,7 +35,10 @@ class TypeParametersRendererHtml implements TypeParametersRenderer {
return '';
}
var joined = typeParameters.typeParameters
.map((t) => t.linkedName)
.map((t) => [
...t.annotations.map((a) => a.linkedNameWithParameters),
t.linkedName
].join(' '))
.join('</span>, <span class="type-parameter">');
return '<span class="signature">&lt;<wbr><span class="type-parameter">$joined</span>&gt;</span>';
}
Expand All @@ -40,12 +48,19 @@ class TypeParametersRendererMd implements TypeParametersRenderer {
const TypeParametersRendererMd();

@override
String renderGenericParameters(TypeParameters typeParameters) =>
_compose(typeParameters.typeParameters, (t) => t.name);
String renderGenericParameters(TypeParameters typeParameters) => _compose(
typeParameters.typeParameters,
(t) => [...t.annotations.map((a) => a.linkedNameWithParameters), t.name]
.join(' '));

@override
String renderLinkedGenericParameters(TypeParameters typeParameters) =>
_compose(typeParameters.typeParameters, (t) => t.linkedName);
_compose(
typeParameters.typeParameters,
(t) => [
...t.annotations.map((a) => a.linkedNameWithParameters),
t.linkedName
].join(' '));

String _compose(List<TypeParameter> typeParameters,
String Function(TypeParameter) mapfn) {
Expand Down

0 comments on commit da7bbfc

Please sign in to comment.