Skip to content

[swift5][swift6] Fix AsyncAwait API documentation - #24717

Open
goutamadwant wants to merge 1 commit into
OpenAPITools:masterfrom
goutamadwant:review/openapi-24631-asyncawait-docs
Open

[swift5][swift6] Fix AsyncAwait API documentation#24717
goutamadwant wants to merge 1 commit into
OpenAPITools:masterfrom
goutamadwant:review/openapi-24631-asyncawait-docs

Conversation

@goutamadwant

@goutamadwant goutamadwant commented Aug 16, 2026

Copy link
Copy Markdown

Fixes #24631.

Summary

Swift 5 and Swift 6 API documentation generated with responseAs: AsyncAwait currently shows completion-handler signatures and callback examples even though the generated APIs expose async throws methods.

This change:

  • adds AsyncAwait-specific signatures and try await examples to the Swift 5 and Swift 6 API documentation templates;
  • preserves completion-handler documentation for response modes that use it;
  • documents Swift 6's typed throws(ErrorResponse) and default apiConfiguration parameter;
  • respects apiStaticMethod, including instance calls such as PetAPI().addPet(...);
  • keeps Vapor on its library-specific EventLoopFuture documentation path; and
  • regenerates the affected Swift API documentation samples.

No generated runtime source or public API behavior changes.

Validation

  • Regenerated Swift 5 asyncAwaitLibrary samples.
  • Regenerated Swift 6 asyncAwaitLibrary, default, apiNonStaticMethod, and validation samples.
  • Regenerated the Swift 6 Vapor sample and confirmed it produces no tracked changes.
  • Ran Swift5ClientCodegenTest and Swift6ClientCodegenTest: 64 tests, 0 failures, 0 errors, 0 skipped.
  • Confirmed AsyncAwait-only docs contain no completion: signatures/examples.
  • Confirmed non-static AsyncAwait examples use API instances.
  • Confirmed git diff --check passes.

Direct swift build could not start on the local host because the installed Swift compiler and macOS SDK builds do not match. The generator tests and deterministic sample regeneration pass; the draft can use project CI for the remaining platform build signal.

@4brunu @tkqubo — review would be appreciated, particularly for the Swift 6 typed-error/configuration signature and the non-static/Vapor branches.

PR checklist

  • Read the contribution guidelines.
  • Run the complete repository build/sample/export sequence from the PR template. Targeted generation and focused generator tests are complete; the full all-generator sequence has not been run locally.
  • Mention the relevant Swift technical committee/reviewer contacts.

Summary by cubic

Fixes Swift 5/6 AsyncAwait API docs so they match generated clients. Previously, docs showed completion-handler signatures and callback examples; now they show async/await usage (Swift 5: async throws; Swift 6: async throws(ErrorResponse) with a default apiConfiguration).

  • Updates swift5/swift6 api_doc.mustache to emit AsyncAwait-specific signatures and try await examples when responseAs: AsyncAwait; preserves completion-handler docs for other response modes.
  • For Swift 6, documents throws(ErrorResponse) and the default apiConfiguration parameter; honors apiStaticMethod so instance calls render as PetAPI().addPet(...).
  • Keeps Vapor docs on the EventLoopFuture path; AsyncAwait changes do not apply under useVapor.
  • Regenerates affected sample docs; no runtime or public API changes. Tests pass. No migration required.

Written for commit 723207b. Summary will update on new commits.

Review in cubic

@4brunu

4brunu commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Hi @goutamadwant, thanks for opening this PR.
This PR is masked as draft, is it ready to review and merge, or you are still working on it?
Thanks

@goutamadwant
goutamadwant marked this pull request as ready for review August 16, 2026 19:22
@goutamadwant

Copy link
Copy Markdown
Author

@4brunu I converted to a PR - i was waiting for CI to pass but i see the failures are not related to my changes. thanks. Pls review and let me know if any suggestions.

@cubic-dev-ai cubic-dev-ai Bot 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.

3 issues found across 27 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="samples/client/petstore/swift5/asyncAwaitLibrary/docs/PetAPI.md">

<violation number="1" location="samples/client/petstore/swift5/asyncAwaitLibrary/docs/PetAPI.md:124">
P2: The regenerated async example for findPetsByStatus does not compile: the changed line `try await PetAPI.findPetsByStatus(status: status)` passes `status`, defined as `let status = ["status_example"]` (a `[String]`), into the parameter typed `[Status_findPetsByStatus]` on the new signature line. `Status_findPetsByStatus` is a distinct String-backed enum (cases available/pending/sold, PetAPI.swift line 102), so a `[String]` literal cannot be passed to it. Since this PR's goal is to emit correct, compilable async examples, update the example values to `[Status_findPetsByStatus]` cases (e.g. `[Status_findPetsByStatus.available]`) and fix the trailing type comment (`// [Status_findPetsByStatus]`).</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/swift5/api_doc.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/swift5/api_doc.mustache:24">
P2: When `library=vapor` is combined with `responseAs=AsyncAwait`, the generated client keeps only the EventLoopFuture API, but this template also documents an async method and try/await example. Wrap both new AsyncAwait sections in `{{^useVapor}}` so Vapor documentation remains on the EventLoopFuture path.</violation>
</file>

