From daa4d48b59aeb35dbb500f898318d6fafc26fcfa Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 24 Oct 2023 12:26:17 -0700 Subject: [PATCH] Extension type constructors --- .../templates.aot_renderers_for_html.dart | 42 ++++++---- .../templates.aot_renderers_for_md.dart | 35 ++++---- .../templates.runtime_renderers.dart | 45 +++++----- lib/src/model/extension_type.dart | 8 +- lib/src/model/model_element.dart | 16 ++-- lib/templates/html/extension_type.html | 6 +- lib/templates/md/extension_type.md | 4 +- test/extension_types_test.dart | 18 ++++ test/templates/extension_type_test.dart | 82 +++++++++---------- 9 files changed, 146 insertions(+), 110 deletions(-) diff --git a/lib/src/generator/templates.aot_renderers_for_html.dart b/lib/src/generator/templates.aot_renderers_for_html.dart index f1201a7ef7..4c9c023cde 100644 --- a/lib/src/generator/templates.aot_renderers_for_html.dart +++ b/lib/src/generator/templates.aot_renderers_for_html.dart @@ -852,7 +852,7 @@ String renderExtensionType(
on
    '''); - var context3 = context2.extendedType; + var context3 = context2.representationType; buffer.writeln(); buffer.write('''
  • '''); @@ -868,7 +868,10 @@ String renderExtensionType( buffer.writeln(); buffer.write(''' -'''); + + '''); + buffer.write(_renderExtensionType_partial_constructors_6(context2)); + buffer.writeln(); if (context2.hasPublicInstanceFields == true) { buffer.writeln(); buffer.write(''' @@ -879,7 +882,7 @@ String renderExtensionType( var context4 = context2.publicInstanceFieldsSorted; for (var context5 in context4) { buffer.write('\n '); - buffer.write(_renderExtensionType_partial_property_6(context5)); + buffer.write(_renderExtensionType_partial_property_7(context5)); } buffer.writeln(); buffer.write(''' @@ -887,15 +890,15 @@ String renderExtensionType( '''); } buffer.write('\n\n '); - buffer.write(_renderExtensionType_partial_instance_methods_7(context2)); + buffer.write(_renderExtensionType_partial_instance_methods_8(context2)); buffer.write('\n '); - buffer.write(_renderExtensionType_partial_instance_operators_8(context2)); + buffer.write(_renderExtensionType_partial_instance_operators_9(context2)); buffer.write('\n '); - buffer.write(_renderExtensionType_partial_static_properties_9(context2)); + buffer.write(_renderExtensionType_partial_static_properties_10(context2)); buffer.write('\n '); - buffer.write(_renderExtensionType_partial_static_methods_10(context2)); + buffer.write(_renderExtensionType_partial_static_methods_11(context2)); buffer.write('\n '); - buffer.write(_renderExtensionType_partial_static_constants_11(context2)); + buffer.write(_renderExtensionType_partial_static_constants_12(context2)); buffer.writeln(); buffer.write(''' @@ -903,7 +906,7 @@ String renderExtensionType( '''); - buffer.write(_renderExtensionType_partial_footer_13(context0)); + buffer.write(_renderExtensionType_partial_footer_14(context0)); buffer.writeln(); buffer.writeln(); @@ -2864,33 +2867,36 @@ String _renderExtensionType_partial_container_annotations_5( ExtensionType context1) => _deduplicated_lib_templates_html__container_annotations_html(context1); -String _renderExtensionType_partial_property_6(Field context2) => +String _renderExtensionType_partial_constructors_6(ExtensionType context1) => + _deduplicated_lib_templates_html__constructors_html(context1); + +String _renderExtensionType_partial_property_7(Field context2) => _deduplicated_lib_templates_html__property_html(context2); -String _renderExtensionType_partial_instance_methods_7( +String _renderExtensionType_partial_instance_methods_8( ExtensionType context1) => _deduplicated_lib_templates_html__instance_methods_html(context1); -String _renderExtensionType_partial_instance_operators_8( +String _renderExtensionType_partial_instance_operators_9( ExtensionType context1) => _deduplicated_lib_templates_html__instance_operators_html(context1); -String _renderExtensionType_partial_static_properties_9( +String _renderExtensionType_partial_static_properties_10( ExtensionType context1) => _deduplicated_lib_templates_html__static_properties_html(context1); -String _renderExtensionType_partial_static_methods_10(ExtensionType context1) => +String _renderExtensionType_partial_static_methods_11(ExtensionType context1) => _deduplicated_lib_templates_html__static_methods_html(context1); -String _renderExtensionType_partial_static_constants_11( +String _renderExtensionType_partial_static_constants_12( ExtensionType context1) => _deduplicated_lib_templates_html__static_constants_html(context1); -String _renderExtensionType_partial_search_sidebar_12( +String _renderExtensionType_partial_search_sidebar_13( ExtensionTypeTemplateData context0) => _deduplicated_lib_templates_html__search_sidebar_html(context0); -String _renderExtensionType_partial_footer_13( +String _renderExtensionType_partial_footer_14( ExtensionTypeTemplateData context0) => _deduplicated_lib_templates_html__footer_html(context0); diff --git a/lib/src/generator/templates.aot_renderers_for_md.dart b/lib/src/generator/templates.aot_renderers_for_md.dart index 35f20b4ffa..c97ab74eff 100644 --- a/lib/src/generator/templates.aot_renderers_for_md.dart +++ b/lib/src/generator/templates.aot_renderers_for_md.dart @@ -491,7 +491,7 @@ String renderExtensionType( buffer.writeln(); buffer.write(''' on '''); - var context2 = context1.extendedType; + var context2 = context1.representationType; buffer.write(context2.linkedName); buffer.write('\n\n'); buffer.write(_renderExtensionType_partial_source_link_1(context1)); @@ -505,6 +505,8 @@ on '''); buffer.write(_renderExtensionType_partial_documentation_4(context3)); buffer.write('\n\n'); buffer.write(_renderExtensionType_partial_annotations_5(context3)); + buffer.write('\n\n'); + buffer.write(_renderExtensionType_partial_constructors_6(context3)); buffer.writeln(); if (context3.hasPublicInstanceFields == true) { buffer.writeln(); @@ -514,25 +516,25 @@ on '''); var context4 = context3.publicInstanceFieldsSorted; for (var context5 in context4) { buffer.writeln(); - buffer.write(_renderExtensionType_partial_property_6(context5)); + buffer.write(_renderExtensionType_partial_property_7(context5)); buffer.writeln(); } } buffer.write('\n\n'); - buffer.write(_renderExtensionType_partial_instance_methods_7(context3)); + buffer.write(_renderExtensionType_partial_instance_methods_8(context3)); buffer.write('\n\n'); - buffer.write(_renderExtensionType_partial_instance_operators_8(context3)); + buffer.write(_renderExtensionType_partial_instance_operators_9(context3)); buffer.write('\n\n'); - buffer.write(_renderExtensionType_partial_static_properties_9(context3)); + buffer.write(_renderExtensionType_partial_static_properties_10(context3)); buffer.write('\n\n'); - buffer.write(_renderExtensionType_partial_static_methods_10(context3)); + buffer.write(_renderExtensionType_partial_static_methods_11(context3)); buffer.write('\n\n'); - buffer.write(_renderExtensionType_partial_static_constants_11(context3)); + buffer.write(_renderExtensionType_partial_static_constants_12(context3)); buffer.writeln(); buffer.write(''' {{ /extension }}'''); buffer.write('\n\n'); - buffer.write(_renderExtensionType_partial_footer_12(context0)); + buffer.write(_renderExtensionType_partial_footer_13(context0)); buffer.writeln(); buffer.writeln(); @@ -1434,29 +1436,32 @@ String _renderExtensionType_partial_documentation_4(ExtensionType context1) => String _renderExtensionType_partial_annotations_5(ExtensionType context1) => _deduplicated_lib_templates_md__annotations_md(context1); -String _renderExtensionType_partial_property_6(Field context2) => +String _renderExtensionType_partial_constructors_6(ExtensionType context1) => + _deduplicated_lib_templates_md__constructors_md(context1); + +String _renderExtensionType_partial_property_7(Field context2) => _deduplicated_lib_templates_md__property_md(context2); -String _renderExtensionType_partial_instance_methods_7( +String _renderExtensionType_partial_instance_methods_8( ExtensionType context1) => _deduplicated_lib_templates_md__instance_methods_md(context1); -String _renderExtensionType_partial_instance_operators_8( +String _renderExtensionType_partial_instance_operators_9( ExtensionType context1) => _deduplicated_lib_templates_md__instance_operators_md(context1); -String _renderExtensionType_partial_static_properties_9( +String _renderExtensionType_partial_static_properties_10( ExtensionType context1) => _deduplicated_lib_templates_md__static_properties_md(context1); -String _renderExtensionType_partial_static_methods_10(ExtensionType context1) => +String _renderExtensionType_partial_static_methods_11(ExtensionType context1) => _deduplicated_lib_templates_md__static_methods_md(context1); -String _renderExtensionType_partial_static_constants_11( +String _renderExtensionType_partial_static_constants_12( ExtensionType context1) => _deduplicated_lib_templates_md__static_constants_md(context1); -String _renderExtensionType_partial_footer_12( +String _renderExtensionType_partial_footer_13( ExtensionTypeTemplateData context0) => _deduplicated_lib_templates_md__footer_md(context0); diff --git a/lib/src/generator/templates.runtime_renderers.dart b/lib/src/generator/templates.runtime_renderers.dart index a7dca3ee09..2fb18c59fb 100644 --- a/lib/src/generator/templates.runtime_renderers.dart +++ b/lib/src/generator/templates.runtime_renderers.dart @@ -5498,28 +5498,6 @@ class _Renderer_ExtensionType extends RendererBase { parent: r); }, ), - 'extendedType': Property( - getValue: (CT_ c) => c.extendedType, - 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) as ElementType, - nextProperty, - [...remainingNames.skip(1)]); - }, - isNullValue: (CT_ c) => false, - renderValue: (CT_ c, RendererBase r, - List ast, StringSink sink) { - _render_ElementType(c.extendedType, ast, r.template, sink, - parent: r); - }, - ), 'filePath': Property( getValue: (CT_ c) => c.filePath, renderVariable: @@ -5661,6 +5639,29 @@ class _Renderer_ExtensionType extends RendererBase { parent: r); }, ), + 'representationType': Property( + getValue: (CT_ c) => c.representationType, + 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) as ElementType, + nextProperty, + [...remainingNames.skip(1)]); + }, + isNullValue: (CT_ c) => false, + renderValue: (CT_ c, RendererBase r, + List ast, StringSink sink) { + _render_ElementType( + c.representationType, ast, r.template, sink, + parent: r); + }, + ), 'sidebarPath': Property( getValue: (CT_ c) => c.sidebarPath, renderVariable: diff --git a/lib/src/model/extension_type.dart b/lib/src/model/extension_type.dart index 6f8c10cc2f..17c8fcd3cc 100644 --- a/lib/src/model/extension_type.dart +++ b/lib/src/model/extension_type.dart @@ -12,7 +12,7 @@ class ExtensionType extends InheritingContainer with Constructable { @override final ExtensionTypeElement element; - late final ElementType extendedType = + late final ElementType representationType = modelBuilder.typeFrom(element.typeErasure, library); ExtensionType(this.element, super.library, super.packageGraph); @@ -56,7 +56,7 @@ class ExtensionType extends InheritingContainer with Constructable { @override late final List allModelElements = [ ...super.allModelElements, - ...typeParameters, + ...constructors, ]; @override @@ -86,8 +86,8 @@ class ExtensionType extends InheritingContainer with Constructable { @override Map get referenceChildren { return _referenceChildren ??= { - ...extendedType.referenceChildren, - // Override `extendedType` entries with local items. + ...representationType.referenceChildren, + // Override `representationType` entries with local items. ...super.referenceChildren, }; } diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart index b3840db1d8..da0f50248f 100644 --- a/lib/src/model/model_element.dart +++ b/lib/src/model/model_element.dart @@ -459,13 +459,15 @@ abstract class ModelElement extends Canonicalization // The canonical ModelElement for this ModelElement, // or null if there isn't one. late final ModelElement? canonicalModelElement = () { - Container? preferredClass; - // TODO(srawlins): Add mixin. - if (enclosingElement is Class || - enclosingElement is Enum || - enclosingElement is Extension) { - preferredClass = enclosingElement as Container?; - } + final enclosingElement = this.enclosingElement; + var preferredClass = switch (enclosingElement) { + // TODO(srawlins): Add mixin. + Class() => enclosingElement, + Enum() => enclosingElement, + Extension() => enclosingElement, + ExtensionType() => enclosingElement, + _ => null, + }; return packageGraph.findCanonicalModelElementFor(element, preferredClass: preferredClass); }(); diff --git a/lib/templates/html/extension_type.html b/lib/templates/html/extension_type.html index e5fd402892..ec7749f558 100644 --- a/lib/templates/html/extension_type.html +++ b/lib/templates/html/extension_type.html @@ -16,15 +16,17 @@
    on
      - {{ #extendedType }} + {{ #representationType }}
    • {{{ linkedName }}}
    • - {{ /extendedType }} + {{ /representationType }}
    {{ >container_annotations }} + {{ >constructors }} + {{ #hasPublicInstanceFields }}

    Properties

    diff --git a/lib/templates/md/extension_type.md b/lib/templates/md/extension_type.md index 306c99123f..7999463527 100644 --- a/lib/templates/md/extension_type.md +++ b/lib/templates/md/extension_type.md @@ -2,7 +2,7 @@ {{ #self }} # {{{ nameWithGenerics }}} {{ kind }} -on {{ #extendedType }}{{{ linkedName }}}{{ /extendedType }} +on {{ #representationType }}{{{ linkedName }}}{{ /representationType }} {{ >source_link }} @@ -15,6 +15,8 @@ on {{ #extendedType }}{{{ linkedName }}}{{ /extendedType }} {{ >annotations }} +{{ >constructors }} + {{ #hasPublicInstanceFields }} ## Properties diff --git a/test/extension_types_test.dart b/test/extension_types_test.dart index a35324c7bb..769726e2a9 100644 --- a/test/extension_types_test.dart +++ b/test/extension_types_test.dart @@ -85,6 +85,24 @@ class C {} ); } + @FailingTest(reason: 'Not implemented yet') + void test_referenceToExtensionTypeConstructor() async { + var library = await bootPackageWithLibrary(''' +extension type ET(int it) { + ET.named(int it); +} + +/// Doc referring to [ET.new] and [Et.named]. +class C {} +'''); + + expect( + library.classes.named('C').documentationAsHtml, + '

    Doc referring to ' + 'ET.named.

    ', + ); + } + void test_referenceToExtensionTypeMember() async { var library = await bootPackageWithLibrary(''' extension type ET(int it) { diff --git a/test/templates/extension_type_test.dart b/test/templates/extension_type_test.dart index bfd9280c26..be0a6cca62 100644 --- a/test/templates/extension_type_test.dart +++ b/test/templates/extension_type_test.dart @@ -71,7 +71,10 @@ analyzer: ''', libFiles: [ d.file('lib.dart', ''' -extension type MyIterable(Iterable e) { +extension type FooET(Foo e) { + /// A named constructor. + MyIterable.named(Foo e); + /// An instance method. void m1() {} @@ -94,14 +97,7 @@ extension type MyIterable(Iterable e) { static void set gs1(int value) {} } -extension type MyListQueue(ListQueue e) implements Iterable, Queue { - void m2() {} -} - -extension type MyListOfInt(List e) - implements MyIterable, Iterable { - void m3() {} -} +class Foo {} '''), ], dartdocOptions: ''' @@ -115,13 +111,13 @@ dartdoc: await writeDartdocResources(resourceProvider); await (await buildDartdoc()).generateDocs(); eLines = resourceProvider - .getFile(path.join( - packagePath, 'doc', 'lib', 'MyIterable-extension-type.html')) + .getFile( + path.join(packagePath, 'doc', 'lib', 'FooET-extension-type.html')) .readAsStringSync() .split('\n'); eRightSidebarLines = resourceProvider - .getFile(path.join(packagePath, 'doc', 'lib', - 'MyIterable-extension-type-sidebar.html')) + .getFile(path.join( + packagePath, 'doc', 'lib', 'FooET-extension-type-sidebar.html')) .readAsStringSync() .split('\n'); }); @@ -129,30 +125,35 @@ dartdoc: test('page contains extension name with generics', () async { eLines.expectMainContentContainsAllInOrder([ matches( - 'MyIterable<' + 'FooET<' 'E>', ) ]); }); - test('page contains extended type', - // TODO(srawlins): Implement. - skip: true, () async { - expect( - eLines, - containsAllInOrder([ - matches('
    on
    '), - matches('Iterable' - '<' - 'E>'), - ]), - ); + test('page contains extended type', () async { + eLines.expectMainContentContainsAllInOrder([ + matches('
    on
    '), + matches('Foo' + '<' + 'E>'), + ]); + }); + + test('page contains constructors', () async { + eLines.expectMainContentContainsAllInOrder([ + matches('

    Constructors

    '), + matches('FooET'), + matches('' + 'FooET.named'), + matches('A named constructor.'), + ]); }); test('page contains static methods', () async { eLines.expectMainContentContainsAllInOrder([ matches('

    Static Methods

    '), - matches('s1'), + matches('s1'), matches('A static method.'), ]); }); @@ -160,7 +161,7 @@ dartdoc: test('page contains static fields', () async { eLines.expectMainContentContainsAllInOrder([ matches('

    Static Properties

    '), - matches('sf1'), + matches('sf1'), matches('A static field.'), ]); }); @@ -168,7 +169,7 @@ dartdoc: test('page contains static getter/setter pairs', () async { eLines.expectMainContentContainsAllInOrder([ matches('

    Static Properties

    '), - matches('gs1'), + matches('gs1'), matches('A static getter.'), ]); }); @@ -180,7 +181,7 @@ dartdoc: () async { eLines.expectMainContentContainsAllInOrder([ matches('

    Constants

    '), - matches('c1'), + matches('c1'), matches('A constant.'), ]); }, @@ -189,8 +190,7 @@ dartdoc: test('page contains instance operators', () async { eLines.expectMainContentContainsAllInOrder([ matches('

    Operators

    '), - matches( - 'operator >'), + matches('operator >'), matches('An operator.'), ]); }); @@ -200,10 +200,10 @@ dartdoc: eRightSidebarLines, containsAllInOrder([ matches( - '' + '' 'Methods', ), - matches('m1'), + matches('m1'), ]), ); }); @@ -213,11 +213,11 @@ dartdoc: eRightSidebarLines, containsAllInOrder([ matches( - '' + '' 'Operators', ), matches( - 'operator >', + 'operator >', ), ]), ); @@ -228,9 +228,9 @@ dartdoc: eRightSidebarLines, containsAllInOrder([ matches( - 'Static properties'), - matches('gs1'), - matches('sf1'), + 'Static properties'), + matches('gs1'), + matches('sf1'), ]), ); }); @@ -240,8 +240,8 @@ dartdoc: eRightSidebarLines, containsAllInOrder([ matches( - 'Static methods'), - matches('s1'), + 'Static methods'), + matches('s1'), ]), ); });