代码与控制流¶
KotlinPoet 的大多数 API 使用不可变的 Kotlin 对象。还有构建器、方法链和可变参数,使 API 更易用。KotlinPoet 提供了 Kotlin 文件 (FileSpec
)、类、接口与对象 (TypeSpec
)、类型别名 (TypeAliasSpec
)、属性 (PropertySpec
)、函数与构造函数 (FunSpec
)、参数 (ParameterSpec
) 和注解 (AnnotationSpec
) 的模型。
但是,方法和构造函数的主体没有被建模。没有表达式类、语句类或语法树节点。取而代之的是,KotlinPoet 使用字符串来表示代码块,并且您可以利用 Kotlin 的多行字符串使其看起来更美观
val main = FunSpec.builder("main")
.addCode("""
|var total = 0
|for (i in 0..<10) {
| total += i
|}
|""".trimMargin())
.build()
这会生成以下代码
fun main() {
var total = 0
for (i in 0..<10) {
total += i
}
}
还有额外的 API 来帮助处理换行、大括号和缩进
val main = FunSpec.builder("main")
.addStatement("var total = 0")
.beginControlFlow("for (i in 0..<10)")
.addStatement("total += i")
.endControlFlow()
.build()
这个例子很蹩脚,因为生成的代码是常量!假设我们不想仅仅将 0 加到 10,而是希望操作和范围是可配置的。这是一个生成方法的方法
private fun computeRange(name: String, from: Int, to: Int, op: String): FunSpec {
return FunSpec.builder(name)
.returns(Int::class)
.addStatement("var result = 1")
.beginControlFlow("for (i in $from..<$to)")
.addStatement("result = result $op i")
.endControlFlow()
.addStatement("return result")
.build()
}
当我们调用 computeRange("multiply10to20", 10, 20, "*")
时,得到的结果如下
fun multiply10to20(): kotlin.Int {
var result = 1
for (i in 10..<20) {
result = result * i
}
return result
}
生成方法的方法!而且由于 KotlinPoet 生成的是源代码而不是字节码,您可以通读它以确保其正确性。