GraphNameAllocator
Central name allocator that produces collision-safe Kotlin identifiers while preserving original GraphQL wire names for serialization annotations.
Per-Scope Allocation
Create one allocator instance per scope (e.g. per class, per operation) to ensure deterministic collision resolution within that scope. Each allocator tracks allocated names independently, so collisions across scopes are allowed (different classes may have properties with the same Kotlin name but different GraphQL names).
Usage
val allocator = GraphNameAllocator()
val name = allocator.allocatePropertyName("private")
// GeneratedName(kotlinName="privateValue", wireName="private")The GeneratedName.wireName is always the original GraphQL name, set before any keyword escaping or collision resolution. It is never derived from GeneratedName.kotlinName. This invariant guarantees that @SerialName("wireName") always produces the correct JSON key matching the GraphQL schema, regardless of Kotlin keyword escaping or collision resolution applied to kotlinName.
Keyword Escape Policy
Hard Kotlin keywords and visibility modifiers are escaped by appending a Value suffix (e.g. private ->privateValue). Digits at the start are prefixed with _. Backticks are intentionally not used. See NamePolicy for the complete keyword list and rationale.
Keyword pre-allocation in the underlying KotlinPoet NameAllocator is disabled because NamePolicy handles keyword escaping before the suggestion reaches the allocator. If pre-allocation were enabled, KotlinPoet would pre-allocate soft keywords like data and private, causing false-positive collision suffixes on escaped names.
Collision Resolution
When two distinct GraphQL names produce the same Kotlin candidate (after keyword escaping), KotlinPoet's NameAllocator appends deterministic underscore-based suffixes (foo, foo_, foo__). Resolution is:
Scoped per allocator instance
Deterministic for the same input order
Applied after keyword escaping
Wire Name Example
val allocator = GraphNameAllocator()
// Keyword escaped
val name1 = allocator.allocatePropertyName("private")
assertEquals("privateValue", name1.kotlinName)
assertEquals("private", name1.wireName) // original preserved for @SerialName
// Collision (same root after escaping)
val name2 = allocator.allocatePropertyName("myField")
val name3 = allocator.allocatePropertyName("my_field")
// name2.kotlinName != name3.kotlinName (one gets suffix)
// Both retain their distinct wire names for @SerialNameSince
1.0
See also
Functions
Allocates a collision-safe Kotlin class name (PascalCase) for the given GraphQL graphqlName.
Allocates a collision-safe Kotlin enum constant name (SCREAMING_SNAKE_CASE) for the given GraphQL enum graphqlValue.
Allocates a collision-safe Kotlin property name (lowerCamelCase) for the given GraphQL graphqlName.