diff --git a/lib/src/element_type.dart b/lib/src/element_type.dart index e5d887d311..ba2da3912f 100644 --- a/lib/src/element_type.dart +++ b/lib/src/element_type.dart @@ -26,11 +26,15 @@ abstract class ElementType extends Privacy with CommentReferable, Nameable { factory ElementType.from( DartType f, Library library, PackageGraph packageGraph, - [ElementType returnedFrom]) { + {ElementType returnedFrom}) { if (f.element == null || f.element.kind == ElementKind.DYNAMIC || f.element.kind == ElementKind.NEVER) { if (f is FunctionType) { + if (f.aliasElement != null) { + return AliasedFunctionTypeElementType( + f, library, packageGraph, returnedFrom); + } return FunctionTypeElementType(f, library, packageGraph, returnedFrom); } return UndefinedElementType(f, library, packageGraph, returnedFrom); @@ -50,10 +54,13 @@ abstract class ElementType extends Privacy with CommentReferable, Nameable { var isGenericTypeAlias = f.aliasElement != null && f is! InterfaceType; if (f is FunctionType) { assert(f is ParameterizedType); - if (isGenericTypeAlias) { - return CallableGenericTypeAliasElementType( - f, library, packageGraph, element, returnedFrom); - } + // This is an indication we have an extremely out of date analyzer.... + assert( + !isGenericTypeAlias, 'should never occur: out of date analyzer?'); + // And finally, delete this case and its associated class + // after https://dart-review.googlesource.com/c/sdk/+/201520 + // is in all published versions of analyzer this version of dartdoc + // is compatible with. return CallableElementType( f, library, packageGraph, element, returnedFrom); } else if (isGenericTypeAlias) { @@ -93,11 +100,10 @@ abstract class ElementType extends Privacy with CommentReferable, Nameable { return ''; } - /// An unmodifiable list of this element type's parameters. - List get parameters; - DartType get instantiatedType; + Iterable get typeArguments; + bool isBoundSupertypeTo(ElementType t); bool isSubtypeOf(ElementType t); @@ -117,33 +123,20 @@ class UndefinedElementType extends ElementType { @override Element get element => null; - String _linkedName; - @override bool get isPublic => true; @override String get name { - if (isImpliedFuture) return 'Future'; if (type.isVoid) return 'void'; assert({'Never', 'void', 'dynamic'}.contains(type.element.name), 'Unrecognized type for UndefinedElementType: ${type.toString()}'); return type.element.name; } - /// Returns true if this type is an implied `Future`. - bool get isImpliedFuture => (type.isDynamic && - returnedFrom != null && - returnedFrom is DefinedElementType && - (returnedFrom as DefinedElementType).modelElement.isAsynchronous); - @override String get nameWithGenerics => '$name$nullabilitySuffix'; - @override - String get nullabilitySuffix => - isImpliedFuture && library.isNullSafety ? '?' : super.nullabilitySuffix; - /// Assume that undefined elements don't have useful bounds. @override DartType get instantiatedType => type; @@ -158,45 +151,22 @@ class UndefinedElementType extends ElementType { String get linkedName => name; @override - Map get referenceChildren => {}; + Iterable get typeArguments => []; @override - Iterable get referenceParents => []; + Map get referenceChildren => {}; @override - // TODO(jcollins-g): remove the need for an empty list here. - List get parameters => []; + Iterable get referenceParents => []; } /// A FunctionType that does not have an underpinning Element. class FunctionTypeElementType extends UndefinedElementType - with CallableElementTypeMixin { - FunctionTypeElementType(DartType f, Library library, + with Rendered, Callable { + FunctionTypeElementType(FunctionType f, Library library, PackageGraph packageGraph, ElementType returnedFrom) : super(f, library, packageGraph, returnedFrom); - @override - List get parameters => type.parameters - .map((p) => ModelElement.from(p, library, packageGraph) as Parameter) - .toList(growable: false); - - @override - ElementType get returnType => - ElementType.from(type.returnType, library, packageGraph, this); - - @override - String get linkedName { - _linkedName ??= _renderer.renderLinkedName(this); - return _linkedName; - } - - String _nameWithGenerics; - @override - String get nameWithGenerics { - _nameWithGenerics ??= _renderer.renderNameWithGenerics(this); - return _nameWithGenerics; - } - /// An unmodifiable list of this function element's type parameters. List get typeFormals => type.typeFormals .map((p) => ModelElement.from(p, library, packageGraph) as TypeParameter) @@ -205,39 +175,42 @@ class FunctionTypeElementType extends UndefinedElementType @override String get name => 'Function'; - ElementTypeRenderer get _renderer => + @override + ElementTypeRenderer get _renderer => packageGraph.rendererFactory.functionTypeElementTypeRenderer; } -class ParameterizedElementType extends DefinedElementType { +class AliasedFunctionTypeElementType extends FunctionTypeElementType + with Aliased { + AliasedFunctionTypeElementType(FunctionType f, Library library, + PackageGraph packageGraph, ElementType returnedFrom) + : super(f, library, packageGraph, returnedFrom) { + assert(type.aliasElement != null); + assert(type.aliasArguments != null); + } + + @override + ElementTypeRenderer get _renderer => + packageGraph.rendererFactory.aliasedFunctionTypeElementTypeRenderer; +} + +class ParameterizedElementType extends DefinedElementType with Rendered { ParameterizedElementType(ParameterizedType type, Library library, PackageGraph packageGraph, ModelElement element, ElementType returnedFrom) : super(type, library, packageGraph, element, returnedFrom); - String _linkedName; - @override - String get linkedName { - _linkedName ??= _renderer.renderLinkedName(this); - return _linkedName; - } - - String _nameWithGenerics; @override - String get nameWithGenerics { - _nameWithGenerics ??= _renderer.renderNameWithGenerics(this); - return _nameWithGenerics; - } - ElementTypeRenderer get _renderer => packageGraph.rendererFactory.parameterizedElementTypeRenderer; } -class AliasedElementType extends ParameterizedElementType { - AliasedElementType(ParameterizedType type, Library library, - PackageGraph packageGraph, ModelElement element, ElementType returnedFrom) - : super(type, library, packageGraph, element, returnedFrom) { - assert(type.aliasElement != null); - } +/// A [ElementType] whose underlying type was referrred to by a type alias. +mixin Aliased implements ElementType { + @override + String get name => type.aliasElement.name; + + @override + bool get isTypedef => true; ModelElement _aliasElement; ModelElement get aliasElement => _aliasElement ??= @@ -249,6 +222,26 @@ class AliasedElementType extends ParameterizedElementType { .map((f) => ElementType.from(f, library, packageGraph)) .toList(growable: false); + Iterable _typeArguments; + @override + Iterable get typeArguments => + _typeArguments ??= (type as ParameterizedType) + .typeArguments + .map((f) => ElementType.from(f, library, packageGraph)) + .toList(growable: false); +} + +class AliasedElementType extends ParameterizedElementType with Aliased { + AliasedElementType(ParameterizedType type, Library library, + PackageGraph packageGraph, ModelElement element, ElementType returnedFrom) + : super(type, library, packageGraph, element, returnedFrom) { + assert(type.aliasElement != null); + } + + /// Parameters, if available, for the underlying typedef. + List get aliasedParameters => + modelElement.isCallable ? modelElement.parameters : []; + @override ElementTypeRenderer get _renderer => packageGraph.rendererFactory.aliasedElementTypeRenderer; @@ -304,24 +297,8 @@ abstract class DefinedElementType extends ElementType { return canonicalClass?.isPublic ?? false; } - @override - bool get isTypedef => - modelElement is Typedef || modelElement is ModelFunctionTypedef; - - @override - List get parameters => - modelElement.isCallable ? modelElement.parameters : []; - - ModelElement get returnElement => modelElement; - ElementType _returnType; - ElementType get returnType { - _returnType ??= ElementType.from(type, library, packageGraph, this); - return _returnType; - } - Iterable _typeArguments; - - /// An unmodifiable list of this element type's parameters. + @override Iterable get typeArguments => _typeArguments ??= (type as ParameterizedType) .typeArguments @@ -383,38 +360,46 @@ abstract class DefinedElementType extends ElementType { modelElement.referenceParents; } -/// Any callable ElementType will mix-in this class, whether anonymous or not. -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 - : null; +/// Any callable ElementType will mix-in this class, whether anonymous or not, +/// unless it is an alias reference. +mixin Callable implements ElementType { + List get parameters => type.parameters + .map((p) => ModelElement.from(p, library, packageGraph) as Parameter) + .toList(growable: false); ElementType _returnType; ElementType get returnType { - _returnType ??= - ElementType.from(type.returnType, library, packageGraph, this); + _returnType ??= ElementType.from(type.returnType, library, packageGraph); return _returnType; } @override FunctionType get type => _type; +} - Iterable _typeArguments; - Iterable get typeArguments => - _typeArguments ??= type.aliasArguments - ?.map((f) => ElementType.from(f, library, packageGraph)) - ?.toList() ?? - []; +/// This [ElementType] uses an [ElementTypeRenderer] to generate +/// some of its parameters. +mixin Rendered implements ElementType { + String _linkedName; + @override + String get linkedName { + _linkedName ??= _renderer.renderLinkedName(this); + return _linkedName; + } + + String _nameWithGenerics; + @override + String get nameWithGenerics { + _nameWithGenerics ??= _renderer.renderNameWithGenerics(this); + return _nameWithGenerics; + } + + ElementTypeRenderer get _renderer; } /// A callable type that may or may not be backed by a declaration using the generic /// function syntax. -class CallableElementType extends ParameterizedElementType - with CallableElementTypeMixin { +class CallableElementType extends DefinedElementType with Rendered, Callable { CallableElementType(FunctionType t, Library library, PackageGraph packageGraph, ModelElement element, ElementType returnedFrom) : super(t, library, packageGraph, element, returnedFrom); @@ -428,39 +413,9 @@ class CallableElementType extends ParameterizedElementType packageGraph.rendererFactory.callableElementTypeRenderer; } -/// Types backed by a [GenericTypeAliasElement] that may or may not be callable. -abstract class GenericTypeAliasElementTypeMixin {} - /// A non-callable type backed by a [GenericTypeAliasElement]. -class GenericTypeAliasElementType extends TypeParameterElementType - with GenericTypeAliasElementTypeMixin { +class GenericTypeAliasElementType extends TypeParameterElementType { GenericTypeAliasElementType(TypeParameterType t, Library library, PackageGraph packageGraph, ModelElement element, ElementType returnedFrom) : super(t, library, packageGraph, element, returnedFrom); } - -/// A Callable generic type alias that may or may not have a name. -class CallableGenericTypeAliasElementType extends ParameterizedElementType - with CallableElementTypeMixin, GenericTypeAliasElementTypeMixin { - CallableGenericTypeAliasElementType(FunctionType t, Library library, - PackageGraph packageGraph, ModelElement element, ElementType returnedFrom) - : super(t, library, packageGraph, element, returnedFrom); - - ModelElement _returnElement; - @override - ModelElement get returnElement { - _returnElement ??= ModelElement.fromElement( - type.aliasElement.enclosingElement, packageGraph); - return _returnElement; - } - - @override - ElementType get returnType { - _returnType ??= - ElementType.from(type.returnType, library, packageGraph, this); - return _returnType; - } - - @override - DartType get instantiatedType => type; -} diff --git a/lib/src/generator/templates.dart b/lib/src/generator/templates.dart index e50ba5eaa1..f358ab801b 100644 --- a/lib/src/generator/templates.dart +++ b/lib/src/generator/templates.dart @@ -41,7 +41,7 @@ import 'package:path/path.dart' as path show Context; const _visibleTypes = { Annotation, - CallableElementTypeMixin, + Callable, Category, Class, Constructor, @@ -50,6 +50,7 @@ const _visibleTypes = { Enum, Extension, FeatureSet, + FunctionTypeElementType, LanguageFeature, Library, LibraryContainer, diff --git a/lib/src/generator/templates.runtime_renderers.dart b/lib/src/generator/templates.runtime_renderers.dart index bd5a970e3d..f524624927 100644 --- a/lib/src/generator/templates.runtime_renderers.dart +++ b/lib/src/generator/templates.runtime_renderers.dart @@ -201,16 +201,14 @@ class _Renderer_Accessor extends RendererBase { } var name = remainingNames.first; var nextProperty = - _Renderer_CallableElementTypeMixin.propertyMap() - .getValue(name); + _Renderer_Callable.propertyMap().getValue(name); return nextProperty.renderVariable(self.getValue(c), nextProperty, [...remainingNames.skip(1)]); }, isNullValue: (CT_ c) => c.modelType == null, renderValue: (CT_ c, RendererBase r, List ast) { - return _render_CallableElementTypeMixin( - c.modelType, ast, r.template, + return _render_Callable(c.modelType, ast, r.template, parent: r); }, ), @@ -484,61 +482,30 @@ class _Renderer_Annotation extends RendererBase { } } -String _render_CallableElementTypeMixin(CallableElementTypeMixin context, - List ast, Template template, +String _render_Callable( + Callable context, List ast, Template template, {RendererBase parent}) { - var renderer = _Renderer_CallableElementTypeMixin(context, parent, template); + var renderer = _Renderer_Callable(context, parent, template); renderer.renderBlock(ast); return renderer.buffer.toString(); } -class _Renderer_CallableElementTypeMixin - extends RendererBase { +class _Renderer_Callable extends RendererBase { static final Map _propertyMapCache = {}; - static Map> propertyMap< - CT_ extends CallableElementTypeMixin>() => + static Map> propertyMap() => _propertyMapCache.putIfAbsent( CT_, () => { - 'linkedName': Property( - getValue: (CT_ c) => c.linkedName, - renderVariable: - (CT_ c, Property self, List 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 r, List ast) { - return _render_String(c.linkedName, ast, r.template, - parent: r); - }, - ), - 'returnElement': Property( - getValue: (CT_ c) => c.returnElement, - renderVariable: - (CT_ c, Property self, List remainingNames) { - if (remainingNames.isEmpty) { - return self.getValue(c).toString(); - } - var name = remainingNames.first; - var nextProperty = - _Renderer_ModelElement.propertyMap().getValue(name); - return nextProperty.renderVariable(self.getValue(c), - nextProperty, [...remainingNames.skip(1)]); - }, - isNullValue: (CT_ c) => c.returnElement == null, - renderValue: + 'parameters': Property( + getValue: (CT_ c) => c.parameters, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable( + c, remainingNames, 'List'), + renderIterable: (CT_ c, RendererBase r, List ast) { - return _render_ModelElement( - c.returnElement, ast, r.template, - parent: r); + return c.parameters.map((e) => + _render_Parameter(e, ast, r.template, parent: r)); }, ), 'returnType': Property( @@ -573,28 +540,16 @@ class _Renderer_CallableElementTypeMixin return renderSimple(c.type, ast, r.template, parent: r); }, ), - 'typeArguments': Property( - getValue: (CT_ c) => c.typeArguments, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable( - c, remainingNames, 'Iterable'), - renderIterable: - (CT_ c, RendererBase r, List ast) { - return c.typeArguments.map( - (e) => renderSimple(e, ast, r.template, parent: r)); - }, - ), }); - _Renderer_CallableElementTypeMixin(CallableElementTypeMixin context, - RendererBase parent, Template template) + _Renderer_Callable( + Callable context, RendererBase parent, Template template) : super(context, parent, template); @override - Property getProperty(String key) { - if (propertyMap().containsKey(key)) { - return propertyMap()[key]; + Property getProperty(String key) { + if (propertyMap().containsKey(key)) { + return propertyMap()[key]; } else { return null; } @@ -2848,16 +2803,14 @@ class _Renderer_Constructor extends RendererBase { } var name = remainingNames.first; var nextProperty = - _Renderer_CallableElementTypeMixin.propertyMap() - .getValue(name); + _Renderer_Callable.propertyMap().getValue(name); return nextProperty.renderVariable(self.getValue(c), nextProperty, [...remainingNames.skip(1)]); }, isNullValue: (CT_ c) => c.modelType == null, renderValue: (CT_ c, RendererBase r, List ast) { - return _render_CallableElementTypeMixin( - c.modelType, ast, r.template, + return _render_Callable(c.modelType, ast, r.template, parent: r); }, ), @@ -4040,13 +3993,6 @@ class _Renderer_DefinedElementType extends RendererBase { self.renderSimpleVariable(c, remainingNames, 'bool'), getBool: (CT_ c) => c.isPublic == true, ), - 'isTypedef': Property( - getValue: (CT_ c) => c.isTypedef, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable(c, remainingNames, 'bool'), - getBool: (CT_ c) => c.isTypedef == true, - ), 'modelElement': Property( getValue: (CT_ c) => c.modelElement, renderVariable: @@ -4086,18 +4032,6 @@ class _Renderer_DefinedElementType extends RendererBase { return _render_String(c.name, ast, r.template, parent: r); }, ), - 'parameters': Property( - getValue: (CT_ c) => c.parameters, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable( - c, remainingNames, 'List'), - renderIterable: - (CT_ c, RendererBase r, List ast) { - return c.parameters.map((e) => - _render_Parameter(e, ast, r.template, parent: r)); - }, - ), 'referenceChildren': Property( getValue: (CT_ c) => c.referenceChildren, renderVariable: (CT_ c, Property self, @@ -4123,47 +4057,6 @@ class _Renderer_DefinedElementType extends RendererBase { (e) => renderSimple(e, ast, r.template, parent: r)); }, ), - 'returnElement': Property( - getValue: (CT_ c) => c.returnElement, - renderVariable: - (CT_ c, Property self, List remainingNames) { - if (remainingNames.isEmpty) { - return self.getValue(c).toString(); - } - var name = remainingNames.first; - var nextProperty = - _Renderer_ModelElement.propertyMap().getValue(name); - return nextProperty.renderVariable(self.getValue(c), - nextProperty, [...remainingNames.skip(1)]); - }, - isNullValue: (CT_ c) => c.returnElement == null, - renderValue: - (CT_ c, RendererBase r, List ast) { - return _render_ModelElement( - c.returnElement, ast, r.template, - parent: r); - }, - ), - 'returnType': Property( - getValue: (CT_ c) => c.returnType, - renderVariable: - (CT_ c, Property self, List remainingNames) { - if (remainingNames.isEmpty) { - return self.getValue(c).toString(); - } - var name = remainingNames.first; - var nextProperty = - _Renderer_ElementType.propertyMap().getValue(name); - return nextProperty.renderVariable(self.getValue(c), - nextProperty, [...remainingNames.skip(1)]); - }, - isNullValue: (CT_ c) => c.returnType == null, - renderValue: - (CT_ c, RendererBase r, List ast) { - return renderSimple(c.returnType, ast, r.template, - parent: r); - }, - ), 'typeArguments': Property( getValue: (CT_ c) => c.typeArguments, renderVariable: (CT_ c, Property self, @@ -4615,18 +4508,6 @@ class _Renderer_ElementType extends RendererBase { parent: r); }, ), - 'parameters': Property( - getValue: (CT_ c) => c.parameters, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable( - c, remainingNames, 'List'), - renderIterable: - (CT_ c, RendererBase r, List ast) { - return c.parameters.map((e) => - _render_Parameter(e, ast, r.template, parent: r)); - }, - ), 'returnedFrom': Property( getValue: (CT_ c) => c.returnedFrom, renderVariable: @@ -4658,6 +4539,18 @@ class _Renderer_ElementType extends RendererBase { return renderSimple(c.type, ast, r.template, parent: r); }, ), + 'typeArguments': Property( + getValue: (CT_ c) => c.typeArguments, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable( + c, remainingNames, 'Iterable'), + renderIterable: + (CT_ c, RendererBase r, List ast) { + return c.typeArguments.map( + (e) => renderSimple(e, ast, r.template, parent: r)); + }, + ), }); _Renderer_ElementType( @@ -6088,6 +5981,72 @@ class _Renderer_FunctionTemplateData } } +String _render_FunctionTypeElementType( + FunctionTypeElementType context, List ast, Template template, + {RendererBase parent}) { + var renderer = _Renderer_FunctionTypeElementType(context, parent, template); + renderer.renderBlock(ast); + return renderer.buffer.toString(); +} + +class _Renderer_FunctionTypeElementType + extends RendererBase { + static final Map _propertyMapCache = {}; + static Map> propertyMap< + CT_ extends FunctionTypeElementType>() => + _propertyMapCache.putIfAbsent( + CT_, + () => { + ..._Renderer_UndefinedElementType.propertyMap(), + ..._Renderer_Rendered.propertyMap(), + ..._Renderer_Callable.propertyMap(), + 'name': Property( + getValue: (CT_ c) => c.name, + renderVariable: + (CT_ c, Property self, List 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.name == null, + renderValue: + (CT_ c, RendererBase r, List ast) { + return _render_String(c.name, ast, r.template, parent: r); + }, + ), + 'typeFormals': Property( + getValue: (CT_ c) => c.typeFormals, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable( + c, remainingNames, 'List'), + renderIterable: + (CT_ c, RendererBase r, List ast) { + return c.typeFormals.map((e) => + _render_TypeParameter(e, ast, r.template, parent: r)); + }, + ), + }); + + _Renderer_FunctionTypeElementType(FunctionTypeElementType context, + RendererBase parent, Template template) + : super(context, parent, template); + + @override + Property getProperty(String key) { + if (propertyMap().containsKey(key)) { + return propertyMap()[key]; + } else { + return null; + } + } +} + String _render_FunctionTypedef( FunctionTypedef context, List ast, Template template, {RendererBase parent}) { @@ -6113,7 +6072,7 @@ class _Renderer_FunctionTypedef extends RendererBase { } var name = remainingNames.first; var nextProperty = - _Renderer_CallableElementTypeMixin.propertyMap() + _Renderer_FunctionTypeElementType.propertyMap() .getValue(name); return nextProperty.renderVariable(self.getValue(c), nextProperty, [...remainingNames.skip(1)]); @@ -6121,7 +6080,7 @@ class _Renderer_FunctionTypedef extends RendererBase { isNullValue: (CT_ c) => c.modelType == null, renderValue: (CT_ c, RendererBase r, List ast) { - return _render_CallableElementTypeMixin( + return _render_FunctionTypeElementType( c.modelType, ast, r.template, parent: r); }, @@ -8325,16 +8284,14 @@ class _Renderer_Method extends RendererBase { } var name = remainingNames.first; var nextProperty = - _Renderer_CallableElementTypeMixin.propertyMap() - .getValue(name); + _Renderer_Callable.propertyMap().getValue(name); return nextProperty.renderVariable(self.getValue(c), nextProperty, [...remainingNames.skip(1)]); }, isNullValue: (CT_ c) => c.modelType == null, renderValue: (CT_ c, RendererBase r, List ast) { - return _render_CallableElementTypeMixin( - c.modelType, ast, r.template, + return _render_Callable(c.modelType, ast, r.template, parent: r); }, ), @@ -10054,16 +10011,14 @@ class _Renderer_ModelFunctionTyped extends RendererBase { } var name = remainingNames.first; var nextProperty = - _Renderer_DefinedElementType.propertyMap() - .getValue(name); + _Renderer_Callable.propertyMap().getValue(name); return nextProperty.renderVariable(self.getValue(c), nextProperty, [...remainingNames.skip(1)]); }, isNullValue: (CT_ c) => c.modelType == null, renderValue: (CT_ c, RendererBase r, List ast) { - return _render_DefinedElementType( - c.modelType, ast, r.template, + return _render_Callable(c.modelType, ast, r.template, parent: r); }, ), @@ -11114,7 +11069,7 @@ class _Renderer_Package extends RendererBase { } } -String renderIndex(PackageTemplateData context, Template template) { +String renderError(PackageTemplateData context, Template template) { return _render_PackageTemplateData(context, template.ast, template); } @@ -11314,7 +11269,7 @@ class _Renderer_PackageTemplateData extends RendererBase { } } -String renderError(PackageTemplateData context, Template template) { +String renderIndex(PackageTemplateData context, Template template) { return _render_PackageTemplateData(context, template.ast, template); } @@ -11601,53 +11556,14 @@ String _render_ParameterizedElementType(ParameterizedElementType context, class _Renderer_ParameterizedElementType extends RendererBase { static final Map _propertyMapCache = {}; - static Map> propertyMap< - CT_ extends ParameterizedElementType>() => - _propertyMapCache.putIfAbsent( - CT_, - () => { - ..._Renderer_DefinedElementType.propertyMap(), - 'linkedName': Property( - getValue: (CT_ c) => c.linkedName, - renderVariable: - (CT_ c, Property self, List 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 r, List ast) { - return _render_String(c.linkedName, ast, r.template, - parent: r); - }, - ), - 'nameWithGenerics': Property( - getValue: (CT_ c) => c.nameWithGenerics, - renderVariable: - (CT_ c, Property self, List 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.nameWithGenerics == null, - renderValue: - (CT_ c, RendererBase r, List ast) { - return _render_String(c.nameWithGenerics, ast, r.template, - parent: r); - }, - ), - }); + static Map> + propertyMap() => + _propertyMapCache.putIfAbsent( + CT_, + () => { + ..._Renderer_DefinedElementType.propertyMap(), + ..._Renderer_Rendered.propertyMap(), + }); _Renderer_ParameterizedElementType(ParameterizedElementType context, RendererBase parent, Template template) @@ -11933,6 +11849,68 @@ class _Renderer_PropertyTemplateData } } +class _Renderer_Rendered extends RendererBase { + static final Map _propertyMapCache = {}; + static Map> propertyMap() => + _propertyMapCache.putIfAbsent( + CT_, + () => { + 'linkedName': Property( + getValue: (CT_ c) => c.linkedName, + renderVariable: + (CT_ c, Property self, List 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 r, List ast) { + return _render_String(c.linkedName, ast, r.template, + parent: r); + }, + ), + 'nameWithGenerics': Property( + getValue: (CT_ c) => c.nameWithGenerics, + renderVariable: + (CT_ c, Property self, List 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.nameWithGenerics == null, + renderValue: + (CT_ c, RendererBase r, List ast) { + return _render_String(c.nameWithGenerics, ast, r.template, + parent: r); + }, + ), + }); + + _Renderer_Rendered( + Rendered context, RendererBase parent, Template template) + : super(context, parent, template); + + @override + Property getProperty(String key) { + if (propertyMap().containsKey(key)) { + return propertyMap()[key]; + } else { + return null; + } + } +} + class _Renderer_SourceCodeMixin extends RendererBase { static final Map _propertyMapCache = {}; static Map> propertyMap< @@ -14310,6 +14288,157 @@ class _Renderer_TypedefTemplateData extends RendererBase { } } +class _Renderer_UndefinedElementType + extends RendererBase { + static final Map _propertyMapCache = {}; + static Map> propertyMap< + CT_ extends UndefinedElementType>() => + _propertyMapCache.putIfAbsent( + CT_, + () => { + ..._Renderer_ElementType.propertyMap(), + 'element': Property( + getValue: (CT_ c) => c.element, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable(c, remainingNames, 'Element'), + isNullValue: (CT_ c) => c.element == null, + renderValue: + (CT_ c, RendererBase r, List ast) { + return renderSimple(c.element, ast, r.template, parent: r); + }, + ), + 'instantiatedType': Property( + getValue: (CT_ c) => c.instantiatedType, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable(c, remainingNames, 'DartType'), + isNullValue: (CT_ c) => c.instantiatedType == null, + renderValue: + (CT_ c, RendererBase r, List ast) { + return renderSimple(c.instantiatedType, ast, r.template, + parent: r); + }, + ), + 'isPublic': Property( + getValue: (CT_ c) => c.isPublic, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable(c, remainingNames, 'bool'), + getBool: (CT_ c) => c.isPublic == true, + ), + 'linkedName': Property( + getValue: (CT_ c) => c.linkedName, + renderVariable: + (CT_ c, Property self, List 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 r, List ast) { + return _render_String(c.linkedName, ast, r.template, + parent: r); + }, + ), + 'name': Property( + getValue: (CT_ c) => c.name, + renderVariable: + (CT_ c, Property self, List 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.name == null, + renderValue: + (CT_ c, RendererBase r, List ast) { + return _render_String(c.name, ast, r.template, parent: r); + }, + ), + 'nameWithGenerics': Property( + getValue: (CT_ c) => c.nameWithGenerics, + renderVariable: + (CT_ c, Property self, List 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.nameWithGenerics == null, + renderValue: + (CT_ c, RendererBase r, List ast) { + return _render_String(c.nameWithGenerics, ast, r.template, + parent: r); + }, + ), + 'referenceChildren': Property( + getValue: (CT_ c) => c.referenceChildren, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable( + c, remainingNames, 'Map'), + isNullValue: (CT_ c) => c.referenceChildren == null, + renderValue: + (CT_ c, RendererBase r, List ast) { + return renderSimple(c.referenceChildren, ast, r.template, + parent: r); + }, + ), + 'referenceParents': Property( + getValue: (CT_ c) => c.referenceParents, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable( + c, remainingNames, 'Iterable'), + renderIterable: + (CT_ c, RendererBase r, List ast) { + return c.referenceParents.map( + (e) => renderSimple(e, ast, r.template, parent: r)); + }, + ), + 'typeArguments': Property( + getValue: (CT_ c) => c.typeArguments, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable( + c, remainingNames, 'Iterable'), + renderIterable: + (CT_ c, RendererBase r, List ast) { + return c.typeArguments.map( + (e) => renderSimple(e, ast, r.template, parent: r)); + }, + ), + }); + + _Renderer_UndefinedElementType(UndefinedElementType context, + RendererBase parent, Template template) + : super(context, parent, template); + + @override + Property getProperty(String key) { + if (propertyMap().containsKey(key)) { + return propertyMap()[key]; + } else { + return null; + } + } +} + class _Renderer_Warnable extends RendererBase { static final Map _propertyMapCache = {}; static Map> propertyMap() => diff --git a/lib/src/model/accessor.dart b/lib/src/model/accessor.dart index c8a6976a68..c8aba534ff 100644 --- a/lib/src/model/accessor.dart +++ b/lib/src/model/accessor.dart @@ -27,8 +27,8 @@ class Accessor extends ModelElement implements EnclosedElement { @override ExecutableMember get originalMember => super.originalMember; - CallableElementTypeMixin _modelType; - CallableElementTypeMixin get modelType => _modelType ??= + Callable _modelType; + Callable get modelType => _modelType ??= ElementType.from((originalMember ?? element).type, library, packageGraph); bool get isSynthetic => element.isSynthetic; diff --git a/lib/src/model/constructor.dart b/lib/src/model/constructor.dart index b07c7032cb..a572b3d699 100644 --- a/lib/src/model/constructor.dart +++ b/lib/src/model/constructor.dart @@ -79,8 +79,8 @@ class Constructor extends ModelElement @override String get kind => 'constructor'; - CallableElementTypeMixin _modelType; - CallableElementTypeMixin get modelType => + Callable _modelType; + Callable get modelType => _modelType ??= ElementType.from(element.type, library, packageGraph); String _name; diff --git a/lib/src/model/method.dart b/lib/src/model/method.dart index 2b6e38e476..a2d288a258 100644 --- a/lib/src/model/method.dart +++ b/lib/src/model/method.dart @@ -97,8 +97,8 @@ class Method extends ModelElement @override ExecutableMember get originalMember => super.originalMember; - CallableElementTypeMixin _modelType; - CallableElementTypeMixin get modelType => _modelType ??= + Callable _modelType; + Callable get modelType => _modelType ??= ElementType.from((originalMember ?? element).type, library, packageGraph); @override diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart index fb4b9ce737..cf59bf1aca 100644 --- a/lib/src/model/model_element.dart +++ b/lib/src/model/model_element.dart @@ -16,6 +16,7 @@ import 'package:analyzer/src/dart/element/member.dart' import 'package:collection/collection.dart'; import 'package:dartdoc/src/comment_references/model_comment_reference.dart'; import 'package:dartdoc/src/dartdoc_options.dart'; +import 'package:dartdoc/src/element_type.dart'; import 'package:dartdoc/src/model/annotation.dart'; import 'package:dartdoc/src/model/comment_referable.dart'; import 'package:dartdoc/src/model/feature.dart'; @@ -941,13 +942,20 @@ abstract class ModelElement extends Canonicalization } else { if (isCallable) newParameters.addAll(parameters); } + // TODO(jcollins-g): This part probably belongs in [ElementType]. while (newParameters.isNotEmpty) { recursedParameters.addAll(newParameters); newParameters.clear(); for (var p in recursedParameters) { - var l = p.modelType.parameters - .where((pm) => !recursedParameters.contains(pm)); - newParameters.addAll(l); + var parameterModelType = p.modelType; + if (parameterModelType is Callable) { + newParameters.addAll(parameterModelType.parameters + .where((pm) => !recursedParameters.contains(pm))); + } + if (parameterModelType is AliasedElementType) { + newParameters.addAll(parameterModelType.aliasedParameters + .where((pm) => !recursedParameters.contains(pm))); + } } } _allParameters = recursedParameters.toList(); diff --git a/lib/src/model/model_function.dart b/lib/src/model/model_function.dart index c323da6cf6..bd442323dd 100644 --- a/lib/src/model/model_function.dart +++ b/lib/src/model/model_function.dart @@ -88,7 +88,7 @@ class ModelFunctionTyped extends ModelElement @override FunctionTypedElement get element => super.element; - DefinedElementType _modelType; - DefinedElementType get modelType => + Callable _modelType; + Callable get modelType => _modelType ??= ElementType.from(element.type, library, packageGraph); } diff --git a/lib/src/model/typedef.dart b/lib/src/model/typedef.dart index 8f4e8527e7..ac36412d57 100644 --- a/lib/src/model/typedef.dart +++ b/lib/src/model/typedef.dart @@ -89,5 +89,5 @@ class FunctionTypedef extends Typedef { : super(element, library, packageGraph); @override - CallableElementTypeMixin get modelType => super.modelType; + FunctionTypeElementType get modelType => super.modelType; } diff --git a/lib/src/render/element_type_renderer.dart b/lib/src/render/element_type_renderer.dart index 940661e8f9..5ef50c24af 100644 --- a/lib/src/render/element_type_renderer.dart +++ b/lib/src/render/element_type_renderer.dart @@ -89,6 +89,41 @@ class ParameterizedElementTypeRendererHtml } } +class AliasedFunctionTypeElementTypeRendererHtml + extends ElementTypeRenderer { + const AliasedFunctionTypeElementTypeRendererHtml(); + + @override + String renderLinkedName(AliasedFunctionTypeElementType elementType) { + var buf = StringBuffer(); + buf.write(elementType.aliasElement.linkedName); + if (elementType.aliasArguments.isNotEmpty && + !elementType.aliasArguments.every((t) => t.name == 'dynamic')) { + buf.write(''); + buf.write('<'); + buf.writeAll(elementType.aliasArguments.map((t) => t.linkedName), + ', '); + buf.write('>'); + buf.write(''); + } + return wrapNullability(elementType, buf.toString()); + } + + @override + String renderNameWithGenerics(AliasedFunctionTypeElementType elementType) { + var buf = StringBuffer(); + buf.write(elementType.aliasElement.name); + if (elementType.aliasArguments.isNotEmpty && + !elementType.aliasArguments.every((t) => t.name == 'dynamic')) { + buf.write('<'); + buf.writeAll(elementType.aliasArguments.map((t) => t.nameWithGenerics), + ', '); + buf.write('>'); + } + return wrapNullability(elementType, buf.toString()); + } +} + class AliasedElementTypeRendererHtml extends ElementTypeRenderer { const AliasedElementTypeRendererHtml(); @@ -255,6 +290,38 @@ class AliasedElementTypeRendererMd } } +class AliasedFunctionTypeElementTypeRendererMd + extends ElementTypeRenderer { + const AliasedFunctionTypeElementTypeRendererMd(); + + @override + String renderLinkedName(AliasedFunctionTypeElementType elementType) { + var buf = StringBuffer(); + buf.write(elementType.aliasElement.linkedName); + if (elementType.aliasArguments.isNotEmpty && + !elementType.aliasArguments.every((t) => t.name == 'dynamic')) { + buf.write('<'); + buf.writeAll(elementType.aliasArguments.map((t) => t.linkedName), ', '); + buf.write('>'); + } + return wrapNullability(elementType, buf.toString()); + } + + @override + String renderNameWithGenerics(AliasedFunctionTypeElementType elementType) { + var buf = StringBuffer(); + buf.write(elementType.aliasElement.name); + if (elementType.aliasArguments.isNotEmpty && + !elementType.aliasArguments.every((t) => t.name == 'dynamic')) { + buf.write('<'); + buf.writeAll( + elementType.aliasArguments.map((t) => t.nameWithGenerics), ', '); + buf.write('>'); + } + return wrapNullability(elementType, buf.toString()); + } +} + class CallableElementTypeRendererMd extends ElementTypeRenderer { const CallableElementTypeRendererMd(); diff --git a/lib/src/render/parameter_renderer.dart b/lib/src/render/parameter_renderer.dart index f4539f6868..b1e551e758 100644 --- a/lib/src/render/parameter_renderer.dart +++ b/lib/src/render/parameter_renderer.dart @@ -183,7 +183,7 @@ abstract class ParameterRenderer { if (param.isCovariant) { buf.write(covariant('covariant') + ' '); } - if (paramModelType is CallableElementTypeMixin) { + if (paramModelType is Callable) { String returnTypeName; if (paramModelType.isTypedef) { returnTypeName = paramModelType.linkedName; @@ -208,10 +208,8 @@ abstract class ParameterRenderer { } if (!paramModelType.isTypedef && paramModelType.type is FunctionType) { buf.write('('); - buf.write(renderLinkedParams( - (paramModelType as UndefinedElementType).parameters, - showMetadata: showMetadata, - showNames: showNames)); + buf.write(renderLinkedParams(paramModelType.parameters, + showMetadata: showMetadata, showNames: showNames)); buf.write(')'); buf.write(paramModelType.nullabilitySuffix); } diff --git a/lib/src/render/renderer_factory.dart b/lib/src/render/renderer_factory.dart index 9ecbc1157b..9bc6d3ba11 100644 --- a/lib/src/render/renderer_factory.dart +++ b/lib/src/render/renderer_factory.dart @@ -51,6 +51,9 @@ abstract class RendererFactory { ElementTypeRenderer get aliasedElementTypeRenderer; + ElementTypeRenderer + get aliasedFunctionTypeElementTypeRenderer; + ElementTypeRenderer get callableElementTypeRenderer; EnumFieldRenderer get enumFieldRenderer; @@ -129,6 +132,11 @@ class HtmlRenderFactory extends RendererFactory { @override FeatureRenderer get featureRenderer => const FeatureRendererHtml(); + + @override + ElementTypeRenderer + get aliasedFunctionTypeElementTypeRenderer => + const AliasedFunctionTypeElementTypeRendererHtml(); } class MdRenderFactory extends RendererFactory { @@ -193,4 +201,9 @@ class MdRenderFactory extends RendererFactory { @override FeatureRenderer get featureRenderer => const FeatureRendererMd(); + + @override + ElementTypeRenderer + get aliasedFunctionTypeElementTypeRenderer => + const AliasedFunctionTypeElementTypeRendererMd(); } diff --git a/test/end2end/model_test.dart b/test/end2end/model_test.dart index 5ecbf4d714..89cd9bf0d3 100644 --- a/test/end2end/model_test.dart +++ b/test/end2end/model_test.dart @@ -120,7 +120,7 @@ void main() { orderedEquals(genericParameters)); } - void expectAliasedTypeName(AliasedElementType n, expected) { + void expectAliasedTypeName(Aliased n, expected) { expect(n.aliasElement.name, expected); } @@ -205,13 +205,13 @@ void main() { equals('?')); }); - test('implied Future types have correct nullability', () { - expect(oddAsyncFunction.modelType.returnType.name, equals('Future')); + test('old implied Future types have correct nullability', () { + expect(oddAsyncFunction.modelType.returnType.name, equals('dynamic')); expect( - oddAsyncFunction.modelType.returnType.nullabilitySuffix, equals('?')); - expect(anotherOddFunction.modelType.returnType.name, equals('Future')); + oddAsyncFunction.modelType.returnType.nullabilitySuffix, equals('')); + expect(anotherOddFunction.modelType.returnType.name, equals('dynamic')); expect(anotherOddFunction.modelType.returnType.nullabilitySuffix, - equals('?')); + equals('')); }); test('isNullSafety is set correctly for libraries', () { @@ -2710,7 +2710,7 @@ void main() { test('async function', () { expect(thisIsAsync.isAsynchronous, isTrue); - expect(thisIsAsync.modelType.returnType.linkedName, equals('Future')); + expect(thisIsAsync.modelType.returnType.linkedName, equals('dynamic')); expect( thisIsAsync.documentation, equals( @@ -3085,10 +3085,7 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans, test('parameter is a function', () { var functionArgParam = m4.parameters[1]; - expect( - (functionArgParam.modelType as CallableElementTypeMixin) - .returnType - .linkedName, + expect((functionArgParam.modelType as Callable).returnType.linkedName, 'String'); }); @@ -4207,7 +4204,7 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans, }); test('async return type', () { - expect(asyncM.modelType.returnType.linkedName, 'Future'); + expect(asyncM.modelType.returnType.linkedName, 'dynamic'); }); test('param with generics', () { diff --git a/tool/mustachio/builder.dart b/tool/mustachio/builder.dart index c4108ff272..85ed810b8e 100644 --- a/tool/mustachio/builder.dart +++ b/tool/mustachio/builder.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/element/member.dart'; import 'package:build/build.dart'; import 'package:dartdoc/src/mustachio/annotations.dart'; @@ -131,7 +132,7 @@ class _RendererGatherer { if (contextField.isNull) { throw StateError('@Renderer context must not be null'); } - var contextFieldType = contextField.type; + var contextFieldType = contextField.type as InterfaceType; assert(contextFieldType.typeArguments.length == 1); var contextType = contextFieldType.typeArguments.single;