diff --git a/lib/src/generator/templates.aot_renderers_for_html.dart b/lib/src/generator/templates.aot_renderers_for_html.dart index febbfed3b1..6c507f2b22 100644 --- a/lib/src/generator/templates.aot_renderers_for_html.dart +++ b/lib/src/generator/templates.aot_renderers_for_html.dart @@ -2634,32 +2634,8 @@ String _renderClass_partial_documentation_4(Class context1) => String _renderClass_partial_super_chain_5(Class context1) => _deduplicated_lib_templates__super_chain_html(context1); -String _renderClass_partial_interfaces_6(Class context1) { - final buffer = StringBuffer(); - if (context1.hasPublicInterfaces) { - buffer.writeln(); - buffer.write(''' -
Implemented types
-
- -
'''); - } - - return buffer.toString(); -} +String _renderClass_partial_interfaces_6(Class context1) => + _deduplicated_lib_templates__interfaces_html(context1); String _renderClass_partial_mixed_in_types_7(Class context1) { final buffer = StringBuffer(); @@ -2761,32 +2737,8 @@ String _renderEnum_partial_documentation_4(Enum context1) => String _renderEnum_partial_super_chain_5(Enum context1) => _deduplicated_lib_templates__super_chain_html(context1); -String _renderEnum_partial_interfaces_6(Enum context1) { - final buffer = StringBuffer(); - if (context1.hasPublicInterfaces) { - buffer.writeln(); - buffer.write(''' -
Implemented types
-
- -
'''); - } - - return buffer.toString(); -} +String _renderEnum_partial_interfaces_6(Enum context1) => + _deduplicated_lib_templates__interfaces_html(context1); String _renderEnum_partial_mixed_in_types_7(Enum context1) { final buffer = StringBuffer(); @@ -2921,32 +2873,8 @@ String _renderExtensionType_partial_categorization_3(ExtensionType context1) => String _renderExtensionType_partial_documentation_4(ExtensionType context1) => _deduplicated_lib_templates__documentation_html(context1); -String _renderExtensionType_partial_interfaces_5(ExtensionType context1) { - final buffer = StringBuffer(); - if (context1.hasPublicInterfaces) { - buffer.writeln(); - buffer.write(''' -
Implemented types
-
- -
'''); - } - - return buffer.toString(); -} +String _renderExtensionType_partial_interfaces_5(ExtensionType context1) => + _deduplicated_lib_templates__interfaces_html(context1); String _renderExtensionType_partial_container_annotations_6( ExtensionType context1) => @@ -3270,32 +3198,8 @@ String _renderMixin_partial_documentation_4(Mixin context1) => String _renderMixin_partial_super_chain_5(Mixin context1) => _deduplicated_lib_templates__super_chain_html(context1); -String _renderMixin_partial_interfaces_6(Mixin context1) { - final buffer = StringBuffer(); - if (context1.hasPublicInterfaces) { - buffer.writeln(); - buffer.write(''' -
Implemented types
-
- -
'''); - } - - return buffer.toString(); -} +String _renderMixin_partial_interfaces_6(Mixin context1) => + _deduplicated_lib_templates__interfaces_html(context1); String _renderMixin_partial_annotations_7(Mixin context1) => _deduplicated_lib_templates__annotations_html(context1); @@ -4518,6 +4422,34 @@ String _deduplicated_lib_templates__super_chain_html( return buffer.toString(); } +String _deduplicated_lib_templates__interfaces_html( + InheritingContainer context0) { + final buffer = StringBuffer(); + if (context0.hasPublicInterfaces) { + buffer.writeln(); + buffer.write(''' +
Implemented types
+
+ +
'''); + } + + return buffer.toString(); +} + String _deduplicated_lib_templates__container_annotations_html( Container context0) { final buffer = StringBuffer(); diff --git a/lib/src/generator/templates.runtime_renderers.dart b/lib/src/generator/templates.runtime_renderers.dart index 4a531bfa7b..f2762f0eb2 100644 --- a/lib/src/generator/templates.runtime_renderers.dart +++ b/lib/src/generator/templates.runtime_renderers.dart @@ -1745,7 +1745,6 @@ class _Renderer_Class extends RendererBase { () => { ..._Renderer_InheritingContainer.propertyMap(), ..._Renderer_Constructable.propertyMap(), - ..._Renderer_TypeImplementing.propertyMap(), ..._Renderer_MixedInTypes.propertyMap(), 'allModelElements': Property( getValue: (CT_ c) => c.allModelElements, @@ -4523,7 +4522,6 @@ class _Renderer_Enum extends RendererBase { () => { ..._Renderer_InheritingContainer.propertyMap(), ..._Renderer_Constructable.propertyMap(), - ..._Renderer_TypeImplementing.propertyMap(), ..._Renderer_MixedInTypes.propertyMap(), 'allModelElements': Property( getValue: (CT_ c) => c.allModelElements, @@ -5263,7 +5261,6 @@ class _Renderer_ExtensionType extends RendererBase { () => { ..._Renderer_InheritingContainer.propertyMap(), ..._Renderer_Constructable.propertyMap(), - ..._Renderer_TypeImplementing.propertyMap(), 'allModelElements': Property( getValue: (CT_ c) => c.allModelElements, renderVariable: (CT_ c, Property self, @@ -7511,6 +7508,20 @@ class _Renderer_InheritingContainer extends RendererBase { self.renderSimpleVariable(c, remainingNames, 'bool'), getBool: (CT_ c) => c.hasPotentiallyApplicableExtensions, ), + 'hasPublicImplementers': Property( + getValue: (CT_ c) => c.hasPublicImplementers, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable(c, remainingNames, 'bool'), + getBool: (CT_ c) => c.hasPublicImplementers, + ), + 'hasPublicInterfaces': Property( + getValue: (CT_ c) => c.hasPublicInterfaces, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable(c, remainingNames, 'bool'), + getBool: (CT_ c) => c.hasPublicInterfaces, + ), 'hasPublicSuperChainReversed': Property( getValue: (CT_ c) => c.hasPublicSuperChainReversed, renderVariable: (CT_ c, Property self, @@ -7591,6 +7602,19 @@ class _Renderer_InheritingContainer extends RendererBase { _render_Operator(e, ast, r.template, sink, parent: r)); }, ), + 'interfaceElements': Property( + getValue: (CT_ c) => c.interfaceElements, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable( + c, remainingNames, 'List'), + renderIterable: (CT_ c, RendererBase r, + List ast, StringSink sink) { + return c.interfaceElements.map((e) => + _render_InheritingContainer(e, ast, r.template, sink, + parent: r)); + }, + ), 'isAbstract': Property( getValue: (CT_ c) => c.isAbstract, renderVariable: (CT_ c, Property self, @@ -7676,6 +7700,19 @@ class _Renderer_InheritingContainer extends RendererBase { _render_Extension(e, ast, r.template, sink, parent: r)); }, ), + 'publicImplementersSorted': Property( + getValue: (CT_ c) => c.publicImplementersSorted, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable( + c, remainingNames, 'List'), + renderIterable: (CT_ c, RendererBase r, + List ast, StringSink sink) { + return c.publicImplementersSorted.map((e) => + _render_InheritingContainer(e, ast, r.template, sink, + parent: r)); + }, + ), 'publicInheritedInstanceFields': Property( getValue: (CT_ c) => c.publicInheritedInstanceFields, renderVariable: (CT_ c, Property self, @@ -7715,7 +7752,7 @@ class _Renderer_InheritingContainer extends RendererBase { renderVariable: (CT_ c, Property self, List remainingNames) => self.renderSimpleVariable( - c, remainingNames, 'Iterable'), + c, remainingNames, 'List'), renderIterable: (CT_ c, RendererBase r, List ast, StringSink sink) { return c.publicInterfaces.map((e) => @@ -9917,7 +9954,6 @@ class _Renderer_Mixin extends RendererBase { CT_, () => { ..._Renderer_InheritingContainer.propertyMap(), - ..._Renderer_TypeImplementing.propertyMap(), 'element': Property( getValue: (CT_ c) => c.element, renderVariable: (CT_ c, Property self, @@ -12699,13 +12735,13 @@ class _Renderer_PackageTemplateData extends RendererBase { } } -String renderError(PackageTemplateData context, Template template) { +String renderIndex(PackageTemplateData context, Template template) { var buffer = StringBuffer(); _render_PackageTemplateData(context, template.ast, template, buffer); return buffer.toString(); } -String renderIndex(PackageTemplateData context, Template template) { +String renderError(PackageTemplateData context, Template template) { var buffer = StringBuffer(); _render_PackageTemplateData(context, template.ast, template, buffer); return buffer.toString(); @@ -15010,115 +15046,6 @@ class _Renderer_TwoDirectoriesDown } } -class _Renderer_TypeImplementing extends RendererBase { - static final Map _propertyMapCache = {}; - static Map> propertyMap< - CT_ extends TypeImplementing>() => - _propertyMapCache.putIfAbsent( - CT_, - () => { - 'hasModifiers': Property( - getValue: (CT_ c) => c.hasModifiers, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable(c, remainingNames, 'bool'), - getBool: (CT_ c) => c.hasModifiers, - ), - 'hasPublicImplementers': Property( - getValue: (CT_ c) => c.hasPublicImplementers, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable(c, remainingNames, 'bool'), - getBool: (CT_ c) => c.hasPublicImplementers, - ), - 'hasPublicInterfaces': Property( - getValue: (CT_ c) => c.hasPublicInterfaces, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable(c, remainingNames, 'bool'), - getBool: (CT_ c) => c.hasPublicInterfaces, - ), - 'interfaceElements': Property( - getValue: (CT_ c) => c.interfaceElements, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable( - c, remainingNames, 'List'), - renderIterable: (CT_ c, RendererBase r, - List ast, StringSink sink) { - return c.interfaceElements.map((e) => - _render_InheritingContainer(e, ast, r.template, sink, - parent: r)); - }, - ), - 'interfaces': Property( - getValue: (CT_ c) => c.interfaces, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable( - c, remainingNames, 'List'), - renderIterable: (CT_ c, RendererBase r, - List ast, StringSink sink) { - return c.interfaces.map((e) => _render_DefinedElementType( - e, ast, r.template, sink, - parent: r)); - }, - ), - 'publicImplementers': Property( - getValue: (CT_ c) => c.publicImplementers, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable( - c, remainingNames, 'Iterable'), - renderIterable: (CT_ c, RendererBase r, - List ast, StringSink sink) { - return c.publicImplementers.map((e) => - _render_InheritingContainer(e, ast, r.template, sink, - parent: r)); - }, - ), - 'publicImplementersSorted': Property( - getValue: (CT_ c) => c.publicImplementersSorted, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable( - c, remainingNames, 'List'), - renderIterable: (CT_ c, RendererBase r, - List ast, StringSink sink) { - return c.publicImplementersSorted.map((e) => - _render_InheritingContainer(e, ast, r.template, sink, - parent: r)); - }, - ), - 'publicInterfaces': Property( - getValue: (CT_ c) => c.publicInterfaces, - renderVariable: (CT_ c, Property self, - List remainingNames) => - self.renderSimpleVariable( - c, remainingNames, 'Iterable'), - renderIterable: (CT_ c, RendererBase r, - List ast, StringSink sink) { - return c.publicInterfaces.map((e) => - _render_DefinedElementType(e, ast, r.template, sink, - parent: r)); - }, - ), - }) as Map>; - - _Renderer_TypeImplementing(TypeImplementing context, - RendererBase? parent, Template template, StringSink sink) - : super(context, parent, template, sink); - - @override - Property? getProperty(String key) { - if (propertyMap().containsKey(key)) { - return propertyMap()[key]; - } else { - return null; - } - } -} - void _render_TypeParameter(TypeParameter context, List ast, Template template, StringSink sink, {RendererBase? parent}) { diff --git a/lib/src/model/class.dart b/lib/src/model/class.dart index 1b5d3dc2a2..95f15c6c81 100644 --- a/lib/src/model/class.dart +++ b/lib/src/model/class.dart @@ -12,8 +12,7 @@ import 'package:dartdoc/src/model/model.dart'; /// /// **instance**: As with [Container], but also includes inherited children. /// **inherited**: Filtered getters giving only inherited children. -class Class extends InheritingContainer - with Constructable, TypeImplementing, MixedInTypes { +class Class extends InheritingContainer with Constructable, MixedInTypes { @override final InterfaceElement element; diff --git a/lib/src/model/enum.dart b/lib/src/model/enum.dart index a525c20670..cbd4ed3fcf 100644 --- a/lib/src/model/enum.dart +++ b/lib/src/model/enum.dart @@ -8,8 +8,7 @@ import 'package:dartdoc/src/model/model.dart'; import 'package:dartdoc/src/model_utils.dart' as model_utils; import 'package:dartdoc/src/render/enum_field_renderer.dart'; -class Enum extends InheritingContainer - with Constructable, TypeImplementing, MixedInTypes { +class Enum extends InheritingContainer with Constructable, MixedInTypes { @override final EnumElement element; diff --git a/lib/src/model/extension_type.dart b/lib/src/model/extension_type.dart index 96bfb1d025..1c0a3a66c3 100644 --- a/lib/src/model/extension_type.dart +++ b/lib/src/model/extension_type.dart @@ -8,8 +8,7 @@ import 'package:dartdoc/src/model/comment_referable.dart'; import 'package:dartdoc/src/model/model.dart'; import 'package:meta/meta.dart'; -class ExtensionType extends InheritingContainer - with Constructable, TypeImplementing { +class ExtensionType extends InheritingContainer with Constructable { @override final ExtensionTypeElement element; diff --git a/lib/src/model/inheriting_container.dart b/lib/src/model/inheriting_container.dart index 60c57a6d86..2b14d4c8ae 100644 --- a/lib/src/model/inheriting_container.dart +++ b/lib/src/model/inheriting_container.dart @@ -305,10 +305,19 @@ abstract class InheritingContainer extends Container String get fullkind => kind.toString(); + /// Whether this container has any "modifiers" that should be displayed on the + /// container's page, above it's members. + // TODO(srawlins): This name is confusing, especially after the language + // feature, "new class modifiers." I think the only purpose is to avoid + // writing a `
` and a `
` tag, if they would be empty. But with + // CSS, we should be able to just always write those tags, and visually make + // them take up zero space if they are empty. bool get hasModifiers => hasAnnotations || hasPublicSuperChainReversed || - hasPotentiallyApplicableExtensions; + hasPotentiallyApplicableExtensions || + hasPublicInterfaces || + hasPublicImplementers; @visibleForTesting bool get hasPublicInheritedMethods => inheritedMethods.any((e) => e.isPublic); @@ -369,7 +378,95 @@ abstract class InheritingContainer extends Container bool get publicInheritedInstanceOperators => instanceOperators.wherePublic.every((f) => f.isInherited); - Iterable get publicInterfaces; + @visibleForTesting + late final List directInterfaces = [ + for (var interface in element.interfaces) + getTypeFor(interface, library) as DefinedElementType + ]; + + bool get hasPublicImplementers => publicImplementersSorted.isNotEmpty; + + /// All the "immediate" public implementers of this container. + /// + /// For a [Mixin], this is actually the mixin applications using the [Mixin]. + /// + /// If this container has a private implementer, then that is counted as a + /// proxy for any public implementers of that private container. + List get publicImplementersSorted { + var result = {}; + var seen = {}; + + // Recursively adds [implementer] if public, or just the implementers of + // [implementer] if not. + void addToResult(InheritingContainer implementer) { + if (seen.contains(implementer)) return; + seen.add(implementer); + if (implementer.isPublicAndPackageDocumented) { + result.add(implementer); + } else { + var implementers = packageGraph.implementers[implementer]; + if (implementers != null) { + model_utils.findCanonicalFor(implementers).forEach(addToResult); + } + } + } + + var immediateImplementers = packageGraph.implementers[this]; + if (immediateImplementers != null) { + model_utils.findCanonicalFor(immediateImplementers).forEach(addToResult); + } + return result.toList(growable: false)..sort(byName); + } + + bool get hasPublicInterfaces => publicInterfaces.isNotEmpty; + + List get interfaceElements => [ + for (var interface in directInterfaces) + interface.modelElement as InheritingContainer, + ]; + + /// The public interfaces of this container. + /// + /// This list may include substitutions for intermediate private interfaces, + /// and so unlike other `public*` methods, is not a strict subset of + /// [directInterfaces] (the direct interfaces). + List get publicInterfaces { + var interfaces = []; + for (var interface in directInterfaces) { + var interfaceElement = interface.modelElement; + + /// Do not recurse if we can find an element here. + if (interfaceElement.canonicalModelElement != null) { + interfaces.add(interface); + continue; + } + // Public types used to be unconditionally exposed here. However, + // if the packages are [DocumentLocation.missing] we generally treat types + // defined in them as actually defined in a documented package. + // That translates to them being defined here, but in 'src/' or similar, + // and so, are now always hidden. + + // This type is not backed by a canonical Class; search + // the superchain and publicInterfaces of this interface to pretend + // as though the hidden class didn't exist and this class was declared + // directly referencing the canonical classes further up the chain. + if (interfaceElement is! InheritingContainer) { + assert( + false, + 'Can not handle intermediate non-public interfaces created by ' + "ModelElements that are not classes or mixins: '$fullyQualifiedName' " + "contains an interface '$interface', defined by '$interfaceElement'", + ); + continue; + } + var publicSuperChain = interfaceElement.superChain.wherePublic; + if (publicSuperChain.isNotEmpty) { + interfaces.add(publicSuperChain.first); + } + interfaces.addAll(interfaceElement.publicInterfaces); + } + return interfaces; + } Iterable get publicInterfaceElements => [ for (var interface in publicInterfaces) @@ -448,7 +545,7 @@ abstract class InheritingContainer extends Container // Pick the one closest to this class on the inheritance chain. if (setterEnclosingElement is Class && setterEnclosingElement._isInheritingFrom( - getter.enclosingElement as InheritingContainer?)) { + getter.enclosingElement as InheritingContainer)) { field = setterElement!.variable as FieldElement; } else { field = getterElement!.variable as FieldElement; @@ -472,7 +569,7 @@ abstract class InheritingContainer extends Container } /// Returns true if [other] is a parent class for this class. - bool _isInheritingFrom(InheritingContainer? other) => superChain + bool _isInheritingFrom(InheritingContainer other) => superChain .map((et) => et.modelElement as InheritingContainer) .contains(other); } @@ -497,108 +594,6 @@ mixin MixedInTypes on InheritingContainer { mixedInTypes.wherePublic; } -/// Add the ability for an [InheritingContainer] to be implemented by other -/// InheritingContainers and to reference what it itself implements. -mixin TypeImplementing on InheritingContainer { - late final List _directInterfaces = [ - for (var interface in element.interfaces) - getTypeFor(interface, library) as DefinedElementType - ]; - - late final List publicImplementersSorted = - publicImplementers.toList(growable: false)..sort(byName); - - @override - bool get hasModifiers => - super.hasModifiers || hasPublicInterfaces || hasPublicImplementers; - - bool get hasPublicImplementers => publicImplementers.isNotEmpty; - - bool get hasPublicInterfaces => publicInterfaces.isNotEmpty; - - /// Interfaces directly implemented by this container. - List get interfaces => _directInterfaces; - - List get interfaceElements => [ - for (var interface in interfaces) - interface.modelElement as InheritingContainer, - ]; - - /// All the "immediate" public implementers of this [TypeImplementing]. - /// - /// For a [Mixin], this is actually the mixin applications using the [Mixin]. - /// - /// If this [InheritingContainer] has a private implementer, then that is - /// counted as a proxy for any public implementers of that private container. - Iterable get publicImplementers { - var result = {}; - var seen = {}; - - // Recursively adds [implementer] if public, or the implementers of - // [implementer] if not. - void addToResult(InheritingContainer implementer) { - if (seen.contains(implementer)) return; - seen.add(implementer); - if (implementer.isPublicAndPackageDocumented) { - result.add(implementer); - } else { - var implementers = packageGraph.implementers[implementer]; - if (implementers != null) { - model_utils.findCanonicalFor(implementers).forEach(addToResult); - } - } - } - - var immediateImplementers = packageGraph.implementers[this]; - if (immediateImplementers != null) { - model_utils.findCanonicalFor(immediateImplementers).forEach(addToResult); - } - return result; - } - - /// The public interfaces may include substitutions for intermediate - /// private interfaces, and so unlike other public* methods, is not - /// a strict subset of [interfaces]. - @override - Iterable get publicInterfaces { - var interfaces = []; - for (var interface in _directInterfaces) { - var interfaceElement = interface.modelElement; - - /// Do not recurse if we can find an element here. - if (interfaceElement.canonicalModelElement != null) { - interfaces.add(interface); - continue; - } - // Public types used to be unconditionally exposed here. However, - // if the packages are [DocumentLocation.missing] we generally treat types - // defined in them as actually defined in a documented package. - // That translates to them being defined here, but in 'src/' or similar, - // and so, are now always hidden. - - // This type is not backed by a canonical Class; search - // the superchain and publicInterfaces of this interface to pretend - // as though the hidden class didn't exist and this class was declared - // directly referencing the canonical classes further up the chain. - if (interfaceElement is! InheritingContainer) { - assert( - false, - 'Can not handle intermediate non-public interfaces created by ' - "ModelElements that are not classes or mixins: '$fullyQualifiedName' " - "contains an interface '$interface', defined by '$interfaceElement'", - ); - continue; - } - var publicSuperChain = interfaceElement.superChain.wherePublic; - if (publicSuperChain.isNotEmpty) { - interfaces.add(publicSuperChain.first); - } - interfaces.addAll(interfaceElement.publicInterfaces); - } - return interfaces; - } -} - extension on InterfaceElement { bool get isDartCoreObject => name == 'Object' && library.name == 'dart.core'; } diff --git a/lib/src/model/mixin.dart b/lib/src/model/mixin.dart index 9444f7207b..51eb53835e 100644 --- a/lib/src/model/mixin.dart +++ b/lib/src/model/mixin.dart @@ -11,7 +11,7 @@ import 'package:dartdoc/src/model_utils.dart' as model_utils; import 'package:dartdoc/src/special_elements.dart'; import 'package:meta/meta.dart'; -class Mixin extends InheritingContainer with TypeImplementing { +class Mixin extends InheritingContainer { @override final MixinElement element; diff --git a/test/end2end/model_test.dart b/test/end2end/model_test.dart index 2b2931ef77..fba17ee76e 100644 --- a/test/end2end/model_test.dart +++ b/test/end2end/model_test.dart @@ -1690,16 +1690,23 @@ void main() async { var ImplementBase = implementorsLibrary.classes .firstWhere((c) => c.name == 'ImplementBase'); - expect(ImplementerOfThings.publicInterfaces.first.modelElement, - equals(ImplementBase)); expect( - ImplementerOfDeclaredPrivateClasses - .publicInterfaces.first.modelElement, - equals(ImplementBase)); + ImplementerOfThings.publicInterfaceElements.first, + equals(ImplementBase), + ); + expect( + ImplementerOfDeclaredPrivateClasses.publicInterfaceElements.first, + equals(ImplementBase), + ); - expect(ImplementBase.publicImplementers, - contains(ImplementerOfDeclaredPrivateClasses)); - expect(ImplementBase.publicImplementers, contains(ImplementerOfThings)); + expect( + ImplementBase.publicImplementersSorted, + contains(ImplementerOfDeclaredPrivateClasses), + ); + expect( + ImplementBase.publicImplementersSorted, + contains(ImplementerOfThings), + ); }); test('Overrides from intermediate abstract classes are picked up correctly', @@ -1803,15 +1810,20 @@ void main() async { expect(ThingToImplementInMixin.hasModifiers, isTrue); expect(MixInImplementation.hasModifiers, isTrue); expect(MixedInImplementation.hasModifiers, isTrue); - expect(ThingToImplementInMixin.publicImplementers, - orderedEquals([MixInImplementation])); - expect(MixInImplementation.publicImplementers, - orderedEquals([MixedInImplementation])); expect( - MixedInImplementation.allFields - .firstWhere((f) => f.name == 'mixinGetter') - .canonicalModelElement, - equals(mixinGetter)); + ThingToImplementInMixin.publicImplementersSorted, + orderedEquals([MixInImplementation]), + ); + expect( + MixInImplementation.publicImplementersSorted, + orderedEquals([MixedInImplementation]), + ); + expect( + MixedInImplementation.allFields + .firstWhere((f) => f.name == 'mixinGetter') + .canonicalModelElement, + equals(mixinGetter), + ); }); test('does have a line number and column', () { @@ -4424,8 +4436,8 @@ String? topLevelFunction(int param1, bool param2, Cool coolBeans, 'ImplementsFutureVoid', ), ); - var FutureVoid = - ImplementsFutureVoid.interfaces.firstWhere((e) => e.name == 'Future'); + var FutureVoid = ImplementsFutureVoid.directInterfaces + .firstWhere((e) => e.name == 'Future'); expect( FutureVoid.linkedName, equals( @@ -4717,16 +4729,16 @@ String? topLevelFunction(int param1, bool param2, Cool coolBeans, setUpAll(() { apple = exLibrary.classes.firstWhere((c) => c.name == 'Apple'); b = exLibrary.classes.firstWhere((c) => c.name == 'B'); - implA = apple.publicImplementers.toList(); + implA = apple.publicImplementersSorted; implC = exLibrary.classes .firstWhere((c) => c.name == 'Cat') - .publicImplementers - .toList(); + .publicImplementersSorted; }); test('private classes do not break the implementor chain', () { var Super1 = fakeLibrary.classes.singleWhere((c) => c.name == 'Super1'); - var publicImplementors = Super1.publicImplementers.map((i) => i.name); + var publicImplementors = + Super1.publicImplementersSorted.map((i) => i.name); expect(publicImplementors, hasLength(3)); // A direct implementor. expect(publicImplementors, contains('Super4')); @@ -4742,7 +4754,7 @@ String? topLevelFunction(int param1, bool param2, Cool coolBeans, var GenericSuperProperty = fakeLibrary.classes .singleWhere((c) => c.name == 'GenericSuperProperty'); var publicImplementors = - GenericSuperProperty.publicImplementers.map((i) => i.name); + GenericSuperProperty.publicImplementersSorted.map((i) => i.name); expect(publicImplementors, hasLength(1)); // A direct implementor. expect(publicImplementors, contains('GenericSuperValue')); @@ -4750,7 +4762,7 @@ String? topLevelFunction(int param1, bool param2, Cool coolBeans, var GenericSuperValue = fakeLibrary.classes.singleWhere((c) => c.name == 'GenericSuperValue'); publicImplementors = - GenericSuperValue.publicImplementers.map((i) => i.name); + GenericSuperValue.publicImplementersSorted.map((i) => i.name); expect(publicImplementors, hasLength(1)); // A direct implementor. expect(publicImplementors, contains('GenericSuperNum')); @@ -4758,7 +4770,7 @@ String? topLevelFunction(int param1, bool param2, Cool coolBeans, var GenericSuperNum = fakeLibrary.classes.singleWhere((c) => c.name == 'GenericSuperNum'); publicImplementors = - GenericSuperNum.publicImplementers.map((i) => i.name); + GenericSuperNum.publicImplementersSorted.map((i) => i.name); expect(publicImplementors, hasLength(1)); expect(publicImplementors, contains('GenericSuperInt')); }); @@ -4785,7 +4797,7 @@ String? topLevelFunction(int param1, bool param2, Cool coolBeans, test('B does not have implementors', () { expect(b, isNotNull); expect(b.name, equals('B')); - expect(b.publicImplementers, hasLength(0)); + expect(b.publicImplementersSorted, hasLength(0)); }); });