Skip to content

%P for String Templates

%S also handles the escaping of dollar signs ($), to avoid inadvertent creation of string templates, which may fail to compile in generated code:

val stringWithADollar = "Your total is " + "$" + "50"
val funSpec = FunSpec.builder("printTotal")
  .returns(String::class)
  .addStatement("return %S", stringWithADollar)
  .build()

produces:

fun printTotal(): String = "Your total is ${'$'}50"

If you need to generate string templates, use %P, which doesn’t escape dollars:

val amount = 50
val stringWithADollar = "Your total is " + "$" + "amount"
val funSpec = FunSpec.builder("printTotal")
  .returns(String::class)
  .addStatement("return %P", stringWithADollar)
  .build()

produces:

fun printTotal(): String = "Your total is $amount"

You can also use CodeBlocks as arguments to %P, which is handy when you need to reference importable types or members inside the string template:

val file = FileSpec.builder("com.example", "Digits")
  .addFunction(
    FunSpec.builder("print")
      .addParameter("digits", IntArray::class)
      .addStatement("println(%P)", buildCodeBlock {
        val contentToString = MemberName("kotlin.collections", "contentToString")
        add("These are the digits: \${digits.%M()}", contentToString)
      })
      .build()
  )
  .build()
println(file)

The snippet above will produce the following output, handling the imports properly:

package com.example

import kotlin.IntArray
import kotlin.collections.contentToString

fun print(digits: IntArray) {
  println("""These are the digits: ${digits.contentToString()}""")
}