<file name="samples/client/petstore/swift6/apiNonStaticMethod/docs/FakeAPI.md">

<violation number="1" location="samples/client/petstore/swift6/apiNonStaticMethod/docs/FakeAPI.md:367">
P3: The new async example block repeats the operation summary comment that already precedes each legacy Promise/Observable example block, so the same comment appears twice in the generated docs (e.g. `// To test \"client\" model` in testClientModel and `// uploads an image` in uploadFile, repeated across all six files). Emit the summary comment only once per operation — either for the async example or the legacy block, not both.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

dump(response)
}
do {
let response = try await PetAPI.findPetsByStatus(status: status)

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.

P2: The regenerated async example for findPetsByStatus does not compile: the changed line try await PetAPI.findPetsByStatus(status: status) passes status, defined as let status = ["status_example"] (a [String]), into the parameter typed [Status_findPetsByStatus] on the new signature line. Status_findPetsByStatus is a distinct String-backed enum (cases available/pending/sold, PetAPI.swift line 102), so a [String] literal cannot be passed to it. Since this PR's goal is to emit correct, compilable async examples, update the example values to [Status_findPetsByStatus] cases (e.g. [Status_findPetsByStatus.available]) and fix the trailing type comment (// [Status_findPetsByStatus]).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/swift5/asyncAwaitLibrary/docs/PetAPI.md, line 124:

<comment>The regenerated async example for findPetsByStatus does not compile: the changed line `try await PetAPI.findPetsByStatus(status: status)` passes `status`, defined as `let status = ["status_example"]` (a `[String]`), into the parameter typed `[Status_findPetsByStatus]` on the new signature line. `Status_findPetsByStatus` is a distinct String-backed enum (cases available/pending/sold, PetAPI.swift line 102), so a `[String]` literal cannot be passed to it. Since this PR's goal is to emit correct, compilable async examples, update the example values to `[Status_findPetsByStatus]` cases (e.g. `[Status_findPetsByStatus.available]`) and fix the trailing type comment (`// [Status_findPetsByStatus]`).</comment>

<file context>
@@ -130,15 +120,11 @@ import PetstoreClient
-        dump(response)
-    }
+do {
+    let response = try await PetAPI.findPetsByStatus(status: status)
+    dump(response)
+} catch {
</file context>

{{/useVapor}}
{{/useRxSwift}}
{{/usePromiseKit}}
{{#useAsyncAwait}}

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.

P2: When library=vapor is combined with responseAs=AsyncAwait, the generated client keeps only the EventLoopFuture API, but this template also documents an async method and try/await example. Wrap both new AsyncAwait sections in {{^useVapor}} so Vapor documentation remains on the EventLoopFuture path.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/swift5/api_doc.mustache, line 24:

<comment>When `library=vapor` is combined with `responseAs=AsyncAwait`, the generated client keeps only the EventLoopFuture API, but this template also documents an async method and try/await example. Wrap both new AsyncAwait sections in `{{^useVapor}}` so Vapor documentation remains on the EventLoopFuture path.</comment>

<file context>
@@ -15,10 +15,15 @@ Method | HTTP request | Description
 {{/useVapor}}
 {{/useRxSwift}}
 {{/usePromiseKit}}
+{{#useAsyncAwait}}
+    {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}[{{enumName}}_{{operationId}}]{{/isContainer}}{{^isContainer}}{{enumName}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) async throws{{#returnType}} -> {{{returnType}}}{{#isResponseOptional}}?{{/isResponseOptional}}{{/returnType}}
+{{/useAsyncAwait}}
</file context>


let body = Client(client: "client_example") // Client | client model

// To test \"client\" model

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.

P3: The new async example block repeats the operation summary comment that already precedes each legacy Promise/Observable example block, so the same comment appears twice in the generated docs (e.g. // To test \"client\" model in testClientModel and // uploads an image in uploadFile, repeated across all six files). Emit the summary comment only once per operation — either for the async example or the legacy block, not both.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/swift6/apiNonStaticMethod/docs/FakeAPI.md, line 367:

<comment>The new async example block repeats the operation summary comment that already precedes each legacy Promise/Observable example block, so the same comment appears twice in the generated docs (e.g. `// To test \"client\" model` in testClientModel and `// uploads an image` in uploadFile, repeated across all six files). Emit the summary comment only once per operation — either for the async example or the legacy block, not both.</comment>

<file context>
@@ -323,6 +364,13 @@ import PetstoreClient
 
 let body = Client(client: "client_example") // Client | client model
 
+// To test \"client\" model
+do {
+    let response = try await FakeAPI().testClientModel(body: body)
</file context>

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.

[BUG][swift6] Docs generated still use completion even when AsyncAwait flag set

2 participants