%T for Types¶
KotlinPoet has rich built-in support for types, including automatic generation of import
statements. Just use %T
to reference types:
val today = FunSpec.builder("today")
.returns(Date::class)
.addStatement("return %T()", Date::class)
.build()
val helloWorld = TypeSpec.classBuilder("HelloWorld")
.addFunction(today)
.build()
val kotlinFile = FileSpec.builder("com.example.helloworld", "HelloWorld")
.addType(helloWorld)
.build()
kotlinFile.writeTo(System.out)
That generates the following .kt
file, complete with the necessary import
:
package com.example.helloworld
import java.util.Date
class HelloWorld {
fun today(): Date = Date()
}
We passed Date::class
to reference a class that just-so-happens to be available when we’re
generating code. This doesn’t need to be the case. Here’s a similar example, but this one
references a class that doesn’t exist (yet):
val hoverboard = ClassName("com.mattel", "Hoverboard")
val tomorrow = FunSpec.builder("tomorrow")
.returns(hoverboard)
.addStatement("return %T()", hoverboard)
.build()
And that not-yet-existent class is imported as well:
package com.example.helloworld
import com.mattel.Hoverboard
class HelloWorld {
fun tomorrow(): Hoverboard = Hoverboard()
}
The ClassName
type is very important, and you’ll need it frequently when you’re using KotlinPoet.
It can identify any declared class. Declared types are just the beginning of Kotlin’s rich type
system: we also have arrays, parameterized types, wildcard types, lambda types and type variables.
KotlinPoet has classes for building each of these:
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import com.squareup.kotlinpoet.STAR
val hoverboard = ClassName("com.mattel", "Hoverboard")
val list = ClassName("kotlin.collections", "List")
val arrayList = ClassName("kotlin.collections", "ArrayList")
val listOfHoverboards = list.parameterizedBy(hoverboard)
val arrayListOfHoverboards = arrayList.parameterizedBy(hoverboard)
val thing = ClassName("com.misc", "Thing")
val array = ClassName("kotlin", "Array")
val producerArrayOfThings = array.parameterizedBy(WildcardTypeName.producerOf(thing))
val beyond = FunSpec.builder("beyond")
.returns(listOfHoverboards)
.addStatement("val result = %T()", arrayListOfHoverboards)
.addStatement("result += %T()", hoverboard)
.addStatement("result += %T()", hoverboard)
.addStatement("result += %T()", hoverboard)
.addStatement("return result")
.build()
val printThings = FunSpec.builder("printThings")
.addParameter("things", producerArrayOfThings)
.addStatement("println(things)")
.build()
val printKClass = FunSpec.builder("printKClass")
.addParameter("kClass", KClass::class.asClassName().parameterizedBy(STAR))
.addStatement("println(kClass)")
.build()
The STAR
is represented as *
in KotlinPoet. You can find more in the KDoc.
KotlinPoet will decompose each type and import its components where possible.
package com.example.helloworld
import com.mattel.Hoverboard
import com.misc.Thing
import kotlin.Array
import kotlin.collections.ArrayList
import kotlin.collections.List
import kotlin.reflect.KClass
class HelloWorld {
fun beyond(): List<Hoverboard> {
val result = ArrayList<Hoverboard>()
result += Hoverboard()
result += Hoverboard()
result += Hoverboard()
return result
}
fun printThings(things: Array<out Thing>) {
println(things)
}
fun printKClass(kClass: KClass<*>) {
println(kClass)
}
}
Nullable Types¶
KotlinPoet supports nullable types. To convert a TypeName
into its nullable counterpart, use the
copy()
method with nullable
parameter set to true
:
val java = PropertySpec.builder("java", String::class.asTypeName().copy(nullable = true))
.mutable()
.addModifiers(KModifier.PRIVATE)
.initializer("null")
.build()
val helloWorld = TypeSpec.classBuilder("HelloWorld")
.addProperty(java)
.addProperty("kotlin", String::class, KModifier.PRIVATE)
.build()
generates:
class HelloWorld {
private var java: String? = null
private val kotlin: String
}