Skip to content

fix(native-codegen): escape schema string values in generated Kotlin/Swift/Dart source - #910

Merged
soberm merged 3 commits into
mainfrom
fix/native-codegen-escape-string-literals
Oct 21, 2026
Merged

soberm merged 3 commits into
mainfrom
fix/native-codegen-escape-string-literals

Conversation

@soberm

@soberm soberm commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The native code generators (Kotlin, Swift, Dart) copy schema-controlled strings from blocks.spec.json into generated source. Several of those emission sites did not escape the value, so a spec value containing special characters (quotes, backslashes, $/interpolation sequences, line terminators) could produce generated code that does not compile or does not carry the value verbatim at runtime.

Changes

Every schema-controlled string — field/parameter names used as JSON keys, descriptions, patterns, enum values, discriminator properties and tags, RPC method names, server URLs, and defaults — is now routed through a per-language string-literal escaper:

  • Kotlin (KotlinCodeGenerator.kt): single-line literal escaper matching KotlinPoet's %S form ($ → ${'$'}, CR/LF/tab/control chars escaped, KotlinPoet layout markers U+00B7/U+2662 escaped). Validation messages use a variant that leaves benign $ (e.g. ^[A-Z]{3}$) unchanged. Two existing unit assertions in DeclaredTransferableBindingTest / UnboundTransferableTest are updated from \$ to the equivalent ${'$'} form.
  • Swift (SwiftCodeGenerator.swift, TransferableEmission.swift): escape the same values in emitted string literals; method names in /// doc lines are sanitized so they stay on one line.
  • Dart (blocks_codegen/lib/src/generator.dart): escape the same values in emitted string literals.
  • New fixture native/codegen-fixtures/28-escaping/ (spec + Dart/Kotlin/Swift goldens) exercising these values. The existing 01–27 goldens are byte-identical.
  • Docs: new "Spec trust model" section in docs/native-clients/codegen-design.md describing where the spec comes from and what the generators guarantee.
  • Release notes: native/kotlin/.changeset/kotlin-codegen-escape-string-literals.md (aws-blocks-kotlin: patch), native/swift/.changeset/swift-codegen-escape-string-literals.md (aws-blocks-swift: patch), and an Unreleased entry in native/dart/packages/blocks_codegen/CHANGELOG.md.

Out of scope / follow-ups:

  • Identifier sanitization (spec names containing characters that are not valid Dart/Swift/Kotlin identifier characters) is a separate concern and not changed here.
  • Minor behavioral difference: for a string-typed field whose default is not a string, Swift falls back (omits the default) while Kotlin coerces the default to a string.

Validation

  • Regenerated all goldens from the current generators; only 28-escaping/ is new, 01–27 unchanged.
  • Kotlin: ./gradlew :codegen:test — 130/130 pass (CodegenFixturesTest 28/28).
  • Dart: dart test in blocks_codegen — 185/185 pass (golden test 28/28); dart format --set-exit-if-changed . clean; dart analyze lib bin no errors/warnings (pre-existing infos only).
  • Swift: BlocksCodegen + BlocksCodegenTests built on Linux in an isolated package — 182/182 pass, including GoldenFileTests. The full package (BlocksRuntime, build-plugin targets) is built and tested on macOS in CI.
  • npx changeset status --since=origin/main in native/kotlin and native/swift reports the expected patch bumps.

Checklist

  • PR description included
  • Tests are changed or added
  • Relevant documentation is changed or added (and PR referenced)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

…Swift/Dart source

- Kotlin: route schema-controlled strings (JSON keys, descriptions, patterns,
  enum values, discriminator tags, method names, server URLs, defaults)
  through a single-line string-literal escaper; `$` is emitted as `${'$'}`
  to match KotlinPoet's %S form. Update two unit assertions to that form.
- Swift: escape the same values when emitting string literals and doc
  comments in SwiftCodeGenerator and TransferableEmission.
- Dart: escape the same values when emitting string literals in the
  blocks_codegen generator.
- Add the 28-escaping codegen fixture (spec + Dart/Kotlin/Swift goldens);
  the existing 01-27 goldens are unchanged.
- Document the spec trust model in docs/native-clients/codegen-design.md.
- Add release notes for aws-blocks-kotlin, aws-blocks-swift (changesets)
  and blocks_codegen (CHANGELOG Unreleased).

Tracking: V2380017102
@changeset-bot

changeset-bot Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 49ac828

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@soberm
soberm marked this pull request as ready for review October 21, 2026 11:05
@soberm
soberm requested a review from a team as a code owner October 21, 2026 11:05
Comment thread native/swift/Sources/BlocksCodegen/SwiftCodeGenerator.swift Outdated
…in Swift

Restores the initializer default for format:time string fields, which the default type-gating had dropped; addresses review feedback.

@cadivus cadivus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If you want, you can follow-up these improvements here.

Comment thread native/swift/Sources/BlocksCodegen/SwiftCodeGenerator.swift
@soberm
soberm merged commit 204be5e into main Oct 21, 2026
58 of 59 checks passed
@soberm
soberm deleted the fix/native-codegen-escape-string-literals branch October 21, 2026 13:22

This branch was successfully deployed

1 active deployment
publish — 49ac8287 Deployed Oct 21, 2026 by soberm via Kotlin E2E (JVM, sandbox) #3710
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