KotlinPoet 2.0 is here!

Lo! KotlinPoet 2.0 doth grace our realm!

William Shakespeare ChatGPT

KotlinPoet is an ergonomic Kotlin and Java API for generating Kotlin source files. Source code generation is a useful technique in scenarios that involve annotation processing or interacting with metadata files: popular libraries, such as SQLDelight and Moshi, use KotlinPoet to generate source code.

After originally releasing KotlinPoet 1.0 in 2018, today we’re announcing the next major version of the library - KotlinPoet 2.0!

We decided to keep KotlinPoet 2.0 source- and binary-compatible with 1.0 to make the migration as seamless as possible. That said, 2.0 ships with an important behavior change:

Spaces don’t wrap by default

KotlinPoet 1.x was designed to replace space characters with newline characters whenever a given line of code exceeded the length limit, so the following FunSpec:

val funSpec = FunSpec.builder("foo")
  .addStatement("return (100..10000).map { number -> number * number }.map { number -> number.toString() }.also { string -> println(string) }")
  .build()

Would be generated as follows, honoring the line length limit:

public fun foo(): Unit = (100..10000).map { number -> number * number }.map { number ->
  number.toString() }.also { string -> println(string) }

This usually led to slightly better code formatting, but could also lead to compilation errors in generated code. Depending on where this function occurred in the generated code, it could be printed out as follows:

public fun foo(): Unit = (100..10000).map { number -> number * number }.map { number -> number.toString() }.also
  { string -> println(string) } // Doesn't compile, "also {" has to be on one line!

Developers could mark spaces that aren’t safe to wrap with the · character, but the discoverability of this feature wasn’t great:

val funSpec = FunSpec.builder("foo")
  .addStatement("return (100..10000).map·{ number -> number * number }.map·{ number -> number.toString() }.also·{ string -> println(string) }")
  .build()

KotlinPoet 2.0 does not wrap spaces, even if the line of code they occur in exceeds the length limit. The newly introduced character can be used to mark spaces that are safe to wrap, which can improve code formatting:

val funSpec = FunSpec.builder("foo")
  .addStatement("return (100..10000).map { number ->♢number * number♢}.map { number ->♢number.toString()♢}.also { string ->♢println(string)♢}")
  .build()

The generated code here is similar to the original example:

public fun foo(): Unit = (100..10000).map { number -> number * number }.map { number ->
  number.toString() }.also { string -> println(string) }

The · character has been preserved for compatibility, but its behavior is now equivalent to thee regular space character.

Please let us know if you’re experiencing any issues with the new release by opening an issue in our issue tracker, or starting a discussion if you’d like to provide general feedback or are looking for help on using the library.

Get KotlinPoet 2.0 on GitHub today!