This repository is hosted on bintray, which will shut down on May 1st, 2021. After that date this library will no longer be directly available.
You may still fork or download this repository for your own use.
KotlinBard is a collection of extension functions for KotlinPoet to provide a fluent kotlin DSL for kotlin code generation.
KotlinPoet's first example is generated with the following:
val file = buildFile("", "HelloWorld") {
val greeterClass = ClassName("", "Greeter")
addClass(greeterClass) {
primaryConstructor {
addParameter("name", String::class)
}
addProperty("name", String::class) {
initializer("name")
}
addFunction("greet") {
addStatement("println(%P)", "Hello, \$name")
}
}
addFunction("main") {
addParameter("args", String::class, VARARG)
addStatement("%T(args[0]).greet()", greeterClass)
}
}
file.writeTo(System.out)
Fun fact: to cover all of KotlinPoet's functions, KotlinBard uses code generation to generate many extension functions -- it uses a previous version of itself to generate itself!
val file = buildFile {
addClass(...){ ... }
addInterface(...){ ... } //Each variant of TypeSpec and FunSpec have separate functions
addTypeAlias(...){ ... }
}
val annotation = buildAnnotation(...){ ... } //AnnotationSpec
val annotationType = buildAnnotationClass(...){ ... } //TypeSpec that is an annotation class
//Each type of Spec has its own function
val enum = buildEnum(...){ ... }
val intf = buildInterface(...){ ... }
val constructor = buildContructor {}
val getter = buildGetter {}
val newClass = klass.modify(name = newName) { ... }
val aBlock = codeBlock("println(%S)", "Hello, weird world")
//or, for a more inline syntax:
val aBlock = "println(%S)".codeFmt("Hello, weird world")
val file = buildFile("", "File") {
addImport(String::class)
addClass("Foo") {
addImport(Int::class) //compile error
}
}
val function = buildFunction("analyzeTaco") {
addCode { //functions are defined in the CodeBlockBuilder scope
controlFlow("taco.let") {
addStatement("println(it)")
}
`if`("taco.isSpicy()") {
addStatement("println(%S)", "spicy!!")
}.`else if`("me.isHungry") {
addStatement("eat(taco)")
} `else` {
addStatement("saveForLater(taco)")
}
`do` {
addStatement("makeTaco()")
}.`while`("tacos < 5")
`for`("taco in tacos") {
addStatement("println(%P)", "taco information: \$taco")
}
`when`("taco") {
"is SpicyTaco" - {
addStatement("println(%S)", "Spicy!!")
}
"else" - "eat(%L)".codeFmt("taco")
}
}
}
This generates the following:
fun analyzeTaco() {
taco.let {
println(it)
}
if (taco.isSpicy()) {
println("spicy!!")
} else if (me.isHungry) {
eat(taco)
} else {
saveForLater(taco)
}
do {
makeTaco()
} while (tacos < 5)
for (taco in tacos) {
println("""taco information: $taco""")
}
when (taco) {
is SpicyTaco -> {
println("Spicy!!")
}
else -> eat(taco)
}
}
val mySetter = buildSetter("value") {
addStatement("field = value")
}
val prop = buildProperty("prop", String::class) {
mutable()
setter("value") {
addStatement("println(%S)", "setting!")
addStatement("field = value")
}
}
val myTypeVarName = TypeVariableName("T")
.reified
.plusTag(ATag::class, myTag)
val myTypeDecName = Int::class.asTypeName()
.plusAnnotations(annotationSpec)
With gradle:
repositories {
jcenter()
}
dependencies {
implementation("io.github.enjoydambience:kotlinbard:0.4.0")
}