Skip to content

C1: Kotlin identifier utilities - #12

Merged
milyin merged 1 commit into
docs/validation-umbrellafrom
step/c1-ident-utilities
Aug 6, 2026
Merged

C1: Kotlin identifier utilities#12
milyin merged 1 commit into
docs/validation-umbrellafrom
step/c1-ident-utilities

Conversation

@milyin

@milyin milyin commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Step C1 of #6. Stacked on #11 — Part C begins.

A program generating Kotlin gets its names from somewhere else — a Rust field, a
C symbol, a JSON key — and some are never legal Kotlin. This crate writes the
file but offered nothing for dealing with that, so every consumer reimplements
it. prebindgen-jni has private copies of three of these today.

Function Purpose
is_valid_kotlin_ident legal, non-keyword, writable bare
is_kotlin_hard_keyword / KOTLIN_HARD_KEYWORDS the 28 reserved words
mangle_kotlin_ident my-namemy_name, 2fast_2fast, objectobject_, ""_
mangle_kotlin_package / is_valid_kotlin_package the same, per dot-separated segment
escape_kotlin_ident the other strategy: `object` — keeps the name instead of changing it

Two decisions worth reviewing

Soft keywords are deliberately absent from the keyword list. data,
value, sealed, inline, operator, companion are contextual in Kotlin
and are valid identifiers — mangling them would be wrong. A test pins that,
because it is the easy mistake to make when transcribing a keyword list.

Escaping is offered alongside mangling, not instead of it. Mangling changes
the name; back-ticks keep it. Which one a generator wants is its own business,
so both are available. escape_kotlin_ident also strips the characters that are
illegal even inside back-ticks (`, line breaks, and the JVM's
.;[]/<>:\), which is the part that is easy to get wrong.

Verification

Two properties are tested rather than assumed, over a table of awkward inputs
(empty, leading digit, punctuation-only, non-ASCII, keywords): mangling always
produces a valid identifier, and mangling is idempotent. Same for packages.
Every public function carries a doctest — 6 doctests, 59 tests, clippy clean.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a first-class set of Kotlin identifier utilities to kotlin-codegen so generators can reliably validate, sanitize, and escape names derived from external sources (Rust fields, C symbols, JSON keys) without each consumer reimplementing the logic.

Changes:

  • Introduces src/ident.rs implementing hard-keyword detection, identifier/package validation, deterministic idempotent mangling, and backtick escaping.
  • Exposes the new identifier utilities from the crate root (src/lib.rs) as part of the public API.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/lib.rs Adds the ident module and re-exports the new identifier/public keyword APIs.
src/ident.rs Implements Kotlin identifier/package helpers with doctests and unit tests for keyword behavior and mangling/escaping properties.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

A program generating Kotlin gets its names from somewhere else — a Rust
field, a C symbol, a JSON key — and some of those are never legal
Kotlin. This crate writes the file but offered nothing for dealing with
that, so every consumer has to reimplement it.

Add the primitives:

  * is_valid_kotlin_ident / is_kotlin_hard_keyword / KOTLIN_HARD_KEYWORDS
  * mangle_kotlin_ident — deterministic, idempotent
  * mangle_kotlin_package, is_valid_kotlin_package
  * escape_kotlin_ident — the back-tick strategy, which keeps the name
    instead of changing it

Soft and modifier keywords (`data`, `value`, `inline`, `operator`) are
deliberately absent from the keyword list: they are contextual and are
valid identifiers, so mangling them would be wrong. A test pins that.

Two properties are tested rather than assumed: mangling always yields a
valid identifier, and is idempotent, over a table of awkward inputs.
Every function carries a doctest.
@milyin
milyin force-pushed the step/a5-external-body branch from 75908e0 to d1c977f Compare August 6, 2026 11:40
@milyin
milyin force-pushed the step/c1-ident-utilities branch from a84bed6 to 00a7282 Compare August 6, 2026 11:40
@milyin
milyin changed the base branch from step/a5-external-body to docs/validation-umbrella August 6, 2026 11:41
@milyin
milyin merged commit 0cb545d into docs/validation-umbrella Aug 6, 2026
0 of 2 checks passed
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.

2 participants