-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Comparing changes
Open a pull request
base repository: oapi-codegen/oapi-codegen
base: main
head repository: oapi-codegen/oapi-codegen
compare: type-name-default
- 10 commits
- 24 files changed
- 3 contributors
Commits on Feb 27, 2026
-
feat: multi-pass type name resolution
I've been meaning to use this approach for a long time, because the attempts at avoiding type collisions via structure suffixes or prefixes work sporadically, at best. Conflict resolution is fundamentally a global problem, not a local problem when doing recursive traversal, so this PR splits the code generation into two parts. First, the OAPI document structure is traversed, and all the schemas that we generate are gathered up into a list of candidates, then we do global conflict resolution across the space of all schemas. This allows us to preserve the functionality of things affected by schema name - `$ref`, `required` properties, and so forth. This fixes issue #1474 (client response wrapper type colliding with a component schema of the same name and improves issue #200 handling (same name across schemas, parameters, responses, requestBodies, headers). The new system is gated behind the existing `resolve-type-name-collisions` output option. When disabled, behavior is unchanged, oapi-codegen exits with an error. This flag is default false, so there is no behavior change to oapi-codegen unless it's specified. All current test files regenerate without any differences. Added a comprehensive test which reproduces the scenarios in all the PR's and Issues below, and adds a few more, to make sure that references to renamed targets are also correct.. Key changes: - gather.go: walks entire spec collecting schemas with location metadata - resolve_names.go: assigns unique names via context suffix, per-schema disambiguation, and numeric fallback strategies - Component schemas are privileged and keep bare names on collision - Client response wrapper types now participate in collision detection - Removed ComponentType/DefinedComp from Schema struct - Removed FixDuplicateTypeNames and related functions from utils.go Obsoletes issues: - #1474 Schema name vs client wrapper (CreateChatCompletionResponse) - #1713 Schema name vs client wrapper (CreateBlueprintResponse) - #1450 Schema name vs client wrapper (DeleteBusinessResponse) - #2097 Path response type vs schema definition (Status) - #255 Endpoint path vs response type (QueryResponse) - #899 Duplicate types from response wrapper vs schema (AccessListResponse) - #1357 Schema vs operationId response (ListAssistantsResponse, OpenAI spec) - #254 Cross-section: requestBodies vs schemas (Pet) - #407 Cross-section: requestBodies vs schemas (myThing) - #1881 Cross-section: requestBodies with multiple content types Obsoletes PRs: - #292 Parameter structures params postfix (superseded by context suffix) - #1005 Fix generate equals structs (superseded by multi-pass resolution) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> EOF )
Configuration menu - View commit details
-
Copy full SHA for 914bfd7 - Browse repository at this point
Copy the full SHA 914bfd7View commit details -
Configuration menu - View commit details
-
Copy full SHA for 1d561ff - Browse repository at this point
Copy the full SHA 1d561ffView commit details -
fix: apply collision strategies in global phases to prevent oscillation
When multiple content types map to the same short suffix (e.g., application/json, application/merge-patch+json, and application/json-patch+json all mapping to "JSON"), the per-group strategy cascade caused an infinite oscillation: context suffix appended "RequestBody", then content type suffix appended "JSON", then context suffix fired again because the name no longer ended in "RequestBody", ad infinitum. Fix by restructuring resolveCollisions to apply each strategy as a global phase: exhaust one strategy across ALL colliding groups (re-checking for new collisions after each pass) before advancing to the next strategy. This ensures numeric fallback is reached when earlier strategies cannot disambiguate. Also fix resolvedNameForComponent to accept an optional content type for exact matching, so each media type variant of a requestBody or response gets its own resolved name instead of all variants receiving whichever name the map iterator returns first. Adds Pattern H test case (TMF622 scenario from PR #2213): a component that exists in both schemas and requestBodies where the requestBody has 3 content types that all collapse to the "JSON" short name. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 7c90e0b - Browse repository at this point
Copy the full SHA 7c90e0bView commit details -
Configuration menu - View commit details
-
Copy full SHA for c1245c2 - Browse repository at this point
Copy the full SHA c1245c2View commit details -
test: add Pattern I for inline response with x-go-type $ref properties
Add test case from oapi-codegen-exp#14: an inline response object whose properties $ref component schemas with x-go-type: string. In the experimental rewrite (libopenapi), this caused duplicate type declarations because libopenapi copies extensions from $ref targets. V2 (kin-openapi) handles this correctly, but the test guards against future regressions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for b7eb753 - Browse repository at this point
Copy the full SHA b7eb753View commit details -
fix: resolve type name mismatches for multi-content-type responses
When a component response has multiple JSON content types (e.g., application/json, application/json-patch+json, application/merge-patch+json), three bugs produced uncompilable code: 1. Duplicate inline type declarations: GenerateGoSchema was called with a path of [operationId, responseName] (or [responseName] in the component phase), which doesn't include the content type. When multiple content types share oneOf schemas with inline elements, they produce identically-named AdditionalTypes. If the schemas differ, the result is conflicting declarations; if they're the same, duplicate declarations. Fix: include a mediaTypeToCamelCase(contentType) segment in the schema path when jsonCount > 1, giving each content type's inline types unique names. This is guarded by jsonCount > 1 for backward compatibility. 2. Undefined types in unmarshal code: GetResponseTypeDefinitions used RefPathToGoType to resolve $ref paths like #/components/responses/200Resource_Patch, but without content type context. resolvedNameForComponent fell into a non-deterministic prefix match, returning an arbitrary per-content-type base name that didn't match any defined type when mediaTypeToCamelCase was appended. Fix: add resolvedNameForRefPath helper that parses the $ref path and delegates to resolvedNameForComponent with the specific content type for exact matching. 3. Mismatched types in response struct fields: same root cause as bug 2 — the struct field types were derived from the same non-deterministic resolution path. Additionally, promote AdditionalTypes from GenerateTypesForResponses and GenerateTypesForRequestBodies to the top-level type list, matching the existing pattern in GenerateTypesForSchemas. Without this, inline types (e.g., oneOf union members, nested objects with additionalProperties) defined inside response/requestBody schemas were silently dropped from the output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 20753f4 - Browse repository at this point
Copy the full SHA 20753f4View commit details -
Configuration menu - View commit details
-
Copy full SHA for 5e3fede - Browse repository at this point
Copy the full SHA 5e3fedeView commit details -
fix: propagate user name overrides through codegen
The collision resolver had two bugs when resolve-type-name-collisions was enabled: 1. x-go-name was ignored: generateCandidateName() never consulted the x-go-name extension, so schemas/responses/requestBodies/parameters/ headers with explicit Go name overrides would lose them during collision resolution. 2. Client wrapper names bypassed the name normalizer: generateCandidateName() used UppercaseFirstCharacter(operationID) instead of SchemaNameToTypeName(operationID), so configured normalizers (e.g. ToCamelCaseWithInitialisms) were not applied to client response wrapper type names. Changes: - Add GoNameOverride field to GatheredSchema, populated from x-go-name on the parent container (schema, response, requestBody, parameter, header) when the component is not a $ref - Add extractGoNameOverride() helper to read x-go-name from extensions - Add Pinned field to ResolvedName; pinned names are returned as-is from generateCandidateName() and skipped by all collision resolution strategies (context suffix, content type, status code, param index, numeric fallback) - Fix client wrapper candidate name to use SchemaNameToTypeName() - Add unit tests for GoNameOverride population and pinning behaviour - Add integration test patterns K/L/M (x-go-name on schema, response, and requestBody) and regenerate Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for a46bd1a - Browse repository at this point
Copy the full SHA a46bd1aView commit details
Commits on Mar 2, 2026
-
Configuration menu - View commit details
-
Copy full SHA for 0f2f02a - Browse repository at this point
Copy the full SHA 0f2f02aView commit details -
Configuration menu - View commit details
-
Copy full SHA for 6632b8a - Browse repository at this point
Copy the full SHA 6632b8aView commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff main...type-name-default