Skip to content

fix(ir): populate displayName for discriminated union variants#16691

Open
devin-ai-integration[bot] wants to merge 4 commits into
mainfrom
devin/1782329369-fix-union-displayname
Open

fix(ir): populate displayName for discriminated union variants#16691
devin-ai-integration[bot] wants to merge 4 commits into
mainfrom
devin/1782329369-fix-union-displayname

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Description

Discriminated union variants derived from named type references (e.g. $ref: '#/components/schemas/VideoInput') were displaying as generic "object" in docs because displayName was always null for these variants. This fix auto-infers displayName from the type reference name when no explicit display name is set.

Changes Made

  • In convertDiscriminatedUnionTypeDeclaration.ts: when a union variant has no explicit displayName and its value type is a named reference, derive displayName via titleCase(getOriginalName(name)) (e.g. VideoInput"Video Input")
  • Added test fixture anyof-ref-displayname with a minimal OpenAPI spec reproducing the issue
  • Updated IR snapshots (unions.json, property-access.json, reserved-keywords.json, exhaustive.json) and ETE-test snapshots to reflect the newly populated displayName values
  • Added changelog entry fix-union-variant-displayname.yml

Testing

  • Unit tests added/updated — new anyof-ref-displayname fixture validates the fix
  • IR generator tests pass (382 passed)
  • ETE-test snapshots updated
  • All CI checks passing (206 passed, 0 failed)

Link to Devin session: https://app.devin.ai/sessions/7025b4dcebcd41c6946a314095ad8de3


Open in Devin Review

Co-Authored-By: rishabh <rishabh@buildwithfern.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

Open in Devin Review

Comment on lines +62 to +68
const explicitDisplayName = getDisplayName(rawSingleUnionType);
const displayName =
explicitDisplayName != null
? explicitDisplayName
: parsedValueType.type === "named"
? titleCase(getOriginalName(parsedValueType.name))
: undefined;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🚩 Behavioral change: all named-type union variants now get auto-populated displayName

Previously, displayName for union variants was only set when explicitly provided via display-name in the Fern definition (always null otherwise). Now every variant referencing a named type automatically gets a displayName derived from the type's original name. This is a semantic change to the IR output that affects all discriminated unions across all generators and docs consumers. The snapshots show ~80+ null → string changes across many test definitions. While additive (the field already exists in the schema), downstream consumers that distinguish between null and a string value for displayName could behave differently. The changelog entry (packages/cli/cli/changes/unreleased/fix-union-variant-displayname.yml) documents this as a fix.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is intentional. The displayName field already exists in the IR schema and was always null for union variants without an explicit display name. The change is additive — downstream consumers that don't use displayName are unaffected, and those that do (like the docs renderer) will now show meaningful schema names instead of "object". The docs UI already handles both null (falls back to "object") and string values, so this change improves the display without breaking anything.

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Docs Generation Benchmark Results

Comparing PR branch against median of 5 nightly run(s) on main (latest: 2026-06-24T05:18:39Z).

Fixture main PR Delta
docs 222.2s (n=5) 203.3s (35 versions) -18.9s (-8.5%)

Docs generation runs fern generate --docs --preview end-to-end against the benchmark fixture with 35 API versions (each version: markdown processing + OpenAPI-to-IR + FDR upload).
Delta is computed against the nightly baseline on main.
Baseline from nightly run(s) on main (latest: 2026-06-24T05:18:39Z). Trigger benchmark-baseline to refresh.
Last updated: 2026-06-25 04:24 UTC

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

SDK Generation Benchmark Results

Comparing PR branch against median of 5 nightly run(s) on main (latest: 2026-06-24T05:18:39Z).

Full benchmark table (click to expand)
Generator Spec main (generator) main (E2E) PR (generator) Delta
csharp-sdk square 76s (n=5) 109s (n=5) 70s -6s (-7.9%)
go-sdk square 134s (n=5) 283s (n=5) 125s -9s (-6.7%)
java-sdk square 214s (n=5) 285s (n=5) 194s -20s (-9.3%)
php-sdk square 59s (n=5) 85s (n=5) 54s -5s (-8.5%)
python-sdk square 130s (n=5) 241s (n=5) 132s +2s (+1.5%)
ruby-sdk-v2 square 92s (n=5) 129s (n=5) 82s -10s (-10.9%)
rust-sdk square 183s (n=5) 174s (n=5) 162s -21s (-11.5%)
swift-sdk square 57s (n=5) 431s (n=5) 53s -4s (-7.0%)
ts-sdk square 236s (n=5) 239s (n=5) 221s -15s (-6.4%)

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 fern generate). main (E2E): full customer-observable time including build/test scripts (nightly baseline, informational). Delta is computed against generator-only baseline.
⚠️ = generation exited with a non-zero exit code (timing may not reflect a successful run).
Baseline from nightly runs on main (latest: 2026-06-24T05:18:39Z). Trigger benchmark-baseline to refresh.
Last updated: 2026-06-25 04:26 UTC

devin-ai-integration Bot and others added 3 commits June 24, 2026 20:02
Co-Authored-By: rishabh <rishabh@buildwithfern.com>
Co-Authored-By: rishabh <rishabh@buildwithfern.com>
…ants

Co-Authored-By: rishabh <rishabh@buildwithfern.com>
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.

0 participants