Skip to content

Special handling of trimIndent multiline strings can break program semantics #556

@MichaelSims

Description

@MichaelSims

After upgrading to 0.57 in my employer's repo, we ran into failing tests involving SQL queries that were defined in multiline strings. I discovered this was triggered by the new feature that formats multiline strings which use trimIndent. Example (inspired by real code in our repo):

fun main() {
    val whereClause = "1 = 1\n  AND 2 = 2"
    val example =
        """
SELECT
  foo
FROM
  bar
WHERE
  $whereClause
        """
            .trimIndent()
    println(example)
}

In our codebase, trimIndent tends to get used for a few reasons:

  1. The IDE automatically adds it when typing """ followed by the Enter key.
  2. We sometimes (but not always) actually indent the string to line up with the indentation of the opening and closing triple quotes.
  3. We sometimes do not indent (as above), but we still rely on trimIndent to remove the leading and trailing newlines and whitespace.

In the example above, ktfmt 0.57 will reformat the string so that it has 8 leading spaces (using the kotlinlang style). Because whereClause contains a string with an embedded newline (followed by a different number of leading spaces than what ktfmt changed the multiline string to use), this breaks the semantics of the program by altering the actual string value.

You may argue that we shouldn't do this, and that's a fine argument, but I still contend that this trimIndent behavior is a dangerous foot-gun, as I imagine ours is not the only code in the wild that does this sort of thing. Furthermore, I firmly believe that a code formatting tool should never alter string literals or string templates in a program unless it's 100% guaranteed to never change the semantics. I personally find the added value of this feature marginal, but the risk of breaking real programs to be very high.

Please reconsider this feature, or provide some escape hatch to avoid its application. We will likely in the meantime pin our version of ktfmt to 0.56 until we can come up with a solution.

Thanks for your consideration!

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions