The original KotlinBard was hosted on bintray, which shut down on May 1st, 2021.
This fork republishes it to maven central.
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 {
mavenCentral()
}
dependencies {
implementation("com.faendir:kotlinbard:0.4.0")
}