| Functions |
| ========= |
| |
| All of the above functions have a code body. Use `KModifier.ABSTRACT` to get a function without any |
| body. This is only legal if it is enclosed by an abstract class or an interface. |
| |
| ```kotlin |
| val flux = FunSpec.builder("flux") |
| .addModifiers(KModifier.ABSTRACT, KModifier.PROTECTED) |
| .build() |
| |
| val helloWorld = TypeSpec.classBuilder("HelloWorld") |
| .addModifiers(KModifier.ABSTRACT) |
| .addFunction(flux) |
| .build() |
| ``` |
| |
| Which generates this: |
| |
| ```kotlin |
| abstract class HelloWorld { |
| protected abstract fun flux() |
| } |
| ``` |
| |
| The other modifiers work where permitted. |
| |
| Methods also have parameters, varargs, KDoc, annotations, type variables, return type and receiver |
| type for extension functions. All of these are configured with `FunSpec.Builder`. |
| |
| ## Extension functions |
| |
| Extension functions can be generated by specifying a `receiver`. |
| |
| ```kotlin |
| val square = FunSpec.builder("square") |
| .receiver(Int::class) |
| .returns(Int::class) |
| .addStatement("var s = this * this") |
| .addStatement("return s") |
| .build() |
| ``` |
| |
| Which outputs: |
| |
| ```kotlin |
| fun Int.square(): Int { |
| val s = this * this |
| return s |
| } |
| ``` |
| |
| ## Single-expression functions |
| |
| KotlinPoet can recognize single-expression functions and print them out properly. It treats |
| each function with a body that starts with `return` as a single-expression function: |
| |
| ```kotlin |
| val abs = FunSpec.builder("abs") |
| .addParameter("x", Int::class) |
| .returns(Int::class) |
| .addStatement("return if (x < 0) -x else x") |
| .build() |
| ``` |
| |
| Which outputs: |
| |
| ```kotlin |
| fun abs(x: Int): Int = if (x < 0) -x else x |
| ``` |
| |
| ## Default function arguments |
| |
| Consider the example below. |
| Function argument `b` has a default value of 0 to avoid overloading this function. |
| |
| ```kotlin |
| fun add(a: Int, b: Int = 0) { |
| print("a + b = ${a + b}") |
| } |
| ``` |
| |
| Use the `defaultValue()` builder function to declare default value for a function argument. |
| |
| ```kotlin |
| FunSpec.builder("add") |
| .addParameter("a", Int::class) |
| .addParameter( |
| ParameterSpec.builder("b", Int::class) |
| .defaultValue("%L", 0) |
| .build() |
| ) |
| .addStatement("print(\"a + b = ${a + b}\")") |
| .build() |
| ``` |
| |
| ## Spaces wrap by default! |
| |
| In order to provide meaningful formatting, KotlinPoet would replace spaces, found in blocks of code, |
| with new line symbols, in cases when the line of code exceeds the length limit. Let's take this |
| function for example: |
| |
| ```kotlin |
| val funSpec = FunSpec.builder("foo") |
| .addStatement("return (100..10000).map { number -> number * number }.map { number -> number.toString() }.also { string -> println(string) }") |
| .build() |
| ``` |
| |
| Depending on where it's found in the file, it may end up being printed out like this: |
| |
| ```kotlin |
| fun foo() = (100..10000).map { number -> number * number }.map { number -> number.toString() }.also |
| { string -> println(string) } |
| ``` |
| |
| Unfortunately this code is broken: the compiler expects `also` and `{` to be on the same line. |
| KotlinPoet is unable to understand the context of the expression and fix the formatting for you, but |
| there's a trick you can use to declare a non-breaking space - use the `·` symbol where you would |
| otherwise use a space. Let's apply this to our example: |
| |
| ```kotlin |
| val funSpec = FunSpec.builder("foo") |
| .addStatement("return (100..10000).map·{ number -> number * number }.map·{ number -> number.toString() }.also·{ string -> println(string) }") |
| .build() |
| ``` |
| |
| This will now produce the following result: |
| |
| ```kotlin |
| fun foo() = (100..10000).map { number -> number * number }.map { number -> |
| number.toString() |
| }.also { string -> println(string) } |
| ``` |
| |
| The code is now correct and will compile properly. It still doesn't look perfect - you can play with |
| replacing other spaces in the code block with `·` symbols to achieve better formatting. |
| |
| Another common use case where you'd want to ensure spaces don't wrap is when emitting string |
| literals: |
| |
| ```kotlin |
| CodeBlock.of("""println("Class: $className")""") |
| ``` |
| |
| If `$className` is long, KotlinPoet may wrap the space that precedes it, resulting in broken output: |
| |
| ```kotlin |
| println("Class: |
| very.long.class.name.Here") |
| ``` |
| |
| KotlinPoet doesn't know that `"Class: $className"` is, in fact, a string literal, and that the space |
| inside of it should never be wrapped. To make sure this case is handled correctly, use the `%S` |
| modifier (as described in [%S for Strings](s-for-strings.md)): |
| |
| ```kotlin |
| CodeBlock.of("""println(%S)""", "Class: $className") |
| ``` |
| |
| Now the library knows it's dealing with a string literal and can use appropriate line-wrapping rules. |