From 03d5fce5d75c14e5f7f63ceeecb89a787e664fed Mon Sep 17 00:00:00 2001 From: Brais Date: Sat, 9 Jul 2022 15:03:00 +0200 Subject: [PATCH 1/7] Refactor TrimMultilineRawString --- .../rules/style/TrimMultilineRawString.kt | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrimMultilineRawString.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrimMultilineRawString.kt index d2d215ee919..fbd0f0278b0 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrimMultilineRawString.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrimMultilineRawString.kt @@ -50,14 +50,7 @@ class TrimMultilineRawString(val config: Config) : Rule(config) { if (expression.text.lines().count() <= 1) return - val nextCall = expression.getQualifiedExpressionForSelectorOrThis() - .getQualifiedExpressionForReceiver() - ?.selectorExpression - ?.asKtCallExpression() - ?.calleeExpression - ?.text - - if (nextCall !in trimFunctions) { + if (!expression.isTrimmed()) { report( CodeSmell( issue, @@ -69,6 +62,17 @@ class TrimMultilineRawString(val config: Config) : Rule(config) { } } -private fun KtExpression.asKtCallExpression(): KtCallExpression? = this as? KtCallExpression +fun KtStringTemplateExpression.isTrimmed(): Boolean { + fun KtExpression.asKtCallExpression(): KtCallExpression? = this as? KtCallExpression + + val nextCall = getQualifiedExpressionForSelectorOrThis() + .getQualifiedExpressionForReceiver() + ?.selectorExpression + ?.asKtCallExpression() + ?.calleeExpression + ?.text + + return nextCall in trimFunctions +} private val trimFunctions = listOf("trimIndent", "trimMargin") From 52988e981d64831b1389bba7657865b5df1a07ec Mon Sep 17 00:00:00 2001 From: Brais Date: Sat, 9 Jul 2022 15:06:49 +0200 Subject: [PATCH 2/7] Implement MultilineRawStringIndentation --- .../main/resources/default-detekt-config.yml | 3 + .../style/MultilineRawStringIndentation.kt | 185 ++++++++++ .../detekt/rules/style/StyleGuideProvider.kt | 1 + .../MultilineRawStringIndentationSpec.kt | 340 ++++++++++++++++++ 4 files changed, 529 insertions(+) create mode 100644 detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt create mode 100644 detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentationSpec.kt diff --git a/detekt-core/src/main/resources/default-detekt-config.yml b/detekt-core/src/main/resources/default-detekt-config.yml index 9f414ae5fe0..b914af4fffe 100644 --- a/detekt-core/src/main/resources/default-detekt-config.yml +++ b/detekt-core/src/main/resources/default-detekt-config.yml @@ -602,6 +602,9 @@ style: active: true MultilineLambdaItParameter: active: false + MultilineRawStringIndentation: + active: false + indentSize: 4 NestedClassesVisibility: active: true NewLineAtEndOfFile: diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt new file mode 100644 index 00000000000..cea3b690c53 --- /dev/null +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt @@ -0,0 +1,185 @@ +package io.gitlab.arturbosch.detekt.rules.style + +import io.github.detekt.psi.getLineAndColumnInPsiFile +import io.github.detekt.psi.toFilePath +import io.gitlab.arturbosch.detekt.api.CodeSmell +import io.gitlab.arturbosch.detekt.api.Config +import io.gitlab.arturbosch.detekt.api.Debt +import io.gitlab.arturbosch.detekt.api.Entity +import io.gitlab.arturbosch.detekt.api.Issue +import io.gitlab.arturbosch.detekt.api.Location +import io.gitlab.arturbosch.detekt.api.Rule +import io.gitlab.arturbosch.detekt.api.Severity +import io.gitlab.arturbosch.detekt.api.SourceLocation +import io.gitlab.arturbosch.detekt.api.TextLocation +import io.gitlab.arturbosch.detekt.api.config +import io.gitlab.arturbosch.detekt.api.internal.Configuration +import org.jetbrains.kotlin.com.intellij.psi.PsiFile +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtStringTemplateExpression + +/** + * This rule ensure that the raw strings have a consistent indentation. + * + * The baseIndentation is the indentation that has the line where the raw string started. The content of the + * raw string should have baseIndent plus one identation extra. And the closing raw string (`"""`) should have + * baseIndentation. + * + * + * val a = """ + * Hello World! + * How are you? + * """.trimMargin() + * + * val a = """ + * Hello World! + * How are you? + * """.trimMargin() + * + * + * + * val a = """ + * Hello World! + * How are you? + * """.trimMargin() + * + * val a = """ + * Hello World! + * How are you? + * """.trimMargin() + * + */ +class MultilineRawStringIndentation(val config: Config) : Rule(config) { + override val issue = Issue( + javaClass.simpleName, + Severity.Style, + "The indentation of the raw String should be consistent", + Debt.FIVE_MINS + ) + + @Configuration("indentation size") + private val indentSize by config(4) + + @Suppress("ReturnCount") + override fun visitStringTemplateExpression(expression: KtStringTemplateExpression) { + super.visitStringTemplateExpression(expression) + + val text = expression.text + val lineCount = text.lines().count() + if (lineCount <= 1) return + if (!expression.isTrimmed()) return + if (!text.matches(rawStringRegex)) return + + val lineAndColumn = getLineAndColumnInPsiFile(expression.containingFile, expression.textRange) ?: return + + expression.checkIndentation( + baseIndent = lineAndColumn.lineContent?.countIndent() ?: return, + firstLineNumber = lineAndColumn.line, + lastLineNumber = lineAndColumn.line + lineCount - 1 + ) + } + + private fun KtStringTemplateExpression.checkIndentation( + baseIndent: Int, + firstLineNumber: Int, + lastLineNumber: Int, + ) { + checkContent(desiredIndent = baseIndent + indentSize, (firstLineNumber + 1)..(lastLineNumber - 1)) + checkClosing(baseIndent, lastLineNumber) + } + + private fun KtStringTemplateExpression.checkContent( + desiredIndent: Int, + lineNumberRange: IntRange, + ) { + val indentation = lineNumberRange + .map { lineNumber -> + val line = containingFile.getLine(lineNumber) + Triple(lineNumber, line, line.countIndent()) + } + + if (indentation.isNotEmpty()) { + indentation + .filter { (_, line, currentIndent) -> line.isNotEmpty() && currentIndent < desiredIndent } + .onEach { (lineNumber, line, currentIndent) -> + val location = containingFile.getLocation( + SourceLocation(lineNumber, if (line.isBlank()) 1 else currentIndent + 1), + SourceLocation(lineNumber, line.length + 1) + ) + + report(this, location, message(desiredIndent, currentIndent)) + } + .ifEmpty { + if (indentation.none { (_, _, currentIndent) -> currentIndent == desiredIndent }) { + val location = containingFile.getLocation( + SourceLocation(lineNumberRange.first, desiredIndent + 1), + SourceLocation(lineNumberRange.last, indentation.last().second.length + 1), + ) + + report( + this, + location, + message(desiredIndent, indentation.minOf { (_, _, indent) -> indent }), + ) + } + } + } + } + + private fun KtStringTemplateExpression.checkClosing( + desiredIndent: Int, + lineNumber: Int, + ) { + val currentIndent = containingFile.getLine(lineNumber).countIndent() + if (currentIndent != desiredIndent) { + val location = if (currentIndent < desiredIndent) { + containingFile.getLocation( + SourceLocation(lineNumber, currentIndent + 1), + SourceLocation(lineNumber, currentIndent + "\"\"\"".length + 1), + ) + } else { + containingFile.getLocation( + SourceLocation(lineNumber, desiredIndent + 1), + SourceLocation(lineNumber, currentIndent + 1), + ) + } + + report(this, location, message(desiredIndent, currentIndent)) + } + } +} + +private fun Rule.report(element: KtElement, location: Location, message: String) { + report(CodeSmell(issue, Entity.from(element, location), message)) +} + +private fun message(desiredIntent: Int, currentIndent: Int): String { + return "The indentation should be $desiredIntent but it is $currentIndent." +} + +private val rawStringRegex = "\"\"\"\n(.|\n)*\n *\"\"\"".toRegex() + +private fun String.countIndent() = this.takeWhile { it == ' ' }.count() + +private fun PsiFile.getLine(line: Int): String { + return text.lineSequence().drop(line - 1).first() +} + +private fun PsiFile.getLocation(start: SourceLocation, end: SourceLocation): Location { + val lines = this.text.lines() + var startOffset = 0 + for (i in 1 until start.line) { + startOffset += lines[i - 1].length + 1 + } + var endOffset = startOffset + for (i in start.line until end.line) { + endOffset += lines[i - 1].length + 1 + } + this.text.lines() + return Location( + start, + end, + TextLocation(startOffset + start.column - 1, endOffset + end.column - 1), + toFilePath() + ) +} diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/StyleGuideProvider.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/StyleGuideProvider.kt index 834e95b2f7d..fac5238d873 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/StyleGuideProvider.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/StyleGuideProvider.kt @@ -96,6 +96,7 @@ class StyleGuideProvider : DefaultRuleSetProvider { RedundantHigherOrderMapUsage(config), UseIfEmptyOrIfBlank(config), MultilineLambdaItParameter(config), + MultilineRawStringIndentation(config), UseIsNullOrEmpty(config), UseOrEmpty(config), UseAnyOrNoneInsteadOfFind(config), diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentationSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentationSpec.kt new file mode 100644 index 00000000000..c309c54af73 --- /dev/null +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentationSpec.kt @@ -0,0 +1,340 @@ +package io.gitlab.arturbosch.detekt.rules.style + +import io.gitlab.arturbosch.detekt.api.Config +import io.gitlab.arturbosch.detekt.test.assertThat +import io.gitlab.arturbosch.detekt.test.compileAndLint +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test + +class MultilineRawStringIndentationSpec { + val subject = MultilineRawStringIndentation(Config.empty) + + @Nested + inner class IfTheOpeningDoesNotStartTheLine { + @Test + fun `raise multiline raw string without indentation`() { + val code = """ + val a = $TQ + Hello world! + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .hasSize(1) + .hasStartSourceLocation(2, 1) + .hasEndSourceLocation(2, 13) + .hasTextLocations("Hello world!") + } + + @Test + fun `raise multiline raw strings without indentation`() { + val code = """ + val a = $TQ + Hello world! + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .hasSize(2) + .hasTextLocations("Hello world!", "How are you?") + } + + @Test + fun `raise multiline raw strings without right indentation`() { + val code = """ + val a = $TQ + Hello world! + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .hasSize(1) + .hasStartSourceLocation(2, 2) + .hasEndSourceLocation(2, 14) + .hasTextLocations("Hello world!") + } + + @Test + fun `raise multiline raw strings with too much indentation`() { + val code = """ + val a = $TQ + Hello world! + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .hasSize(1) + .hasStartSourceLocation(2, 5) + .hasEndSourceLocation(3, 18) + .hasTextLocations(" Hello world!\n How are you?") + } + + @Test + fun `don't raise multiline raw strings if one has correct indentation and the other more`() { + val code = """ + val a = $TQ + Hello world! + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .isEmpty() + } + + @Test + fun `don't raise multiline raw strings if all have the correct indentation`() { + val code = """ + val a = $TQ + Hello world! + + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .isEmpty() + } + + @Test + fun `don't raise multiline raw strings if all have the correct indentation or empty`() { + val code = """ + val a = $TQ + Hello world! + + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .isEmpty() + } + + @Test + fun `raise multiline raw strings if a blank line doesn't have the minimum indentation`() { + val code = """ + val a = $TQ + Hello world! + + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .hasSize(1) + .hasStartSourceLocation(3, 1) + .hasEndSourceLocation(3, 3) + } + + @Test + fun `raise multiline raw strings with indentation on closing`() { + val code = """ + val a = $TQ + Hello world! + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .hasSize(1) + .hasStartSourceLocation(4, 1) + .hasEndSourceLocation(4, 5) + } + } + + @Nested + inner class IfTheOpeningStartTheLine { + @Test + fun `raise multiline raw string without indentation`() { + val code = """ + val a = + $TQ + Hello world! + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .hasSize(1) + .hasStartSourceLocation(3, 5) + .hasEndSourceLocation(3, 17) + } + + @Test + fun `raise multiline raw strings without indentation`() { + val code = """ + val a = + $TQ + Hello world! + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .hasSize(2) + } + + @Test + fun `raise multiline raw strings without right indentation`() { + val code = """ + val a = + $TQ + Hello world! + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .hasSize(1) + .hasStartSourceLocation(3, 6) + .hasEndSourceLocation(3, 18) + } + + @Test + fun `raise multiline raw strings with too much indentation`() { + val code = """ + val a = + $TQ + Hello world! + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .hasSize(1) + .hasStartSourceLocation(3, 9) + .hasEndSourceLocation(4, 22) + .hasTextLocations(" Hello world!\n How are you?") + } + + @Test + fun `don't raise multiline raw strings if one has correct indentation and the other more`() { + val code = """ + val a = + $TQ + Hello world! + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .isEmpty() + } + + @Test + fun `don't raise multiline raw strings if all have the correct indentation`() { + val code = """ + val a = + $TQ + Hello world! + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .isEmpty() + } + + @Test + fun `raise multiline raw strings with too much indentation on closing`() { + val code = """ + val a = + $TQ + Hello world! + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .hasSize(1) + .hasStartSourceLocation(5, 5) + .hasEndSourceLocation(5, 9) + } + + @Test + fun `raise multiline raw strings with too little indentation on closing`() { + val code = """ + val a = + $TQ + Hello world! + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .hasSize(1) + .hasStartSourceLocation(5, 3) + .hasEndSourceLocation(5, 6) + } + } + + @Nested + inner class CasesThatShouldBeIgnored { + @Test + fun `doesn't raise multiline raw strings without trim`() { + val code = """ + val a = $TQ + Hello world! + $TQ + """ + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } + + @Test + fun `don't raise one line raw strings`() { + val code = """ + val a = ${TQ}Hello world!$TQ + """ + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } + + @Test + fun `doesn't raise if it is not a raw string`() { + val code = """ + val a = "Hello world!" + """ + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } + + @Test + fun `don't raise if it contains content after the opening triple quote`() { + val code = """ + val a = ${TQ}Hello world! + How are you? + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .isEmpty() + } + + @Test + fun `don't raise if it contains content before the closing triple quote`() { + val code = """ + val a = $TQ + Hello world! + How are you?$TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .isEmpty() + } + + @Test + fun `don't raise if it isEmpty`() { + val code = """ + val a = $TQ + $TQ.trimIndent() + """ + subject.compileAndLint(code) + assertThat(subject.findings) + .isEmpty() + } + } +} + +private const val TQ = "\"\"\"" From 4d0cc5607a7530cd757b093246783fd040fe1ab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brais=20Gab=C3=ADn?= Date: Sat, 23 Jul 2022 12:01:19 +0200 Subject: [PATCH 3/7] Update detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt Co-authored-by: marschwar --- .../detekt/rules/style/MultilineRawStringIndentation.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt index cea3b690c53..2df723672f7 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt @@ -19,7 +19,7 @@ import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtStringTemplateExpression /** - * This rule ensure that the raw strings have a consistent indentation. + * This rule ensures that raw strings have a consistent indentation. * * The baseIndentation is the indentation that has the line where the raw string started. The content of the * raw string should have baseIndent plus one identation extra. And the closing raw string (`"""`) should have From 1d4378448f859050352e9e9641bdeaee2f573386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brais=20Gab=C3=ADn?= Date: Sat, 23 Jul 2022 12:01:29 +0200 Subject: [PATCH 4/7] Update detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt Co-authored-by: marschwar --- .../detekt/rules/style/MultilineRawStringIndentation.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt index 2df723672f7..418ac01d0da 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt @@ -21,9 +21,8 @@ import org.jetbrains.kotlin.psi.KtStringTemplateExpression /** * This rule ensures that raw strings have a consistent indentation. * - * The baseIndentation is the indentation that has the line where the raw string started. The content of the - * raw string should have baseIndent plus one identation extra. And the closing raw string (`"""`) should have - * baseIndentation. + * The content of a multi line raw string should have the same indentation as the enclosing expression plus the + * configured indentSize. The closing triple-quotes (`"""`) must have the same indentation as the enclosing expression. * * * val a = """ From 33a46d2764cd0fef40eb35c00e8c9b58c63fa664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brais=20Gab=C3=ADn?= Date: Sat, 23 Jul 2022 12:01:36 +0200 Subject: [PATCH 5/7] Update detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt Co-authored-by: marschwar --- .../detekt/rules/style/MultilineRawStringIndentation.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt index 418ac01d0da..5a5d4bfb9e1 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt @@ -48,7 +48,7 @@ import org.jetbrains.kotlin.psi.KtStringTemplateExpression * """.trimMargin() * */ -class MultilineRawStringIndentation(val config: Config) : Rule(config) { +class MultilineRawStringIndentation(config: Config) : Rule(config) { override val issue = Issue( javaClass.simpleName, Severity.Style, From 59b6e5307f4657455e093d6372032776e6119e1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brais=20Gab=C3=ADn?= Date: Sat, 23 Jul 2022 12:05:44 +0200 Subject: [PATCH 6/7] Update detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt Co-authored-by: marschwar --- .../detekt/rules/style/MultilineRawStringIndentation.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt index 5a5d4bfb9e1..93b81030422 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt @@ -156,7 +156,7 @@ private fun message(desiredIntent: Int, currentIndent: Int): String { return "The indentation should be $desiredIntent but it is $currentIndent." } -private val rawStringRegex = "\"\"\"\n(.|\n)*\n *\"\"\"".toRegex() +private val rawStringRegex = "\"{3}\n.*\n *\"{3}".toRegex(RegexOption.DOT_MATCHES_ALL) private fun String.countIndent() = this.takeWhile { it == ' ' }.count() From ab9ab07f250d332039cfc6f7856faa84e85798d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brais=20Gab=C3=ADn?= Date: Sat, 23 Jul 2022 12:21:16 +0200 Subject: [PATCH 7/7] Don't use Triple --- .../detekt/rules/style/MultilineRawStringIndentation.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt index 93b81030422..b7af32bf85f 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineRawStringIndentation.kt @@ -91,10 +91,12 @@ class MultilineRawStringIndentation(config: Config) : Rule(config) { desiredIndent: Int, lineNumberRange: IntRange, ) { + data class LineInformation(val lineNumber: Int, val line: String, val currentIndent: Int) + val indentation = lineNumberRange .map { lineNumber -> val line = containingFile.getLine(lineNumber) - Triple(lineNumber, line, line.countIndent()) + LineInformation(lineNumber, line, line.countIndent()) } if (indentation.isNotEmpty()) { @@ -112,7 +114,7 @@ class MultilineRawStringIndentation(config: Config) : Rule(config) { if (indentation.none { (_, _, currentIndent) -> currentIndent == desiredIndent }) { val location = containingFile.getLocation( SourceLocation(lineNumberRange.first, desiredIndent + 1), - SourceLocation(lineNumberRange.last, indentation.last().second.length + 1), + SourceLocation(lineNumberRange.last, indentation.last().line.length + 1), ) report(