diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/StringTemplateIndentRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/StringTemplateIndentRule.kt index 0989fdea13..0199aee8e6 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/StringTemplateIndentRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/StringTemplateIndentRule.kt @@ -161,7 +161,7 @@ public class StringTemplateIndentRule : ?.takeIf { it.elementType == ElementType.EQ } ?.closingParenthesisOfFunctionOrNull() ?.prevLeaf() - ?.let { it.isWhiteSpaceWithNewline() } + ?.isWhiteSpaceWithNewline() ?: false private fun ASTNode.closingParenthesisOfFunctionOrNull() = @@ -292,7 +292,13 @@ public class StringTemplateIndentRule : indent: String, emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> AutocorrectDecision, ) { - val firstNodeAfterOpeningQuotes = node.firstChildNode.nextLeaf() ?: return + val firstNodeAfterOpeningQuotes = + node + // The string template can start with an INTERPOLATION_PREFIX (multi dollar string interpolation, see + // https://kotlinlang.org/docs/strings.html#multi-dollar-string-interpolation), which is to be skipped. + .findChildByType(OPEN_QUOTE) + ?.nextLeaf() + ?: return if (firstNodeAfterOpeningQuotes.text.isNotBlank()) { emit( firstNodeAfterOpeningQuotes.startOffset + firstNodeAfterOpeningQuotes.text.length, diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/StringTemplateIndentRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/StringTemplateIndentRuleTest.kt index bd13578a1e..d361250103 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/StringTemplateIndentRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/StringTemplateIndentRuleTest.kt @@ -500,4 +500,16 @@ class StringTemplateIndentRuleTest { """.trimIndent() stringTemplateIndentRuleAssertThat(code).hasNoLintViolations() } + + @Test + fun `Issue 2885 - Given a multiline string template prefix with a multi-dollar interpolation prefix`() { + val code = + """ + val foo = + $$$MULTILINE_STRING_QUOTE + Some text + $MULTILINE_STRING_QUOTE.trimIndent() + """.trimIndent() + stringTemplateIndentRuleAssertThat(code).hasNoLintViolations() + } }