Skip to content

Smithy Model Gen Part 2 - #3883

Open
sbaluja wants to merge 18 commits into
mainfrom
migration-smithy-2
Open

Smithy Model Gen Part 2#3883
sbaluja wants to merge 18 commits into
mainfrom
migration-smithy-2

Conversation

@sbaluja

@sbaluja sbaluja commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Issue #, if available:

Description of changes:

  • Transformation Pipeline and interface
  • ShapeRenderer interface
  • Proper decoupling of renderer types (Request, Result)
  • Event stream operation generation
  • Correctness fixes

Check all that applies:

  • Did a review by yourself.
  • Added proper tests to cover this PR. (If tests are not applicable, explain.)
  • Checked if this PR is a breaking (APIs have been changed) change.
  • Checked if this PR will not introduce cross-platform inconsistent behavior.
  • Checked if this PR would require a ReadMe/Wiki update.

Check which platforms you have built SDK on to verify the correctness of this PR.

  • Linux
  • Windows
  • Android
  • MacOS
  • IOS
  • Other Platforms

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

sbaluja added 18 commits July 20, 2026 16:50
- Fix typos in EnumRenderer FORBIDDEN_WORDS: co_yeild->co_yield, moduel->module
- Make generateResultSource/Header protocol-aware (was hardcoded to JSON)
- Fix endpoint context param accessor casing (need PascalCase for C++ accessors)
Composable model-to-model transform chain that runs before code generation.
Service-level transforms will implement ModelTransform and register in the pipeline.
ModelGenerator is now a thin dispatcher that routes classified shapes to
registered ShapeRenderer implementations. Adding new classification types
(e.g., event streams) requires only a new renderer class, not editing
the orchestrator.

- EnumShapeRenderer, SubObjectRenderer, RequestRenderer, ResultRenderer
- Consolidate isPrimitive() into CppTypeMapper
- Promote writeDocComment/collapseWhitespace to public in MemberRenderer
- No behavioral change to generated output
Transforms run before generation, per-service. Service-level transforms
(S3, EC2, etc.) will implement ModelTransform and register in the pipeline.
Also deduplicate sanitize() between ModelCodegenPlugin and ServiceNameUtil.
Extract shared logic into renderMembers(emitHasBeenSet) to eliminate
~100 lines of near-identical code between request and result rendering.
Enables Smithy's built-in change detection and file tracking
instead of raw Files.writeString().
Add response-side event stream generation (handler, initial response, and
event stream union) plus request augmentation for simplex streaming
operations, closing the gap versus C2J for kinesis SubscribeToShard and
bedrock-runtime streaming operations.

- Add EventStreamRenderer producing the handler and initial-response (with
  serde stubs) and the header-only event stream union, matching C2J which
  emits no .cpp for the union.
- Augment RequestRenderer with HasEventStreamResponse/IsEventStreamRequest
  and the decoder/handler accessors, placing members to match C2J ordering.
- Add event stream detection helpers to ShapeClassifier and event-stream
  serde stub helpers to SerdeStub.
- Restore handler and union documentation to match C2J.
- Deduplicate renderClassDocComment into MemberRenderer and emit the file
  copyright header once from CppWriterDelegator.
@sbaluja
sbaluja marked this pull request as ready for review July 30, 2026 18:49

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in multiple places in the code we have classes that are more or less

publc class FileGenerator {
  public void function() {
     if(protocol.isJsonLike()) {
        ... do json thing
     } else {
       ... do xml thing
     }
  }
}

theres a couple of issues i see with that, logic for protocols is scattered between classes, and that xml is used at a fallback. protocol should be selected once in the generator then injected into generator classes, where they dont need to remember protocol specific logic. i.e.

public interface ProtocolSpecificCommands {
  void WriteSerializerHeaders();
  // whatever others functions
}

public class JsonCommands implements ProtocolSpecificCommands {
  @override
  void WriteSerializerHeaders() { .. do json stuff}
}

public class Generator {
  private final ProtocolSpecificCommands commands;
  public void run() {
    commands.WriteSerializerHeaders(... pass in scope)
  }
}

public class Plugin {
  ProtocolSpecificCommands commands = new JsonCommands();
  Generator generator = new Generator(commands)
}

that way its easier to add more protocols, you dont need to add another branch statment, and you can handle the "no such protocol, throw exception" once instead of in multiple places.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants