fix(kotlin): forbid enum case names equal to the enum type name#2999
Merged
Conversation
Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
The new priority fixture kotlin-enum-class-case-collision.json is a top-level JSON array, which the kotlinx renderer emits as `typealias TopLevel = JsonArray<T>` — invalid Kotlin, since kotlinx's JsonArray takes no type arguments. This is a pre-existing, documented kotlinx limitation (see the ~40 existing top-level-array entries in this same skipJSON block and the TODO in KotlinXRenderer.ts), unrelated to the enum-naming fix in this PR. The enum case/class name-collision fix lives in the shared KotlinRenderer base class and remains covered by the kotlin (klaxon) and kotlin-jackson fixture runs, which handle top-level arrays as `class TopLevel : ArrayList<T>` and do run this fixture. Co-Authored-By: Claude <noreply@anthropic.com>
#1815) The new priority JSON input kotlin-enum-class-case-collision.json is a top-level array. quicktype's TypeScript --just-types renderer collapses a top-level array's element type onto the top-level name itself instead of emitting an array alias, so the C# code generated from that intermediate TypeScript expects a JSON object and throws when run against the original array JSON. This is the same pre-existing top-level-array limitation already covered by ~70 other entries in skipTypeScriptTests; add this fixture alongside them. Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.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.
Bug
Kotlin enum-typed output could generate an invalid enum constant with the
same name as its enclosing enum class, e.g.:
This happens when a JSON string value with no identifier-safe characters
(e.g. whitespace-only or a NUL byte) legalizes to an empty name. quicktype's
naming falls back to
Emptyfor such values, and when two case valuescollide on that fallback,
ConvenienceRenderer.makeNameForEnumCaseproposesan "alternative" name of the form
${enumCombinedName}_${caseName}todisambiguate them. Kotlin's name-styling strips all non-identifier
characters from that alternative, so a value like
"Category_ "collapsesdown to just
"Category"— colliding, silently, with the enum type's ownname.
Root cause
KotlinRenderer.forbiddenForEnumCases(inpackages/quicktype-core/src/language/Kotlin/KotlinRenderer.ts) didn'tforbid the enum's own type name from being reused as a case name, so nothing
caught this second-order collision.
Fix
KotlinRenderer.forbiddenForEnumCasesnow includes the enum's ownNameinits forbidden-names list, forcing the namer to keep looking for a
non-colliding alternative instead of silently reusing the enum's own name.
This follows the same pattern already used by
CSharpRendererfor objectproperties (
forbiddenForObjectPropertiesforbids the class's own name).Test coverage
Added
test/inputs/json/priority/kotlin-enum-class-case-collision.json, aJSON fixture (runs for every language, per
priority/fixture conventions)with repeated whitespace-only and empty-string values for a
categoryproperty, enough to trigger quicktype's string-to-enum inference and
reproduce the exact class-name/case-name collision from the issue.
Verification
npm run buildpasses.npm run test:unitpasses (163/163).node dist/index.js --src <repro.json> --src-lang json --lang kotlin --framework jackson --top-level SomeClass,confirmed the generated
enum class Category { Category(...), ... }collision, then confirmed after the fix the case is renamed (e.g. to
Purple) instead of colliding with the class name.generation manually — all produce non-colliding case names.
QUICKTEST=true FIXTURE=python script/testpasses (62/62), confirming thenew shared JSON fixture doesn't break other languages.
was not run locally because
kotlinc/kotlinare not installed in thisenvironment; CI will exercise
FIXTURE=kotlinand the other Kotlinvariants (
kotlin-jackson,kotlinx) against the new fixture.Fixes #1815.
🤖 Generated with Claude Code