Skip to content

%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
}