experimental: merge allOf member extensions before type generation#22
Merged
mromaszewicz merged 1 commit intomainfrom Feb 14, 2026
Merged
experimental: merge allOf member extensions before type generation#22mromaszewicz merged 1 commit intomainfrom
mromaszewicz merged 1 commit intomainfrom
Conversation
Refactor allOf type generation to merge extensions from all allOf members
into a composite before deciding what code to generate, mirroring V2's
MergeSchemas approach. This was surfaced by the issue 1957 test, which
uses the standard OpenAPI 3.0 pattern of combining a $ref with
extension-only allOf members:
id:
allOf:
- $ref: '#/components/schemas/ID' # has x-go-type
- x-go-type-skip-optional-pointer: true # extension-only
Previously, V3 preserved the allOf structure as-is, so
generateAllOfType() only collected struct fields from each member. When a
$ref target was a type-override alias (no struct properties), there were
no fields to collect, producing an empty struct. Extensions on allOf
members were also never propagated to the parent field.
The fix adds three pieces:
- mergeExtensions(dst, src) in extension.go: field-by-field merge helper
for the Extensions struct (later values win).
- mergeAllOfExtensions() + hasAnyFields() in codegen.go: iterates allOf
member descriptors, resolves $ref targets from the schema index, and
merges all extensions. generateAllOfType() now calls this at the top
and, when the composite has no struct fields but carries a TypeOverride,
emits a type alias instead of an empty struct.
- GenerateStructFields() in typegen.go: when a property is itself an
allOf, merges extensions from its allOf members into the property's
extensions, so x-go-type-skip-optional-pointer propagates to the
field declaration in the parent struct.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refactor allOf type generation to merge extensions from all allOf members into a composite before deciding what code to generate, mirroring V2's MergeSchemas approach. This was surfaced by the issue 1957 test, which uses the standard OpenAPI 3.0 pattern of combining a $ref with extension-only allOf members:
Previously, V3 preserved the allOf structure as-is, so generateAllOfType() only collected struct fields from each member. When a $ref target was a type-override alias (no struct properties), there were no fields to collect, producing an empty struct. Extensions on allOf members were also never propagated to the parent field.
The fix adds three pieces:
mergeExtensions(dst, src) in extension.go: field-by-field merge helper for the Extensions struct (later values win).
mergeAllOfExtensions() + hasAnyFields() in codegen.go: iterates allOf member descriptors, resolves $ref targets from the schema index, and merges all extensions. generateAllOfType() now calls this at the top and, when the composite has no struct fields but carries a TypeOverride, emits a type alias instead of an empty struct.
GenerateStructFields() in typegen.go: when a property is itself an allOf, merges extensions from its allOf members into the property's extensions, so x-go-type-skip-optional-pointer propagates to the field declaration in the parent struct.