kotlin-codegen 0.2.0

A declaration model and renderer for generating Kotlin source code
Documentation
# kotlin-codegen

A declaration model and renderer for generating Kotlin source code.

Declarations (files, classes, functions, properties, parameters, types,
annotations) are typed model values (`KtFile`, `KtClass`, `KtFun`, `KtType`,
…); imports and formatting derive from the model automatically via
`ImportSet`. Statement **bodies** stay raw Kotlin text, structured through the
indentation-aware `KtCode` builder rather than modeled as a full expression AST.

You build a `KtFile` out of typed pieces, and the renderer produces
formatted, import-complete Kotlin source text plus a file-writer that lays
the result out on disk.

## Examples

Two runnable examples, both checked against stored output by
`tests/examples.rs` so they cannot rot:

```sh
cargo run --example showcase   # every construct the model can emit
cargo run --example invalid    # a broken model, and what the validator says
```

`showcase` is a small but complete generator — it builds `KtFile` fragments,
merges them so each package collapses to one file, and renders classes,
objects, enums, data and value classes, sealed interfaces, `fun interface`s,
type aliases, extension functions, properties with accessors and delegates,
`external` natives, and raw blocks. `invalid` shows the two ways a mistake surfaces: as a diagnostic
from the validator, or as a builder that refuses to construct the value at all.

To accept an intended change to either output:

```sh
UPDATE_GOLDEN=1 cargo test --test examples   # then review the diff
```

## Catching mistakes before `kotlinc` does

A *program* builds the model, so the mistakes are program mistakes: a name
derived from a Rust field that happens to be `object`, two generated classes
that mangle to the same name, a branch that built an `object` where it meant a
`data class`. Without a check, those first surface when the Kotlin compiler
runs — often in a different build, against a generated file that gives no hint
about what produced it.

Two things address that.

**Bad shapes are mostly unbuildable.** The kinds carry their own data, so an
`object` has nowhere to put constructor parameters, a `value class` holds
exactly one property, a `data class` cannot have zero, a `companion object`
cannot be a top-level declaration, a class cannot construct two superclasses,
a `fun interface` method cannot have a body, and `external` cannot be combined
with one.

**What is left is validated.** `KtFile::validate()` walks the file, every class
body and every companion body and reports what the model can prove is wrong:
names that are not legal Kotlin identifiers, redeclarations (per scope, with
Kotlin's separate type / value / function namespaces, so real overloads pass),
and the shapes the types could not rule out. `merge_files` and `write_files`
run it and refuse to write.

It is deliberately **not** a Kotlin compiler: no type resolution, no parsing of
body text, and no check that could fire on correct output. `ValidationPolicy`
sets any check to error, warning or off — `ValidationPolicy::warn_all()` is the
way to adopt validation in a generator that already produces output.

## Kotlin identifiers

Generated names come from somewhere else — a Rust field, a C symbol, a JSON
key — and some are never legal Kotlin. `is_valid_kotlin_ident`,
`mangle_kotlin_ident` (`my-name` → `my_name`, `object` → `object_`) and
`escape_kotlin_ident` (`` `object` ``, keeping the name instead of changing it)
are available for that, along with their package-path equivalents.

## Why

This crate was made for the [prebindgen-jni](https://crates.io/crates/prebindgen-jni)
library, which generates JNI bindings for Rust libraries. The existing
[kotlin-poet-rs](https://crates.io/crates/kotlin-poet-rs) crate was not used
for Not-Invented-Here reasons and because full control over the code generator was needed.

This crate will be supported as long as `prebindgen-jni` is alive.

## Status

Early, dependency-free, and intentionally minimal. No macros, no derive, no
external crates — just a plain declaration model, a renderer, and a validator.

## License

Licensed under either of

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE)
- MIT license ([LICENSE-MIT]LICENSE-MIT)

at your option.

## Releasing

Publishing is automated from GitHub Actions. See [RELEASING.md](RELEASING.md)
for the release process and [CHANGELOG.md](CHANGELOG.md) for release notes.