From 348cbd7204645f99074bf7873af8b6ba6d34ceb0 Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Mon, 30 Aug 2021 16:44:08 -0700 Subject: [PATCH 01/19] Basic implementation of typedef member lookups (#2768) * flatten * Fix up typedef implementation to handle generic non-class correctly * oops, forgot a bit --- lib/src/model/model_element.dart | 5 +- lib/src/model/typedef.dart | 61 ++++++++++++++++--- test/end2end/model_special_cases_test.dart | 17 ++++++ test/end2end/model_test.dart | 11 +++- .../lib/constructor_tearoffs.dart | 2 +- 5 files changed, 83 insertions(+), 13 deletions(-) diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart index f01ce12963..9d834dd151 100644 --- a/lib/src/model/model_element.dart +++ b/lib/src/model/model_element.dart @@ -315,7 +315,10 @@ abstract class ModelElement extends Canonicalization if (e.aliasedType is FunctionType) { return FunctionTypedef(e, library, packageGraph); } - return Typedef(e, library, packageGraph); + if (e.aliasedType.element is ClassElement) { + return ClassTypedef(e, library, packageGraph); + } + return GeneralizedTypedef(e, library, packageGraph); } if (e is ConstructorElement) { return Constructor(e, library, packageGraph); diff --git a/lib/src/model/typedef.dart b/lib/src/model/typedef.dart index 93358152d6..d4be7b2433 100644 --- a/lib/src/model/typedef.dart +++ b/lib/src/model/typedef.dart @@ -9,7 +9,7 @@ import 'package:dartdoc/src/model/comment_referable.dart'; import 'package:dartdoc/src/model/model.dart'; import 'package:dartdoc/src/render/typedef_renderer.dart'; -class Typedef extends ModelElement +abstract class Typedef extends ModelElement with TypeParameters, Categorization implements EnclosedElement { Typedef(TypeAliasElement element, Library library, PackageGraph packageGraph) @@ -40,6 +40,8 @@ class Typedef extends ModelElement @override String get filePath => '${library.dirName}/$fileName'; + /// Helper for mustache templates, which can't do casting themselves + /// without this. FunctionTypedef get asCallable => this as FunctionTypedef; @override @@ -65,34 +67,73 @@ class Typedef extends ModelElement TypedefRenderer get _renderer => packageGraph.rendererFactory.typedefRenderer; - Map _referenceChildren; + @override + Iterable get referenceParents => [definingLibrary]; + Map _referenceChildren; @override Map get referenceChildren { if (_referenceChildren == null) { _referenceChildren = {}; - - // Only consider parameters if this is a function typedef. - if (isCallable) { - _referenceChildren - .addEntriesIfAbsent(parameters.explicitOnCollisionWith(this)); - } _referenceChildren .addEntriesIfAbsent(typeParameters.explicitOnCollisionWith(this)); } return _referenceChildren; } +} + +/// A typedef referring to a non-function typedef that is nevertheless not +/// referring to a defined class. An example is a typedef alias for `void` or +/// for `Function` itself. +class GeneralizedTypedef extends Typedef { + GeneralizedTypedef( + TypeAliasElement element, Library library, PackageGraph packageGraph) + : super(element, library, packageGraph) { + assert(!isCallable); + } +} + +/// A typedef referring to a non-function, defined type. +class ClassTypedef extends Typedef { + ClassTypedef( + TypeAliasElement element, Library library, PackageGraph packageGraph) + : super(element, library, packageGraph) { + assert(!isCallable); + assert(modelType.modelElement is Class); + } @override - Iterable get referenceParents => [definingLibrary]; + DefinedElementType get modelType => super.modelType; + + @override + Map get referenceChildren { + if (_referenceChildren == null) { + _referenceChildren = super.referenceChildren; + _referenceChildren + .addEntriesIfAbsent(modelType.modelElement.referenceChildren.entries); + } + return _referenceChildren; + } } /// A typedef referring to a function type. class FunctionTypedef extends Typedef { FunctionTypedef( TypeAliasElement element, Library library, PackageGraph packageGraph) - : super(element, library, packageGraph); + : super(element, library, packageGraph) { + assert(isCallable); + } @override Callable get modelType => super.modelType; + + @override + Map get referenceChildren { + if (_referenceChildren == null) { + _referenceChildren = super.referenceChildren; + _referenceChildren + .addEntriesIfAbsent(parameters.explicitOnCollisionWith(this)); + } + return _referenceChildren; + } } diff --git a/test/end2end/model_special_cases_test.dart b/test/end2end/model_special_cases_test.dart index 0e2af4366b..50c4d54978 100644 --- a/test/end2end/model_special_cases_test.dart +++ b/test/end2end/model_special_cases_test.dart @@ -186,6 +186,23 @@ void main() { expect(referenceLookup(constructorTearoffs, 'F.new'), equals(MatchingLinkResult(Fnew))); }); + + test('.new works on typedefs', () { + expect(referenceLookup(constructorTearoffs, 'At.new'), + equals(MatchingLinkResult(Anew))); + expect(referenceLookup(constructorTearoffs, 'Bt.new'), + equals(MatchingLinkResult(Bnew))); + expect(referenceLookup(constructorTearoffs, 'Ct.new'), + equals(MatchingLinkResult(Cnew))); + expect(referenceLookup(constructorTearoffs, 'Dt.new'), + equals(MatchingLinkResult(Dnew))); + expect(referenceLookup(constructorTearoffs, 'Et.new'), + equals(MatchingLinkResult(Enew))); + expect(referenceLookup(constructorTearoffs, 'Fstring.new'), + equals(MatchingLinkResult(Fnew))); + expect(referenceLookup(constructorTearoffs, 'Ft.new'), + equals(MatchingLinkResult(Fnew))); + }); }, skip: !_constructorTearoffsAllowed.allows(utils.platformVersion)); }); diff --git a/test/end2end/model_test.dart b/test/end2end/model_test.dart index bc153c1398..d4ee8867d4 100644 --- a/test/end2end/model_test.dart +++ b/test/end2end/model_test.dart @@ -2236,7 +2236,8 @@ void main() { group('Linking for generalized typedef cases works', () { Library generalizedTypedefs; Typedef T0, T2, T5, T8; - Class C2; + Class C1, C2; + Field C1a; setUpAll(() { generalizedTypedefs = packageGraph.libraries @@ -2245,7 +2246,9 @@ void main() { T2 = generalizedTypedefs.typedefs.firstWhere((a) => a.name == 'T2'); T5 = generalizedTypedefs.typedefs.firstWhere((a) => a.name == 'T5'); T8 = generalizedTypedefs.typedefs.firstWhere((a) => a.name == 'T8'); + C1 = generalizedTypedefs.classes.firstWhere((c) => c.name == 'C1'); C2 = generalizedTypedefs.classes.firstWhere((c) => c.name == 'C2'); + C1a = C1.allFields.firstWhere((f) => f.name == 'a'); }); test('Verify basic ability to link anything', () { @@ -2266,6 +2269,12 @@ void main() { var T5name = T5.parameters.firstWhere((t) => t.name == 'name'); expect(referenceLookup(T5, 'name'), equals(MatchingLinkResult(T5name))); }); + + test('Verify ability to link to class members of aliased classes', () { + expect(referenceLookup(generalizedTypedefs, 'T8.a'), + equals(MatchingLinkResult(C1a))); + expect(referenceLookup(T8, 'a'), equals(MatchingLinkResult(C1a))); + }); }); group('Linking for complex inheritance and reexport cases', () { diff --git a/testing/test_package_experiments/lib/constructor_tearoffs.dart b/testing/test_package_experiments/lib/constructor_tearoffs.dart index 6c3e87dd34..722f4e4bde 100644 --- a/testing/test_package_experiments/lib/constructor_tearoffs.dart +++ b/testing/test_package_experiments/lib/constructor_tearoffs.dart @@ -58,4 +58,4 @@ typedef NotAClass = Function; /// Mixins don't have constructors either, so disallow `M.new`. mixin M on C { -} \ No newline at end of file +} From 26cd594f53eb3eaa8b829ae6f90b15a82a5ba3d7 Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Tue, 31 Aug 2021 14:18:44 -0700 Subject: [PATCH 02/19] Extract 'Constructable' from 'Class', creating a new class 'InheritingContainer' --- lib/src/generator/generator_frontend.dart | 8 - lib/src/generator/template_data.dart | 33 +- .../templates.aot_renderers_for_html.dart | 207 +- .../templates.aot_renderers_for_md.dart | 176 +- lib/src/generator/templates.dart | 8 +- .../templates.runtime_renderers.dart | 2221 +++++++++-------- lib/src/model/accessor.dart | 12 +- lib/src/model/class.dart | 544 +--- lib/src/model/container.dart | 15 +- lib/src/model/extension.dart | 4 +- lib/src/model/field.dart | 10 +- lib/src/model/inheritable.dart | 30 +- lib/src/model/inheriting_container.dart | 462 ++++ lib/src/model/mixin.dart | 50 +- lib/src/model/model.dart | 1 + lib/src/model/operator.dart | 4 +- lib/src/model/package_graph.dart | 43 +- lib/src/model_utils.dart | 5 +- lib/templates/html/mixin.html | 46 +- lib/templates/md/mixin.md | 22 +- test/end2end/model_test.dart | 2 +- 21 files changed, 2063 insertions(+), 1840 deletions(-) create mode 100644 lib/src/model/inheriting_container.dart diff --git a/lib/src/generator/generator_frontend.dart b/lib/src/generator/generator_frontend.dart index 08d9f3caff..6bfcf2c769 100644 --- a/lib/src/generator/generator_frontend.dart +++ b/lib/src/generator/generator_frontend.dart @@ -168,14 +168,6 @@ class GeneratorFrontEnd implements Generator { indexAccumulator.add(mixin); _generatorBackend.generateMixin(writer, packageGraph, lib, mixin); - for (var constructor in filterNonDocumented(mixin.constructors)) { - if (!constructor.isCanonical) continue; - - indexAccumulator.add(constructor); - _generatorBackend.generateConstructor( - writer, packageGraph, lib, mixin, constructor); - } - for (var constant in filterNonDocumented(mixin.constantFields)) { if (!constant.isCanonical) continue; indexAccumulator.add(constant); diff --git a/lib/src/generator/template_data.dart b/lib/src/generator/template_data.dart index 594816fd50..e82681be9a 100644 --- a/lib/src/generator/template_data.dart +++ b/lib/src/generator/template_data.dart @@ -173,34 +173,51 @@ class LibraryTemplateData extends TemplateData } /// Template data for Dart 2.1-style mixin declarations. -class MixinTemplateData extends ClassTemplateData { - final Mixin mixin; - +class MixinTemplateData extends InheritingContainerTemplateData { MixinTemplateData( TemplateOptions htmlOptions, PackageGraph packageGraph, Library library, - this.mixin, + Mixin mixin, LibrarySidebar _sidebarForLibrary, ContainerSidebar _sidebarForContainer) : super(htmlOptions, packageGraph, library, mixin, _sidebarForLibrary, _sidebarForContainer); + Mixin get mixin => clazz; + @override Mixin get self => mixin; } +/// Template data for Dart classes. +class ClassTemplateData extends InheritingContainerTemplateData { + ClassTemplateData( + TemplateOptions htmlOptions, + PackageGraph packageGraph, + Library library, + Class clazz, + LibrarySidebar _sidebarForLibrary, + ContainerSidebar _sidebarForContainer) + : super(htmlOptions, packageGraph, library, clazz, _sidebarForLibrary, + _sidebarForContainer); + + @override + Class get clazz => super.clazz; +} + /// Base template data class for [Class], [Enum], and [Mixin]. -class ClassTemplateData extends TemplateData +abstract class InheritingContainerTemplateData + extends TemplateData implements TemplateDataWithLibrary, TemplateDataWithContainer { - final Class clazz; + final InheritingContainer clazz; @override final Library library; Class _objectType; final LibrarySidebar _sidebarForLibrary; final ContainerSidebar _sidebarForContainer; - ClassTemplateData( + InheritingContainerTemplateData( TemplateOptions htmlOptions, PackageGraph packageGraph, this.library, @@ -335,7 +352,7 @@ class ConstructorTemplateData extends TemplateData 'for the Dart programming language.'; } -class EnumTemplateData extends ClassTemplateData { +class EnumTemplateData extends InheritingContainerTemplateData { EnumTemplateData( TemplateOptions htmlOptions, PackageGraph packageGraph, diff --git a/lib/src/generator/templates.aot_renderers_for_html.dart b/lib/src/generator/templates.aot_renderers_for_html.dart index 0ece2698bb..b5e3d9c5ee 100644 --- a/lib/src/generator/templates.aot_renderers_for_html.dart +++ b/lib/src/generator/templates.aot_renderers_for_html.dart @@ -1437,7 +1437,7 @@ String _renderCategory_partial_footer_12(_i1.CategoryTemplateData context0) { return buffer.toString(); } -String renderClass(_i1.ClassTemplateData context0) { +String renderClass(_i1.ClassTemplateData context0) { final buffer = StringBuffer(); buffer.write(_renderClass_partial_head_0(context0)); buffer.writeln(); @@ -1821,8 +1821,7 @@ String renderClass(_i1.ClassTemplateData context0) { return buffer.toString(); } -String _renderClass_partial_head_0( - _i1.ClassTemplateData context0) { +String _renderClass_partial_head_0(_i1.ClassTemplateData context0) { final buffer = StringBuffer(); buffer.write(''' @@ -1975,8 +1974,8 @@ String _renderClass_partial_head_0( return buffer.toString(); } -String _renderClass_partial_source_link_1( - _i4.Class context1, _i1.ClassTemplateData context0) { +String _renderClass_partial_source_link_1( + _i4.Class context1, _i1.ClassTemplateData context0) { final buffer = StringBuffer(); if (context1.hasSourceHref == true) { buffer.writeln(); @@ -1990,8 +1989,8 @@ String _renderClass_partial_source_link_1( return buffer.toString(); } -String _renderClass_partial_feature_set_2( - _i4.Class context1, _i1.ClassTemplateData context0) { +String _renderClass_partial_feature_set_2( + _i4.Class context1, _i1.ClassTemplateData context0) { final buffer = StringBuffer(); if (context1.hasFeatureSet == true) { var context2 = context1.displayedLanguageFeatures; @@ -2007,8 +2006,8 @@ String _renderClass_partial_feature_set_2( return buffer.toString(); } -String _renderClass_partial_categorization_3( - _i4.Class context1, _i1.ClassTemplateData context0) { +String _renderClass_partial_categorization_3( + _i4.Class context1, _i1.ClassTemplateData context0) { final buffer = StringBuffer(); if (context1.hasCategoryNames == true) { var context2 = context1.displayedCategories; @@ -2024,8 +2023,8 @@ String _renderClass_partial_categorization_3( return buffer.toString(); } -String _renderClass_partial_documentation_4( - _i4.Class context1, _i1.ClassTemplateData context0) { +String _renderClass_partial_documentation_4( + _i4.Class context1, _i1.ClassTemplateData context0) { final buffer = StringBuffer(); if (context1.hasDocumentation == true) { buffer.writeln(); @@ -2042,8 +2041,8 @@ String _renderClass_partial_documentation_4( return buffer.toString(); } -String _renderClass_partial_property_5( - _i9.Field context2, _i4.Class context1, _i1.ClassTemplateData context0) { +String _renderClass_partial_property_5( + _i9.Field context2, _i4.Class context1, _i1.ClassTemplateData context0) { final buffer = StringBuffer(); buffer.write('''
'''); @@ -2116,10 +2114,8 @@ String __renderClass_partial_property_5_partial_features_1( return buffer.toString(); } -String _renderClass_partial_callable_6( - _i10.Method context2, - _i4.Class context1, - _i1.ClassTemplateData context0) { +String _renderClass_partial_callable_6( + _i10.Method context2, _i4.Class context1, _i1.ClassTemplateData context0) { final buffer = StringBuffer(); buffer.write('''
'''); @@ -2202,8 +2195,8 @@ String __renderClass_partial_callable_6_partial_features_1( return buffer.toString(); } -String _renderClass_partial_constant_7( - _i9.Field context2, _i4.Class context1, _i1.ClassTemplateData context0) { +String _renderClass_partial_constant_7( + _i9.Field context2, _i4.Class context1, _i1.ClassTemplateData context0) { final buffer = StringBuffer(); buffer.write('''
'''); @@ -2276,8 +2268,7 @@ String __renderClass_partial_constant_7_partial_features_1( return buffer.toString(); } -String _renderClass_partial_search_sidebar_8( - _i1.ClassTemplateData context0) { +String _renderClass_partial_search_sidebar_8(_i1.ClassTemplateData context0) { final buffer = StringBuffer(); buffer.write('''