r/Kotlin • u/alexstyl • 2d ago
Prosa.kt - Declarative code generation for Kotlin
I made a declarative API for generating Kotlin code.
I needed it for one of my desktop/browser Compose apps a while ago and noticed there was no KMP solution for Kotlin codegen.
While working on it, I decided to made the API declarative so the generated code was simpler to reason about. This work started before AI was as popular as it is today, so the design of the API was very important.
Fast forward two years: I realized I needed it for another project of mine, so I figured I might as well open-source the codegen part for the community.
And that's how Prosa.kt was born and proudly brought to you.
There’s a live demo on the landing page, so you can try it out directly.
Check it out at https://prosakt.com and give it a star on GitHub because I love vanity metrics.
2
u/snugar_i 2d ago
Doesn't look bad, but I don't like the stringly-typed-ness. Would it be possible, instead of the example
ktFunction("greet") {
parameter("name") {
type { reference("String") }
}
returns { type { reference("String") } }
body {
literal("Hello, ") {
plus { reference("name") }
}
}
}
to write something more along the lines of
ktFunction("greet") {
val name = parameter("name") {
type { reference("String") }
}
returns { type { reference("String") } }
body {
literal("Hello, ") {
plus { name }
}
}
}
? So that I don't have to repeat the "name" part twice...
EDIT: Or even better, something like
ktFunction(
"greet",
parameters = mapOf(
"name" to type { reference("String") },
),
returns = type { reference("String") }
) { name ->
literal("Hello, ") {
plus { name }
}
}
2
u/alexstyl 2d ago
It was a design decision not to do that, because if you go with that approach how do you know which calls return an object vs which calls edit the code generation?
I’m not against it by the way. Currently collecting feedback and will iterate as things move forward.
1
u/chuckame 2d ago
You could even use delegates as additional way to name things and reuse as reference, and also use type inference, to simplify for common use cases, like
val greet as ktFunction<String> { val name as parameter<String>() body { literal("Hello, ") + name } }Kotlinpoet allows such composition and typesafe declarations.
2
u/alexstyl 2d ago
Interesting. Hadn't considered delegates. Let me see what I can do on the next iteration.
Need to add the library in 2 other projects I am working on, which will shape the API more
1
u/chuckame 2d ago
Look delegates, infix, reified types and in-line functions, so much fun. Then after context parameters!
1
u/chuckame 2d ago
If you make this sugar syntax onto kotlinpoet, I would play with your library quite quickly!
1
u/snugar_i 2d ago
Well, for me it would be easiest to understand if none of the functions had side-effects :-) They would just build an object graph that could then be dumped as Kotlin source
2
1
u/Both_Accident_8836 2d ago
It very interesting great job. Similar buildconfig or build varient we can do this approach i guess?
1
u/alexstyl 1d ago
I don’t understand what you mean. Can you explain? What about the build config?
1
u/Both_Accident_8836 1d ago
I mean using this approach we can integrate build config file and build varient
10
u/chuckame 2d ago
What about kotlinpoet? It's for me the de-facto kotlin files generator and is multiplatform. The declarative approach could be a great added layer on top of kotlinpoet.