Kotlin and Java API for generating Kotlin source files (.kt) with type-safe, fluent builder patterns
—
Essential utilities for name allocation, modifier management, and platform-specific functionality across JVM, JavaScript, and WebAssembly targets.
Manages identifier names while avoiding collisions with Kotlin keywords and existing identifiers.
/**
* Allocates names while avoiding collisions with keywords and existing identifiers
*/
class NameAllocator {
/** Allocates a new name based on the suggestion, avoiding conflicts */
fun newName(suggestion: String, tag: Any? = null): String
/** Retrieves the allocated name for the given tag */
fun get(tag: Any): String
/** Creates a copy of this name allocator with the same allocated names */
fun copy(): NameAllocator
companion object {
/** Creates a new NameAllocator instance */
fun get(): NameAllocator
}
}Usage Examples:
import com.squareup.kotlinpoet.*
// Basic name allocation
val allocator = NameAllocator()
// Allocate names avoiding conflicts
val className = allocator.newName("User", "userClass")
val methodName = allocator.newName("process", "processMethod")
// Avoid Kotlin keywords
val safeName = allocator.newName("class", "typeInfo") // Results in "class_" or similar
val safeObject = allocator.newName("object", "instanceRef")
// Use tags to retrieve allocated names later
val userTag = "USER_ENTITY"
val allocatedUserName = allocator.newName("User", userTag)
// Later retrieve the same name
val retrievedName = allocator.get(userTag) // Same as allocatedUserName
// Generate multiple related names
val propertyNames = listOf("name", "age", "email", "class", "object")
val allocatedProperties = propertyNames.mapIndexed { index, name ->
allocator.newName(name, "property_$index")
}
// Copy allocator for different scopes
val methodAllocator = allocator.copy()
val localVar = methodAllocator.newName("result", "localResult")
// Practical usage in code generation
fun generateDataClass(fields: List<Field>): TypeSpec {
val allocator = NameAllocator()
val className = allocator.newName("Generated${fields.first().type}", "mainClass")
return TypeSpec.classBuilder(className)
.addModifiers(KModifier.DATA)
.primaryConstructor(
FunSpec.constructorBuilder()
.apply {
fields.forEach { field ->
val paramName = allocator.newName(field.name, field)
addParameter(paramName, field.type)
}
}
.build()
)
.apply {
fields.forEach { field ->
val propName = allocator.get(field)
addProperty(
PropertySpec.builder(propName, field.type)
.initializer(propName)
.build()
)
}
}
.build()
}Comprehensive enumeration of all Kotlin language modifiers with proper categorization.
/**
* Kotlin language modifiers
*/
enum class KModifier {
// Visibility modifiers
PUBLIC, PROTECTED, PRIVATE, INTERNAL,
// Inheritance modifiers
FINAL, OPEN, ABSTRACT, SEALED,
// Multiplatform modifiers
EXPECT, ACTUAL,
// Function/property modifiers
OVERRIDE, LATEINIT, CONST, EXTERNAL,
// Function-specific modifiers
TAILREC, OPERATOR, INFIX, INLINE, SUSPEND,
// Parameter modifiers
VARARG, CROSSINLINE, NOINLINE, REIFIED,
// Class type modifiers
DATA, INNER, ENUM, ANNOTATION, FUN, COMPANION, VALUE
}Usage Examples:
// Visibility modifiers
val publicClass = TypeSpec.classBuilder("PublicClass")
.addModifiers(KModifier.PUBLIC)
.build()
val privateProperty = PropertySpec.builder("privateField", String::class)
.addModifiers(KModifier.PRIVATE)
.build()
val internalFunction = FunSpec.builder("internalHelper")
.addModifiers(KModifier.INTERNAL)
.build()
// Inheritance modifiers
val openClass = TypeSpec.classBuilder("BaseClass")
.addModifiers(KModifier.OPEN)
.build()
val abstractClass = TypeSpec.classBuilder("AbstractProcessor")
.addModifiers(KModifier.ABSTRACT)
.build()
val sealedClass = TypeSpec.classBuilder("Result")
.addModifiers(KModifier.SEALED)
.addTypeVariable(TypeVariableName("T"))
.build()
val finalClass = TypeSpec.classBuilder("ImmutableData")
.addModifiers(KModifier.FINAL) // Default for classes, explicit here
.build()
// Class type modifiers
val dataClass = TypeSpec.classBuilder("Person")
.addModifiers(KModifier.DATA)
.build()
val enumClass = TypeSpec.enumBuilder("Status")
.addModifiers(KModifier.ENUM) // Implicit with enumBuilder
.build()
val valueClass = TypeSpec.classBuilder("UserId")
.addModifiers(KModifier.VALUE)
.build()
val companionObject = TypeSpec.companionObjectBuilder()
.addModifiers(KModifier.COMPANION) // Implicit with companionObjectBuilder
.build()
// Function modifiers
val inlineFunction = FunSpec.builder("fastOperation")
.addModifiers(KModifier.INLINE)
.build()
val suspendFunction = FunSpec.builder("asyncTask")
.addModifiers(KModifier.SUSPEND)
.build()
val operatorFunction = FunSpec.builder("plus")
.addModifiers(KModifier.OPERATOR)
.build()
val infixFunction = FunSpec.builder("multiply")
.addModifiers(KModifier.INFIX)
.build()
val tailrecFunction = FunSpec.builder("factorial")
.addModifiers(KModifier.TAILREC)
.build()
// Property modifiers
val lateInitProperty = PropertySpec.varBuilder("database", ClassName("", "Database"))
.addModifiers(KModifier.LATEINIT)
.build()
val constProperty = PropertySpec.builder("MAX_SIZE", Int::class)
.addModifiers(KModifier.CONST)
.build()
val overrideProperty = PropertySpec.builder("size", Int::class)
.addModifiers(KModifier.OVERRIDE)
.build()
// Parameter modifiers
val varargParameter = ParameterSpec.builder("items", String::class)
.addModifiers(KModifier.VARARG)
.build()
val crossInlineParameter = ParameterSpec.builder("block", LambdaTypeName.get(returnType = UNIT))
.addModifiers(KModifier.CROSSINLINE)
.build()
val noinlineParameter = ParameterSpec.builder("callback", LambdaTypeName.get(returnType = UNIT))
.addModifiers(KModifier.NOINLINE)
.build()
// Multiplatform modifiers
val expectClass = TypeSpec.classBuilder("PlatformSpecific")
.addModifiers(KModifier.EXPECT)
.build()
val actualClass = TypeSpec.classBuilder("PlatformSpecific")
.addModifiers(KModifier.ACTUAL)
.build()
// External modifier for native interop
val externalFunction = FunSpec.builder("nativeFunction")
.addModifiers(KModifier.EXTERNAL)
.build()Enumeration of all Kotlin operators for operator function overloading.
/**
* Kotlin operators for operator functions
*/
enum class KOperator {
// Unary operators
UNARY_PLUS, UNARY_MINUS, NOT, INC, DEC,
// Binary arithmetic operators
PLUS, MINUS, TIMES, DIV, REM,
// Range operator
RANGE_TO,
// Collection operators
CONTAINS, GET, SET,
// Invoke operator
INVOKE,
// Compound assignment operators
PLUS_ASSIGN, MINUS_ASSIGN, TIMES_ASSIGN, DIV_ASSIGN, REM_ASSIGN,
// Comparison operators
EQUALS, COMPARE_TO
}Usage Examples:
// Arithmetic operators
val plusOperator = FunSpec.builder("plus")
.addModifiers(KModifier.OPERATOR)
.receiver(ClassName("", "Vector"))
.addParameter("other", ClassName("", "Vector"))
.returns(ClassName("", "Vector"))
.addStatement("return Vector(x + other.x, y + other.y)")
.build()
val minusOperator = FunSpec.builder("minus")
.addModifiers(KModifier.OPERATOR)
.receiver(ClassName("", "Vector"))
.addParameter("other", ClassName("", "Vector"))
.returns(ClassName("", "Vector"))
.addStatement("return Vector(x - other.x, y - other.y)")
.build()
// Unary operators
val unaryMinusOperator = FunSpec.builder("unaryMinus")
.addModifiers(KModifier.OPERATOR)
.receiver(ClassName("", "Vector"))
.returns(ClassName("", "Vector"))
.addStatement("return Vector(-x, -y)")
.build()
val incOperator = FunSpec.builder("inc")
.addModifiers(KModifier.OPERATOR)
.receiver(ClassName("", "Counter"))
.returns(ClassName("", "Counter"))
.addStatement("return Counter(value + 1)")
.build()
// Collection access operators
val getOperator = FunSpec.builder("get")
.addModifiers(KModifier.OPERATOR)
.receiver(ClassName("", "Matrix"))
.addParameter("row", Int::class)
.addParameter("col", Int::class)
.returns(Double::class)
.addStatement("return data[row * cols + col]")
.build()
val setOperator = FunSpec.builder("set")
.addModifiers(KModifier.OPERATOR)
.receiver(ClassName("", "Matrix"))
.addParameter("row", Int::class)
.addParameter("col", Int::class)
.addParameter("value", Double::class)
.returns(UNIT)
.addStatement("data[row * cols + col] = value")
.build()
// Contains operator
val containsOperator = FunSpec.builder("contains")
.addModifiers(KModifier.OPERATOR)
.receiver(ClassName("", "Range"))
.addParameter("value", Int::class)
.returns(Boolean::class)
.addStatement("return value >= start && value <= end")
.build()
// Invoke operator (function-like objects)
val invokeOperator = FunSpec.builder("invoke")
.addModifiers(KModifier.OPERATOR)
.receiver(ClassName("", "Multiplier"))
.addParameter("value", Int::class)
.returns(Int::class)
.addStatement("return value * factor")
.build()
// Compound assignment operators
val plusAssignOperator = FunSpec.builder("plusAssign")
.addModifiers(KModifier.OPERATOR)
.receiver(ClassName("", "MutableVector"))
.addParameter("other", ClassName("", "Vector"))
.returns(UNIT)
.addStatement("x += other.x")
.addStatement("y += other.y")
.build()
// Comparison operators
val compareToOperator = FunSpec.builder("compareTo")
.addModifiers(KModifier.OPERATOR)
.receiver(ClassName("", "Version"))
.addParameter("other", ClassName("", "Version"))
.returns(Int::class)
.addStatement("return major.compareTo(other.major)")
.build()
// Range operator
val rangeToOperator = FunSpec.builder("rangeTo")
.addModifiers(KModifier.OPERATOR)
.receiver(ClassName("", "Date"))
.addParameter("other", ClassName("", "Date"))
.returns(ClassName("", "DateRange"))
.addStatement("return DateRange(this, other)")
.build()Utilities that handle platform differences and provide multiplatform support.
// Common utilities (available on all platforms)
class CodePoint {
companion object {
fun isISOControl(codePoint: Int): Boolean
}
}
// Line wrapping utilities
class LineWrapper {
// Implementation varies by platform
}
// Platform-specific utility objects
object Util {
// Common utilities available on all platforms
}
// JVM-specific utilities (only available on JVM)
object JvmUtil {
// JVM-specific implementation details
}Usage Examples:
// Unicode handling across platforms
val unicodeChecker = FunSpec.builder("isControlCharacter")
.addParameter("codePoint", Int::class)
.returns(Boolean::class)
.addStatement("return %T.isISOControl(codePoint)", CodePoint::class)
.build()
// Platform-specific code generation
val platformSpecificFunction = when (targetPlatform) {
Platform.JVM -> FunSpec.builder("processFile")
.addParameter("file", File::class)
.addStatement("// JVM-specific file processing")
.build()
Platform.JS -> FunSpec.builder("processFile")
.addParameter("file", Dynamic)
.addStatement("// JavaScript-specific file processing")
.build()
Platform.WASM -> FunSpec.builder("processFile")
.addParameter("file", String::class)
.addStatement("// WebAssembly-specific file processing")
.build()
}Core interfaces that provide common functionality across KotlinPoet specifications.
/**
* Interface for specs that support tags
*/
interface Taggable {
val tags: Map<KClass<*>, Any>
}
/**
* Interface for specs that support KDoc documentation
*/
interface Documentable {
val kdoc: CodeBlock
}
/**
* Interface for specs that hold references to originating elements (for annotation processing)
*/
interface OriginatingElementsHolder {
val originatingElements: List<Element>
}
/**
* Interface for specs that contain member specifications
*/
interface MemberSpecHolder {
// Marker interface for type hierarchy
}Usage Examples:
// Using tagging for metadata
val taggedFunction = FunSpec.builder("processData")
.tag(String::class, "user-generated")
.tag(Int::class, 42)
.build()
// Retrieve tags later
val userTag = taggedFunction.tags[String::class] as? String
val numberTag = taggedFunction.tags[Int::class] as? Int
// Documentation interface usage
val documentedClass = TypeSpec.classBuilder("UserService")
.addKdoc("""
Service for managing user operations.
This service provides CRUD operations for user entities
and handles business logic related to user management.
""".trimIndent())
.build()
// Check if a spec is documentable
fun addDocumentationIfSupported(spec: Any, doc: String) {
if (spec is Documentable && spec.kdoc.isEmpty) {
// Add documentation
}
}Annotations for marking unstable or dangerous APIs.
/**
* Marks delicate KotlinPoet APIs that require careful usage
*/
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class DelicateKotlinPoetApi
/**
* Marks experimental KotlinPoet APIs
*/
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalKotlinPoetApiUsage Examples:
// Using experimental APIs
@OptIn(ExperimentalKotlinPoetApi::class)
fun useExperimentalFeature() {
// Use experimental KotlinPoet features
}
// Using delicate APIs
@OptIn(DelicateKotlinPoetApi::class)
fun useDelicateApi() {
// Use delicate KotlinPoet APIs that require careful handling
}Install with Tessl CLI
npx tessl i tessl/maven-com-squareup--kotlinpoet