1*3c321d95SSadaf EbrahimiCode & Control Flow 2*3c321d95SSadaf Ebrahimi=================== 3*3c321d95SSadaf Ebrahimi 4*3c321d95SSadaf EbrahimiMost of KotlinPoet's API uses immutable Kotlin objects. There's also builders, method chaining 5*3c321d95SSadaf Ebrahimiand varargs to make the API friendly. KotlinPoet offers models for Kotlin files (`FileSpec`), 6*3c321d95SSadaf Ebrahimiclasses, interfaces & objects (`TypeSpec`), type aliases (`TypeAliasSpec`), 7*3c321d95SSadaf Ebrahimiproperties (`PropertySpec`), functions & constructors (`FunSpec`), parameters (`ParameterSpec`) and 8*3c321d95SSadaf Ebrahimiannotations (`AnnotationSpec`). 9*3c321d95SSadaf Ebrahimi 10*3c321d95SSadaf EbrahimiBut the _body_ of methods and constructors is not modeled. There's no expression class, no 11*3c321d95SSadaf Ebrahimistatement class or syntax tree nodes. Instead, KotlinPoet uses strings for code blocks, and you can 12*3c321d95SSadaf Ebrahimitake advantage of Kotlin's multiline strings to make this look nice: 13*3c321d95SSadaf Ebrahimi 14*3c321d95SSadaf Ebrahimi```kotlin 15*3c321d95SSadaf Ebrahimival main = FunSpec.builder("main") 16*3c321d95SSadaf Ebrahimi .addCode(""" 17*3c321d95SSadaf Ebrahimi |var total = 0 18*3c321d95SSadaf Ebrahimi |for (i in 0..<10) { 19*3c321d95SSadaf Ebrahimi | total += i 20*3c321d95SSadaf Ebrahimi |} 21*3c321d95SSadaf Ebrahimi |""".trimMargin()) 22*3c321d95SSadaf Ebrahimi .build() 23*3c321d95SSadaf Ebrahimi``` 24*3c321d95SSadaf Ebrahimi 25*3c321d95SSadaf EbrahimiWhich generates this: 26*3c321d95SSadaf Ebrahimi 27*3c321d95SSadaf Ebrahimi```kotlin 28*3c321d95SSadaf Ebrahimifun main() { 29*3c321d95SSadaf Ebrahimi var total = 0 30*3c321d95SSadaf Ebrahimi for (i in 0..<10) { 31*3c321d95SSadaf Ebrahimi total += i 32*3c321d95SSadaf Ebrahimi } 33*3c321d95SSadaf Ebrahimi} 34*3c321d95SSadaf Ebrahimi``` 35*3c321d95SSadaf Ebrahimi 36*3c321d95SSadaf EbrahimiThere are additional APIs to assist with newlines, braces and indentation: 37*3c321d95SSadaf Ebrahimi 38*3c321d95SSadaf Ebrahimi```kotlin 39*3c321d95SSadaf Ebrahimival main = FunSpec.builder("main") 40*3c321d95SSadaf Ebrahimi .addStatement("var total = 0") 41*3c321d95SSadaf Ebrahimi .beginControlFlow("for (i in 0..<10)") 42*3c321d95SSadaf Ebrahimi .addStatement("total += i") 43*3c321d95SSadaf Ebrahimi .endControlFlow() 44*3c321d95SSadaf Ebrahimi .build() 45*3c321d95SSadaf Ebrahimi``` 46*3c321d95SSadaf Ebrahimi 47*3c321d95SSadaf EbrahimiThis example is lame because the generated code is constant! Suppose instead of just adding 0 to 10, 48*3c321d95SSadaf Ebrahimiwe want to make the operation and range configurable. Here's a method that generates a method: 49*3c321d95SSadaf Ebrahimi 50*3c321d95SSadaf Ebrahimi```kotlin 51*3c321d95SSadaf Ebrahimiprivate fun computeRange(name: String, from: Int, to: Int, op: String): FunSpec { 52*3c321d95SSadaf Ebrahimi return FunSpec.builder(name) 53*3c321d95SSadaf Ebrahimi .returns(Int::class) 54*3c321d95SSadaf Ebrahimi .addStatement("var result = 1") 55*3c321d95SSadaf Ebrahimi .beginControlFlow("for (i in $from..<$to)") 56*3c321d95SSadaf Ebrahimi .addStatement("result = result $op i") 57*3c321d95SSadaf Ebrahimi .endControlFlow() 58*3c321d95SSadaf Ebrahimi .addStatement("return result") 59*3c321d95SSadaf Ebrahimi .build() 60*3c321d95SSadaf Ebrahimi} 61*3c321d95SSadaf Ebrahimi``` 62*3c321d95SSadaf Ebrahimi 63*3c321d95SSadaf EbrahimiAnd here's what we get when we call `computeRange("multiply10to20", 10, 20, "*")`: 64*3c321d95SSadaf Ebrahimi 65*3c321d95SSadaf Ebrahimi```kotlin 66*3c321d95SSadaf Ebrahimifun multiply10to20(): kotlin.Int { 67*3c321d95SSadaf Ebrahimi var result = 1 68*3c321d95SSadaf Ebrahimi for (i in 10..<20) { 69*3c321d95SSadaf Ebrahimi result = result * i 70*3c321d95SSadaf Ebrahimi } 71*3c321d95SSadaf Ebrahimi return result 72*3c321d95SSadaf Ebrahimi} 73*3c321d95SSadaf Ebrahimi``` 74*3c321d95SSadaf Ebrahimi 75*3c321d95SSadaf EbrahimiMethods generating methods! And since KotlinPoet generates source instead of bytecode, you can 76*3c321d95SSadaf Ebrahimiread through it to make sure it's right. 77