private Symbol provideSymbol(Shape shape, SymbolProvider symbolProvider, Model model) {
        if (shape.hasTrait(IdRefTrait.ID)) {
            return SHAPE_ID_SYMBOL;
        } else if (shape.isMemberShape()) {
            Shape target = model.expectShape(shape.asMemberShape().orElseThrow(RuntimeException::new).getTarget());
            return provideSymbol(target, symbolProvider, model);
        } else if (shape.isListShape()) {
            // Replace any members reference by a list shape as the decorator does wrap the internal call from the
            // toSymbol(member)
            MemberShape member = shape.asListShape().orElseThrow(RuntimeException::new).getMember();
            return symbolProvider.toSymbol(shape)
                    .toBuilder()
                    .references(ListUtils.of(new SymbolReference(provideSymbol(member, symbolProvider, model))))
                    .build();
        } else if (shape.isMapShape()) {
            // Same as list replacement but for map shapes
            MapShape mapShape = shape.asMapShape().orElseThrow(RuntimeException::new);
            return symbolProvider.toSymbol(shape)
                    .toBuilder()
                    .references(ListUtils.of(
                            new SymbolReference(provideSymbol(mapShape.getKey(), symbolProvider, model)),
                            new SymbolReference(provideSymbol(mapShape.getValue(), symbolProvider, model))))
                    .build();
        }
        return symbolProvider.toSymbol(shape);
    }
Handles the conversion of String members and String types with the {@link IdRefTrait} trait map to
the {@link ShapeId} type.

<p>This integration is run with a high priority to ensure downstream integrations see a
{@code ShapeId} type instead of a {@code string}.
smithy-trait-codegen/src/main/java/software/amazon/smithy/traitcodegen/integrations/idref/IdRefDecoratorIntegration.java