fix(go): preserve embedded struct and shadow fields in HandleExplicitFields - #17618
Conversation
…Fields Co-Authored-By: bot_apk <apk@cognition.ai>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
There was a problem hiding this comment.
AI Review Summary
The fix correctly generalizes the embed-pattern detection and indexes explicit-field bits against the embedded type. Main concerns: the explicit-field bit index no longer matches the embedded struct's field ordinal once unexported/explicitFields fields appear before other fields (pre-existing but now more visible), and the shadow lookup is O(n·m) with a closure that could be a map. Also worth noting the -/json:"-" name collision in jsonFieldName could cause an unintended shadow match.
- 🟡 2 warning(s)
- 🔵 1 suggestion(s)
To request another review, comment /ai-review on this pull request.
SDK Generation Benchmark ResultsComparing PR branch against median of 5 nightly run(s) on Full benchmark table (click to expand)
main (generator): generator-only time via --skip-scripts (includes Docker image build, container startup, IR parsing, and code generation — this is the same Docker-based flow customers use via |
…:"-" shadows; map-based shadow lookup Co-Authored-By: bot_apk <apk@cognition.ai>
Description
Linear ticket: N/A
Calling any generated
SetXxxsetter on a Go SDK type that also has date/date-time fields silently dropped most of the JSON body (and made offset-based auto-pagination loop forever).Generated
MarshalJSONfor such types builds a wrapperstruct { embed; StartDate *internal.DateTime ...; EndDate ... }.HandleExplicitFieldsonly recognized the embed pattern whenNumField() == 1, so multi-field wrappers fell into the "regular struct" branch:SetCount-> bit 2 -> wrapperEndDate->"end_date":null), andembedfield was skipped as unexported, so the whole embedded payload vanished.Fix:
HandleExplicitFieldsnow detects the embed byField(0).Anonymousregardless of field count, indexes bits against the embedded type, and builds a flat struct where each wrapper shadow field (matched by JSON name) replaces the embedded field it shadows.omitemptyis stripped from whichever field actually serializes (the shadow for date fields, the embedded field otherwise). Non-shadowing wrapper fields are appended. Fast path (explicitFields == nil || Sign() == 0) is unchanged.Changes Made
generators/go/internal/generator/sdk/internal/explicit_fields.go(embedded runtime template) — fix above; extractedjsonFieldName/removeOmitEmptyhelpersgenerators/go/internal/generator/sdk/internal/explicit_fields_test.go— newTestHandleExplicitFieldsShadowedWrapper: multi-field wrapper with non-date field set ({"count":7}), date field explicitly nil ("start_date":null), bit index beyond wrapper field count (SetOffset), mixed shadowed/non-shadowed. Existing 1-field-wrapper tests act as the regression guard.generators/go/internal/fern/ir/internal/explicit_fields.go— same file (kept in sync)seed/go-sdk/**/internal/explicit_fields{,_test}.go— snapshots updated (183 fixtures)generators/go/sdk/changes/unreleased/fix-explicit-fields-date-wrapper.yml— changelog entryTesting
go test ./...ingenerators/gopasses;go test ./internal/inseed/go-sdk/allofpassesLink to Devin session: https://app.devin.ai/sessions/c429338faac64d5ba771101848dd1fbf
Open in Devin Desktop: https://app.devin.ai/desktop/session/c429338faac64d5ba771101848dd1fbf?variant=devin