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 @SerialName

Since

1.0

See also

Constructors

Link copied to clipboard
constructor()

Functions

Link copied to clipboard

Allocates a collision-safe Kotlin class name (PascalCase) for the given GraphQL graphqlName.

Link copied to clipboard

Allocates a collision-safe Kotlin enum constant name (SCREAMING_SNAKE_CASE) for the given GraphQL enum graphqlValue.

Link copied to clipboard

Allocates a collision-safe Kotlin property name (lowerCamelCase) for the given GraphQL graphqlName.