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