From 6e9b8235bea9d10fe5cca0bd29e43006a2203ce2 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 26 Oct 2023 10:42:22 -0700 Subject: [PATCH] Display extension type super interfaces --- .../templates.aot_renderers_for_html.dart | 71 +++++++--- .../templates.runtime_renderers.dart | 20 +++ lib/src/model/extension_type.dart | 19 +++ lib/templates/html/extension_type.html | 1 + test/templates/extension_type_test.dart | 124 +++++++++++------- 5 files changed, 170 insertions(+), 65 deletions(-) diff --git a/lib/src/generator/templates.aot_renderers_for_html.dart b/lib/src/generator/templates.aot_renderers_for_html.dart index 4c9c023cde..96cd48855a 100644 --- a/lib/src/generator/templates.aot_renderers_for_html.dart +++ b/lib/src/generator/templates.aot_renderers_for_html.dart @@ -862,15 +862,19 @@ String renderExtensionType( buffer.write(''' + '''); + buffer.write(_renderExtensionType_partial_interfaces_5(context2)); + buffer.writeln(); + buffer.write(''' '''); - buffer.write(_renderExtensionType_partial_container_annotations_5(context2)); + buffer.write(_renderExtensionType_partial_container_annotations_6(context2)); buffer.writeln(); buffer.write(''' '''); - buffer.write(_renderExtensionType_partial_constructors_6(context2)); + buffer.write(_renderExtensionType_partial_constructors_7(context2)); buffer.writeln(); if (context2.hasPublicInstanceFields == true) { buffer.writeln(); @@ -882,7 +886,7 @@ String renderExtensionType( var context4 = context2.publicInstanceFieldsSorted; for (var context5 in context4) { buffer.write('\n '); - buffer.write(_renderExtensionType_partial_property_7(context5)); + buffer.write(_renderExtensionType_partial_property_8(context5)); } buffer.writeln(); buffer.write(''' @@ -890,15 +894,15 @@ String renderExtensionType( '''); } buffer.write('\n\n '); - buffer.write(_renderExtensionType_partial_instance_methods_8(context2)); + buffer.write(_renderExtensionType_partial_instance_methods_9(context2)); buffer.write('\n '); - buffer.write(_renderExtensionType_partial_instance_operators_9(context2)); + buffer.write(_renderExtensionType_partial_instance_operators_10(context2)); buffer.write('\n '); - buffer.write(_renderExtensionType_partial_static_properties_10(context2)); + buffer.write(_renderExtensionType_partial_static_properties_11(context2)); buffer.write('\n '); - buffer.write(_renderExtensionType_partial_static_methods_11(context2)); + buffer.write(_renderExtensionType_partial_static_methods_12(context2)); buffer.write('\n '); - buffer.write(_renderExtensionType_partial_static_constants_12(context2)); + buffer.write(_renderExtensionType_partial_static_constants_13(context2)); buffer.writeln(); buffer.write(''' @@ -906,7 +910,7 @@ String renderExtensionType( '''); - buffer.write(_renderExtensionType_partial_footer_14(context0)); + buffer.write(_renderExtensionType_partial_footer_15(context0)); buffer.writeln(); buffer.writeln(); @@ -2863,40 +2867,67 @@ String _renderExtensionType_partial_categorization_3(ExtensionType context1) => String _renderExtensionType_partial_documentation_4(ExtensionType context1) => _deduplicated_lib_templates_html__documentation_html(context1); -String _renderExtensionType_partial_container_annotations_5( +String _renderExtensionType_partial_interfaces_5(ExtensionType context1) { + final buffer = StringBuffer(); + if (context1.hasPublicInterfaces == true) { + buffer.writeln(); + buffer.write(''' +
Implemented types
+
+
    '''); + var context2 = context1.publicInterfaces; + for (var context3 in context2) { + buffer.writeln(); + buffer.write(''' +
  • '''); + buffer.write(context3.linkedName); + buffer.write('''
  • '''); + } + buffer.writeln(); + buffer.write(''' +
+
'''); + } + + return buffer.toString(); +} + +String _renderExtensionType_partial_container_annotations_6( ExtensionType context1) => _deduplicated_lib_templates_html__container_annotations_html(context1); -String _renderExtensionType_partial_constructors_6(ExtensionType context1) => +String _renderExtensionType_partial_constructors_7(ExtensionType context1) => _deduplicated_lib_templates_html__constructors_html(context1); -String _renderExtensionType_partial_property_7(Field context2) => +String _renderExtensionType_partial_property_8(Field context2) => _deduplicated_lib_templates_html__property_html(context2); -String _renderExtensionType_partial_instance_methods_8( +String _renderExtensionType_partial_instance_methods_9( ExtensionType context1) => _deduplicated_lib_templates_html__instance_methods_html(context1); -String _renderExtensionType_partial_instance_operators_9( +String _renderExtensionType_partial_instance_operators_10( ExtensionType context1) => _deduplicated_lib_templates_html__instance_operators_html(context1); -String _renderExtensionType_partial_static_properties_10( +String _renderExtensionType_partial_static_properties_11( ExtensionType context1) => _deduplicated_lib_templates_html__static_properties_html(context1); -String _renderExtensionType_partial_static_methods_11(ExtensionType context1) => +String _renderExtensionType_partial_static_methods_12(ExtensionType context1) => _deduplicated_lib_templates_html__static_methods_html(context1); -String _renderExtensionType_partial_static_constants_12( +String _renderExtensionType_partial_static_constants_13( ExtensionType context1) => _deduplicated_lib_templates_html__static_constants_html(context1); -String _renderExtensionType_partial_search_sidebar_13( +String _renderExtensionType_partial_search_sidebar_14( ExtensionTypeTemplateData context0) => _deduplicated_lib_templates_html__search_sidebar_html(context0); -String _renderExtensionType_partial_footer_14( +String _renderExtensionType_partial_footer_15( ExtensionTypeTemplateData context0) => _deduplicated_lib_templates_html__footer_html(context0); diff --git a/lib/src/generator/templates.runtime_renderers.dart b/lib/src/generator/templates.runtime_renderers.dart index 38897d33a8..0b4268ee5b 100644 --- a/lib/src/generator/templates.runtime_renderers.dart +++ b/lib/src/generator/templates.runtime_renderers.dart @@ -5508,6 +5508,13 @@ class _Renderer_ExtensionType extends RendererBase { parent: r); }, ), + 'hasPublicInterfaces': Property( + getValue: (CT_ c) => c.hasPublicInterfaces, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable(c, remainingNames, 'bool'), + getBool: (CT_ c) => c.hasPublicInterfaces == true, + ), 'inheritanceChain': Property( getValue: (CT_ c) => c.inheritanceChain, renderVariable: (CT_ c, Property self, @@ -5592,6 +5599,19 @@ class _Renderer_ExtensionType extends RendererBase { parent: r, getters: _invisibleGetters['Kind']!); }, ), + 'publicInterfaces': Property( + getValue: (CT_ c) => c.publicInterfaces, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable( + c, remainingNames, 'List'), + renderIterable: (CT_ c, RendererBase r, + List ast, StringSink sink) { + return c.publicInterfaces.map((e) => + _render_DefinedElementType(e, ast, r.template, sink, + parent: r)); + }, + ), 'referenceChildren': Property( getValue: (CT_ c) => c.referenceChildren, renderVariable: (CT_ c, Property self, diff --git a/lib/src/model/extension_type.dart b/lib/src/model/extension_type.dart index 17c8fcd3cc..1f6566b537 100644 --- a/lib/src/model/extension_type.dart +++ b/lib/src/model/extension_type.dart @@ -38,6 +38,25 @@ class ExtensionType extends InheritingContainer with Constructable { @override bool get isSealed => false; + bool get hasPublicInterfaces => publicInterfaces.isNotEmpty; + + @override + List get publicInterfaces { + var interfaces = []; + for (var interface in element.interfaces) { + var elementType = + modelBuilder.typeFrom(interface, library) as DefinedElementType; + + if (elementType.modelElement.canonicalModelElement != null) { + interfaces.add(elementType); + continue; + } + + // TODO(srawlins): Work through intermediate, private, interfaces. + } + return interfaces; + } + @override late final List declaredFields = element.fields.map((field) { Accessor? getter, setter; diff --git a/lib/templates/html/extension_type.html b/lib/templates/html/extension_type.html index ec7749f558..f2ef2e214a 100644 --- a/lib/templates/html/extension_type.html +++ b/lib/templates/html/extension_type.html @@ -21,6 +21,7 @@ {{ /representationType }} + {{ >interfaces }} {{ >container_annotations }} diff --git a/test/templates/extension_type_test.dart b/test/templates/extension_type_test.dart index be0a6cca62..b748b2a219 100644 --- a/test/templates/extension_type_test.dart +++ b/test/templates/extension_type_test.dart @@ -20,8 +20,10 @@ void main() async { late MemoryResourceProvider resourceProvider; late PackageMetaProvider packageMetaProvider; late DartdocGeneratorOptionContext context; - late List eLines; - late List eRightSidebarLines; + late List oneLines; + late List oneSidebarLines; + late List twoLines; + late List threeLines; Future createPackageBuilder() async { context = await generatorContextFromArgv([ @@ -71,7 +73,15 @@ analyzer: ''', libFiles: [ d.file('lib.dart', ''' -extension type FooET(Foo e) { +class Base1 {} + +class Base2 {} + +class Foo extends Base1, Base2 {} + +class FooSub extends Foo {} + +extension type One(Foo e) { /// A named constructor. MyIterable.named(Foo e); @@ -97,7 +107,9 @@ extension type FooET(Foo e) { static void set gs1(int value) {} } -class Foo {} +extension type TwoWithBase(Foo it) implements Base1, Base2 {} + +extension type ThreeWithOne(FooSub it) implements One {} '''), ], dartdocOptions: ''' @@ -110,29 +122,27 @@ dartdoc: ); await writeDartdocResources(resourceProvider); await (await buildDartdoc()).generateDocs(); - eLines = resourceProvider - .getFile( - path.join(packagePath, 'doc', 'lib', 'FooET-extension-type.html')) - .readAsStringSync() - .split('\n'); - eRightSidebarLines = resourceProvider - .getFile(path.join( - packagePath, 'doc', 'lib', 'FooET-extension-type-sidebar.html')) - .readAsStringSync() - .split('\n'); + oneLines = resourceProvider + .readLines([packagePath, 'doc', 'lib', 'One-extension-type.html']); + oneSidebarLines = resourceProvider.readLines( + [packagePath, 'doc', 'lib', 'One-extension-type-sidebar.html']); + twoLines = resourceProvider.readLines( + [packagePath, 'doc', 'lib', 'TwoWithBase-extension-type.html']); + threeLines = resourceProvider.readLines( + [packagePath, 'doc', 'lib', 'ThreeWithOne-extension-type.html']); }); test('page contains extension name with generics', () async { - eLines.expectMainContentContainsAllInOrder([ + oneLines.expectMainContentContainsAllInOrder([ matches( - 'FooET<' + 'One<' 'E>', ) ]); }); - test('page contains extended type', () async { - eLines.expectMainContentContainsAllInOrder([ + test('page contains representation type', () async { + oneLines.expectMainContentContainsAllInOrder([ matches('
on
'), matches('Foo' '<' @@ -140,36 +150,55 @@ dartdoc: ]); }); + test('page contains class interfaces', () async { + twoLines.expectMainContentContainsAllInOrder([ + matches('
Implemented types
'), + matches('Base1' + '<' + 'E>'), + matches('Base2'), + ]); + }); + + test('page contains extension type interfaces', () async { + threeLines.expectMainContentContainsAllInOrder([ + matches('
Implemented types
'), + matches('One' + '<' + 'int>'), + ]); + }); + test('page contains constructors', () async { - eLines.expectMainContentContainsAllInOrder([ + oneLines.expectMainContentContainsAllInOrder([ matches('

Constructors

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

Static Methods

'), - matches('s1'), + matches('s1'), matches('A static method.'), ]); }); test('page contains static fields', () async { - eLines.expectMainContentContainsAllInOrder([ + oneLines.expectMainContentContainsAllInOrder([ matches('

Static Properties

'), - matches('sf1'), + matches('sf1'), matches('A static field.'), ]); }); test('page contains static getter/setter pairs', () async { - eLines.expectMainContentContainsAllInOrder([ + oneLines.expectMainContentContainsAllInOrder([ matches('

Static Properties

'), - matches('gs1'), + matches('gs1'), matches('A static getter.'), ]); }); @@ -179,45 +208,45 @@ dartdoc: // TODO(srawlins): Implement. skip: true, () async { - eLines.expectMainContentContainsAllInOrder([ + oneLines.expectMainContentContainsAllInOrder([ matches('

Constants

'), - matches('c1'), + matches('c1'), matches('A constant.'), ]); }, ); test('page contains instance operators', () async { - eLines.expectMainContentContainsAllInOrder([ + oneLines.expectMainContentContainsAllInOrder([ matches('

Operators

'), - matches('operator >'), + matches('operator >'), matches('An operator.'), ]); }); test('sidebar contains methods', () async { expect( - eRightSidebarLines, + oneSidebarLines, containsAllInOrder([ matches( - '' + '' 'Methods', ), - matches('m1'), + matches('m1'), ]), ); }); test('sidebar contains operators', () async { expect( - eRightSidebarLines, + oneSidebarLines, containsAllInOrder([ matches( - '' + '' 'Operators', ), matches( - 'operator >', + 'operator >', ), ]), ); @@ -225,25 +254,30 @@ dartdoc: test('sidebar contains static properties', () async { expect( - eRightSidebarLines, + oneSidebarLines, containsAllInOrder([ matches( - 'Static properties'), - matches('gs1'), - matches('sf1'), + 'Static properties'), + matches('gs1'), + matches('sf1'), ]), ); }); test('sidebar contains static methods', () async { expect( - eRightSidebarLines, + oneSidebarLines, containsAllInOrder([ matches( - 'Static methods'), - matches('s1'), + 'Static methods'), + matches('s1'), ]), ); }); }); } + +extension on MemoryResourceProvider { + List readLines(List pathParts) => + getFile(path.joinAll(pathParts)).readAsStringSync().split('\n'); +}