Skip to content

fix(naming): preserve word-initial acronyms in pascal-upper-acronyms style#3036

Open
schani wants to merge 8 commits into
masterfrom
agent/fix-issue-1363
Open

fix(naming): preserve word-initial acronyms in pascal-upper-acronyms style#3036
schani wants to merge 8 commits into
masterfrom
agent/fix-issue-1363

Conversation

@schani

@schani schani commented Jul 20, 2026

Copy link
Copy Markdown
Member

Bug

With --type-style pascal-case-upper-acronyms, a word-initial acronym in a
type name was incorrectly downcased to just its first letter capitalized,
while the same acronym elsewhere in the name (medial position) was correctly
kept fully upper-case.

Example from the issue: a JSON Schema with titles SCUBAWaypoint and
SCUBAManeuver, generated with C++ + pascal-case-upper-acronyms, produced
ScubaWaypoint / ScubaManeuver instead of the expected SCUBAWaypoint /
SCUBAManeuver. Further testing confirmed a mixed case: IDCardHTTP was
rendered as IdCardHTTP — the medial acronym HTTP stayed upper-case, but
the word-initial acronym ID was incorrectly downcased.

Root cause

In packages/quicktype-core/src/support/Strings.ts, makeNameStyle builds
per-style WordStyle functions for the first word vs. the rest, and for
acronym words vs. non-acronym words. The "pascal" and
"pascal-upper-acronyms" naming styles shared the same case block and both
set firstWordAcronymStyle = firstUpperWordStyle (capitalizes only the first
letter). That's correct for plain "pascal" (acronyms aren't specially
preserved there), but wrong for "pascal-upper-acronyms", where a
word-initial acronym should use allUpperWordStyle — the same style already
used for non-initial acronym words in that mode (restAcronymStyle = allUpperWordStyle).

Fix

Split the "pascal-upper-acronyms" case out of the shared "pascal" case
and set firstWordAcronymStyle = allUpperWordStyle for it, while
firstWordStyle (used for a non-acronym first word) keeps
firstUpperWordStyle. "camel-upper-acronyms" is untouched — camelCase
identifiers conventionally start lowercase regardless of whether the first
word is an acronym, so its existing firstWordAcronymStyle = allLowerWordStyle was already correct and is out of scope for this issue.

Test coverage

  • Added test/inputs/schema/upper-acronym-names.schema (+ .1.json sample),
    a JSON Schema with a word-initial-acronym type (SCUBAWaypoint,
    SCUBAManeuver) and a mixed word-initial+medial-acronym type
    (IDCardHTTP), modeled directly on the issue's repro.
  • Added a new fixture schema-cplusplus-upper-acronyms in test/fixtures.ts
    / test/languages.ts that generates C++ from that schema with
    --type-style pascal-case-upper-acronyms --member-style camel-case-upper-acronyms.
  • Added test/fixtures/cplusplus/acronym_names.cpp, a small driver file that
    references the generated types by their exact expected names
    (quicktype::SCUBAWaypoint, quicktype::SCUBAManeuver,
    quicktype::IDCardHTTP) — so the fixture fails to compile if the naming
    regresses, not just at runtime.

Verification

  • Confirmed the new fixture fails to compile against the unfixed code
    (g++ reports 'SCUBAWaypoint' is not a member of 'quicktype'; did you mean 'ScubaWaypoint'?, etc.), proving the test actually exercises the bug.
  • Applied the fix and confirmed the fixture passes:
    QUICKTEST=true FIXTURE=schema-cplusplus-upper-acronyms script/test → 1/1.
  • Re-ran the original issue repro (--src-lang schema --lang c++ --type-style pascal-case-upper-acronyms --member-style camel-case-upper-acronyms) and confirmed it now emits SCUBAManeuver /
    SCUBAWaypoint.
  • Confirmed no regression: plain pascal-case still downcases
    (IDCardHTTP -> IdCardHttp), and camel-case-upper-acronyms
    member/property names are unaffected by this change.
  • npm run build passes.
  • CI will run the full fixture/unit suite across all languages.

Fixes #1363

🤖 Generated with Claude Code

schani and others added 4 commits July 20, 2026 18:16
…style (#1363)

Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
The upper-acronym-names.schema fixture was a top-level array, which
several language drivers can't handle: kotlinx renders top-level arrays
as `typealias TopLevel = JsonArray<T>` (doesn't compile), and the
typescript-zod driver can't locate the top-level schema when the array's
titled item type is named `SCUBAWaypointSchema` instead of
`TopLevelElementSchema` ("No schema found"). The CI failure surfaced on
kotlinx first; fail-fast hid the rest.

The top-level array is incidental to the acronym-naming bug being tested
(word-initial acronyms in type names). Wrapping the waypoints in a
top-level object exercises the identical naming path — C++ still emits
`SCUBAWaypoint`/`SCUBAManeuver`/`IDCardHTTP` with the fix and downcases
them without it — while working across all language drivers.

Co-Authored-By: Claude <noreply@anthropic.com>
…1363)

cjson's generated deserializer does not validate enum values (a known,
already-documented limitation shared with enum.schema, enum-large.schema,
etc.), so the new upper-acronym-names.schema's .1.fail.enum.json sample
round-trips instead of being rejected. Add it to the shared
skipsEnumValueValidation list, matching the identical precedent in
commit 349bc78 for all-of-additional-properties-false.schema.

Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
@schani

schani commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

Reopening to retrigger CI for the latest commit (no new run was generated for c0b8c24).

@schani schani closed this Jul 21, 2026
@schani schani reopened this Jul 21, 2026
schani and others added 4 commits July 21, 2026 10:04
# Conflicts:
#	test/fixtures.ts
#	test/languages.ts
The schema-cplusplus-upper-acronyms fixture was never listed in the CI
matrix, so it never ran, and acronym_names.cpp included the multi-source
header TopLevel.hpp while the fixture generates single-source output
(quicktype.hpp), causing a compile failure when the fixture is actually
executed.

Include the generated single-source header and add the fixture to the
cplusplus CI matrix entry so the acronym-preservation check runs.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Generated-output differences

40 files differ — 0 modified, 40 new, 0 deleted
4198 changed lines — +4198 / −0

Open the generated-output report →

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.

C++ identifiers generated with -upper-acronyms have lowercase word-initial acronyms

1 participant