@Override
    public void run() {
        var members = getMembers();
        writer.pushState(new ShapeMembersSection(context, shape, members, listingType));
        var parentSymbol = context.symbolProvider().toSymbol(shape);
        if (!members.isEmpty()) {
            parentSymbol.getProperty(DocSymbolProvider.LINK_ID_PROPERTY, String.class).ifPresent(linkId -> {
                writer.writeAnchor(linkId + "-" + listingType.getLinkIdSuffix());
            });
            writer.openHeading(listingType.getTitle());
            writer.openDefinitionList();
            for (MemberShape member : members) {
                writer.pushState(new MemberSection(context, member));

                var symbol = context.symbolProvider().toSymbol(member);
                var target = context.model().expectShape(member.getTarget());

                var typeWriter = writer.consumer(w -> target.accept(new MemberTypeVisitor(w, context, member)));
                writer.openDefinitionListItem(w -> w.writeInline("$L ($C)", symbol.getName(), typeWriter));

                writer.injectSection(new ShapeSubheadingSection(context, member));
                writer.writeShapeDocs(member, context.model());
                writer.injectSection(new ShapeDetailsSection(context, member));
                GeneratorUtils.writeProtocolsSection(context, writer, member);
                writer.closeDefinitionListItem();
                writer.popState();
            }
            writer.closeDefinitionList();
            writer.closeHeading();
        }
        writer.popState();
    }
Constructs a MemberGenerator.

@param context The context used to generate documentation.
@param writer The writer to write to.
@param shape The shape whose members are being generated.
@param listingType The type of listing being generated.
smithy-docgen/src/main/java/software/amazon/smithy/docgen/generators/MemberGenerator.java