1*3c321d95SSadaf EbrahimiFunctions 2*3c321d95SSadaf Ebrahimi========= 3*3c321d95SSadaf Ebrahimi 4*3c321d95SSadaf EbrahimiAll of the above functions have a code body. Use `KModifier.ABSTRACT` to get a function without any 5*3c321d95SSadaf Ebrahimibody. This is only legal if it is enclosed by an abstract class or an interface. 6*3c321d95SSadaf Ebrahimi 7*3c321d95SSadaf Ebrahimi```kotlin 8*3c321d95SSadaf Ebrahimival flux = FunSpec.builder("flux") 9*3c321d95SSadaf Ebrahimi .addModifiers(KModifier.ABSTRACT, KModifier.PROTECTED) 10*3c321d95SSadaf Ebrahimi .build() 11*3c321d95SSadaf Ebrahimi 12*3c321d95SSadaf Ebrahimival helloWorld = TypeSpec.classBuilder("HelloWorld") 13*3c321d95SSadaf Ebrahimi .addModifiers(KModifier.ABSTRACT) 14*3c321d95SSadaf Ebrahimi .addFunction(flux) 15*3c321d95SSadaf Ebrahimi .build() 16*3c321d95SSadaf Ebrahimi``` 17*3c321d95SSadaf Ebrahimi 18*3c321d95SSadaf EbrahimiWhich generates this: 19*3c321d95SSadaf Ebrahimi 20*3c321d95SSadaf Ebrahimi```kotlin 21*3c321d95SSadaf Ebrahimiabstract class HelloWorld { 22*3c321d95SSadaf Ebrahimi protected abstract fun flux() 23*3c321d95SSadaf Ebrahimi} 24*3c321d95SSadaf Ebrahimi``` 25*3c321d95SSadaf Ebrahimi 26*3c321d95SSadaf EbrahimiThe other modifiers work where permitted. 27*3c321d95SSadaf Ebrahimi 28*3c321d95SSadaf EbrahimiMethods also have parameters, varargs, KDoc, annotations, type variables, return type and receiver 29*3c321d95SSadaf Ebrahimitype for extension functions. All of these are configured with `FunSpec.Builder`. 30*3c321d95SSadaf Ebrahimi 31*3c321d95SSadaf Ebrahimi## Extension functions 32*3c321d95SSadaf Ebrahimi 33*3c321d95SSadaf EbrahimiExtension functions can be generated by specifying a `receiver`. 34*3c321d95SSadaf Ebrahimi 35*3c321d95SSadaf Ebrahimi```kotlin 36*3c321d95SSadaf Ebrahimival square = FunSpec.builder("square") 37*3c321d95SSadaf Ebrahimi .receiver(Int::class) 38*3c321d95SSadaf Ebrahimi .returns(Int::class) 39*3c321d95SSadaf Ebrahimi .addStatement("var s = this * this") 40*3c321d95SSadaf Ebrahimi .addStatement("return s") 41*3c321d95SSadaf Ebrahimi .build() 42*3c321d95SSadaf Ebrahimi``` 43*3c321d95SSadaf Ebrahimi 44*3c321d95SSadaf EbrahimiWhich outputs: 45*3c321d95SSadaf Ebrahimi 46*3c321d95SSadaf Ebrahimi```kotlin 47*3c321d95SSadaf Ebrahimifun Int.square(): Int { 48*3c321d95SSadaf Ebrahimi val s = this * this 49*3c321d95SSadaf Ebrahimi return s 50*3c321d95SSadaf Ebrahimi} 51*3c321d95SSadaf Ebrahimi``` 52*3c321d95SSadaf Ebrahimi 53*3c321d95SSadaf Ebrahimi## Single-expression functions 54*3c321d95SSadaf Ebrahimi 55*3c321d95SSadaf EbrahimiKotlinPoet can recognize single-expression functions and print them out properly. It treats 56*3c321d95SSadaf Ebrahimieach function with a body that starts with `return` as a single-expression function: 57*3c321d95SSadaf Ebrahimi 58*3c321d95SSadaf Ebrahimi```kotlin 59*3c321d95SSadaf Ebrahimival abs = FunSpec.builder("abs") 60*3c321d95SSadaf Ebrahimi .addParameter("x", Int::class) 61*3c321d95SSadaf Ebrahimi .returns(Int::class) 62*3c321d95SSadaf Ebrahimi .addStatement("return if (x < 0) -x else x") 63*3c321d95SSadaf Ebrahimi .build() 64*3c321d95SSadaf Ebrahimi``` 65*3c321d95SSadaf Ebrahimi 66*3c321d95SSadaf EbrahimiWhich outputs: 67*3c321d95SSadaf Ebrahimi 68*3c321d95SSadaf Ebrahimi```kotlin 69*3c321d95SSadaf Ebrahimifun abs(x: Int): Int = if (x < 0) -x else x 70*3c321d95SSadaf Ebrahimi``` 71*3c321d95SSadaf Ebrahimi 72*3c321d95SSadaf Ebrahimi## Default function arguments 73*3c321d95SSadaf Ebrahimi 74*3c321d95SSadaf EbrahimiConsider the example below. 75*3c321d95SSadaf EbrahimiFunction argument `b` has a default value of 0 to avoid overloading this function. 76*3c321d95SSadaf Ebrahimi 77*3c321d95SSadaf Ebrahimi```kotlin 78*3c321d95SSadaf Ebrahimifun add(a: Int, b: Int = 0) { 79*3c321d95SSadaf Ebrahimi print("a + b = ${a + b}") 80*3c321d95SSadaf Ebrahimi} 81*3c321d95SSadaf Ebrahimi``` 82*3c321d95SSadaf Ebrahimi 83*3c321d95SSadaf EbrahimiUse the `defaultValue()` builder function to declare default value for a function argument. 84*3c321d95SSadaf Ebrahimi 85*3c321d95SSadaf Ebrahimi```kotlin 86*3c321d95SSadaf EbrahimiFunSpec.builder("add") 87*3c321d95SSadaf Ebrahimi .addParameter("a", Int::class) 88*3c321d95SSadaf Ebrahimi .addParameter( 89*3c321d95SSadaf Ebrahimi ParameterSpec.builder("b", Int::class) 90*3c321d95SSadaf Ebrahimi .defaultValue("%L", 0) 91*3c321d95SSadaf Ebrahimi .build() 92*3c321d95SSadaf Ebrahimi ) 93*3c321d95SSadaf Ebrahimi .addStatement("print(\"a + b = ${a + b}\")") 94*3c321d95SSadaf Ebrahimi .build() 95*3c321d95SSadaf Ebrahimi``` 96*3c321d95SSadaf Ebrahimi 97*3c321d95SSadaf Ebrahimi## Spaces wrap by default! 98*3c321d95SSadaf Ebrahimi 99*3c321d95SSadaf EbrahimiIn order to provide meaningful formatting, KotlinPoet would replace spaces, found in blocks of code, 100*3c321d95SSadaf Ebrahimiwith new line symbols, in cases when the line of code exceeds the length limit. Let's take this 101*3c321d95SSadaf Ebrahimifunction for example: 102*3c321d95SSadaf Ebrahimi 103*3c321d95SSadaf Ebrahimi```kotlin 104*3c321d95SSadaf Ebrahimival funSpec = FunSpec.builder("foo") 105*3c321d95SSadaf Ebrahimi .addStatement("return (100..10000).map { number -> number * number }.map { number -> number.toString() }.also { string -> println(string) }") 106*3c321d95SSadaf Ebrahimi .build() 107*3c321d95SSadaf Ebrahimi``` 108*3c321d95SSadaf Ebrahimi 109*3c321d95SSadaf EbrahimiDepending on where it's found in the file, it may end up being printed out like this: 110*3c321d95SSadaf Ebrahimi 111*3c321d95SSadaf Ebrahimi```kotlin 112*3c321d95SSadaf Ebrahimifun foo() = (100..10000).map { number -> number * number }.map { number -> number.toString() }.also 113*3c321d95SSadaf Ebrahimi{ string -> println(string) } 114*3c321d95SSadaf Ebrahimi``` 115*3c321d95SSadaf Ebrahimi 116*3c321d95SSadaf EbrahimiUnfortunately this code is broken: the compiler expects `also` and `{` to be on the same line. 117*3c321d95SSadaf EbrahimiKotlinPoet is unable to understand the context of the expression and fix the formatting for you, but 118*3c321d95SSadaf Ebrahimithere's a trick you can use to declare a non-breaking space - use the `·` symbol where you would 119*3c321d95SSadaf Ebrahimiotherwise use a space. Let's apply this to our example: 120*3c321d95SSadaf Ebrahimi 121*3c321d95SSadaf Ebrahimi```kotlin 122*3c321d95SSadaf Ebrahimival funSpec = FunSpec.builder("foo") 123*3c321d95SSadaf Ebrahimi .addStatement("return (100..10000).map·{ number -> number * number }.map·{ number -> number.toString() }.also·{ string -> println(string) }") 124*3c321d95SSadaf Ebrahimi .build() 125*3c321d95SSadaf Ebrahimi``` 126*3c321d95SSadaf Ebrahimi 127*3c321d95SSadaf EbrahimiThis will now produce the following result: 128*3c321d95SSadaf Ebrahimi 129*3c321d95SSadaf Ebrahimi```kotlin 130*3c321d95SSadaf Ebrahimifun foo() = (100..10000).map { number -> number * number }.map { number -> 131*3c321d95SSadaf Ebrahimi number.toString() 132*3c321d95SSadaf Ebrahimi}.also { string -> println(string) } 133*3c321d95SSadaf Ebrahimi``` 134*3c321d95SSadaf Ebrahimi 135*3c321d95SSadaf EbrahimiThe code is now correct and will compile properly. It still doesn't look perfect - you can play with 136*3c321d95SSadaf Ebrahimireplacing other spaces in the code block with `·` symbols to achieve better formatting. 137*3c321d95SSadaf Ebrahimi 138*3c321d95SSadaf EbrahimiAnother common use case where you'd want to ensure spaces don't wrap is when emitting string 139*3c321d95SSadaf Ebrahimiliterals: 140*3c321d95SSadaf Ebrahimi 141*3c321d95SSadaf Ebrahimi```kotlin 142*3c321d95SSadaf EbrahimiCodeBlock.of("""println("Class: $className")""") 143*3c321d95SSadaf Ebrahimi``` 144*3c321d95SSadaf Ebrahimi 145*3c321d95SSadaf EbrahimiIf `$className` is long, KotlinPoet may wrap the space that precedes it, resulting in broken output: 146*3c321d95SSadaf Ebrahimi 147*3c321d95SSadaf Ebrahimi```kotlin 148*3c321d95SSadaf Ebrahimiprintln("Class: 149*3c321d95SSadaf Ebrahimivery.long.class.name.Here") 150*3c321d95SSadaf Ebrahimi``` 151*3c321d95SSadaf Ebrahimi 152*3c321d95SSadaf EbrahimiKotlinPoet doesn't know that `"Class: $className"` is, in fact, a string literal, and that the space 153*3c321d95SSadaf Ebrahimiinside of it should never be wrapped. To make sure this case is handled correctly, use the `%S` 154*3c321d95SSadaf Ebrahimimodifier (as described in [%S for Strings](s-for-strings.md)): 155*3c321d95SSadaf Ebrahimi 156*3c321d95SSadaf Ebrahimi```kotlin 157*3c321d95SSadaf EbrahimiCodeBlock.of("""println(%S)""", "Class: $className") 158*3c321d95SSadaf Ebrahimi``` 159*3c321d95SSadaf Ebrahimi 160*3c321d95SSadaf EbrahimiNow the library knows it's dealing with a string literal and can use appropriate line-wrapping rules. 161