private void writeShapeName(Shape shape) {
            var symbol = context.symbolProvider().toSymbol(shape);

            if (StringUtils.isNotBlank(symbol.getDefinitionFile())) {
                writer.writeInline("$R", symbol);
            } else {
                // If the symbol doesn't have a definition file, it can't be linked.
                // If it can't be linked to, then the actual name of the shape
                // doesn't matter and would only serve as a confusing dead reference
                // if displayed in the docs. Instead we just use the shape type name,
                // which should be more clear in almost every case. A SymbolReference
                // is passed along rather than writing a literal string so that
                // implementations can do something with the source symbol if
                // necessary.
                var reference = SymbolReference.builder()
                        .symbol(symbol)
                        .alias(StringUtils.capitalize(shape.getType().name().toLowerCase(Locale.ENGLISH)))
                        .build();
                writer.writeInline("$R", reference);
            }
        }
@return returns the suffix that will be applied to the parent shape's link
        id to form this member listing's link id.
smithy-docgen/src/main/java/software/amazon/smithy/docgen/generators/MemberGenerator.java