From e8d67999523e583a3965b0d14f9a4486a7c4f310 Mon Sep 17 00:00:00 2001 From: paul-dingemans Date: Sun, 8 Aug 2021 22:01:29 +0200 Subject: [PATCH] Lint and format trailing spaces inside block comments (#1204) * Lint and format trailing spaces inside block comments Closes #1197 * Add changelog entry Co-authored-by: Paul Dingemans Co-authored-by: Roman Zavarnitsyn --- CHANGELOG.md | 1 + .../ruleset/standard/NoTrailingSpacesRule.kt | 52 +++++++++---------- .../standard/NoTrailingSpacesRuleTest.kt | 41 +++++++++++++++ 3 files changed, 68 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ea5c0a5f7..00185b2403 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - New `trailing-comma` rule ([#709](https://github.com/pinterest/ktlint/issues/709)) (prior art by [paul-dingemans](https://github.com/paul-dingemans)) ### Fixed - Fix false positive with lambda argument and call chain (`indent`) ([#1202](https://github.com/pinterest/ktlint/issues/1202)) +- Fix trailing spaces not formatted inside block comments (`no-trailing-spaces`) ([#1197](https://github.com/pinterest/ktlint/issues/1197)) ### Changed - Support absolute paths for globs ([#1131](https://github.com/pinterest/ktlint/issues/1131)) diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/NoTrailingSpacesRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/NoTrailingSpacesRule.kt index a5451ce440..229c10d402 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/NoTrailingSpacesRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/NoTrailingSpacesRule.kt @@ -3,6 +3,7 @@ package com.pinterest.ktlint.ruleset.standard import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.nextLeaf import org.jetbrains.kotlin.com.intellij.lang.ASTNode +import org.jetbrains.kotlin.com.intellij.psi.PsiComment import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement @@ -13,36 +14,35 @@ class NoTrailingSpacesRule : Rule("no-trailing-spaces") { autoCorrect: Boolean, emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit ) { - if (node is PsiWhiteSpace) { - val lines = node.getText().split("\n") - if (lines.size > 1) { - val violated = checkForTrailingSpaces(lines.head(), node.startOffset, emit) - if (violated && autoCorrect) { - (node as LeafPsiElement).rawReplaceWithText("\n".repeat(lines.size - 1) + lines.last()) + if (node is PsiWhiteSpace || node is PsiComment) { + val lines = node.text.split("\n") + var violated = false + var violationOffset = node.startOffset + lines + .head() + .forEach { line -> + if (line.hasTrailingSpace()) { + emit(violationOffset, "Trailing space(s)", true) + violated = true + } + violationOffset += line.length + 1 } - } else if (node.nextLeaf() == null /* eof */) { - val violated = checkForTrailingSpaces(lines, node.startOffset, emit) - if (violated && autoCorrect) { - (node as LeafPsiElement).rawReplaceWithText("\n".repeat(lines.size - 1)) + when { + node is PsiWhiteSpace && node.nextLeaf() != null -> + // Ignore the last line as it contains the indentation of the next element + Unit + lines.last().hasTrailingSpace() -> { + emit(violationOffset, "Trailing space(s)", true) + violated = true } } - } - } - - private fun checkForTrailingSpaces( - lines: List, - offset: Int, - emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit - ): Boolean { - var violated = false - var violationOffset = offset - lines.forEach { line -> - if (!line.isEmpty()) { - emit(violationOffset, "Trailing space(s)", true) - violated = true + if (violated && autoCorrect) { + val modifiedLines = lines.joinToString(separator = "\n") { it.trimEnd() } + (node as LeafPsiElement).rawReplaceWithText(modifiedLines) } - violationOffset += line.length + 1 } - return violated } + + private fun String.hasTrailingSpace() = + takeLast(1) == " " } diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/NoTrailingSpacesRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/NoTrailingSpacesRuleTest.kt index 2e66c54163..07d8837a53 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/NoTrailingSpacesRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/NoTrailingSpacesRuleTest.kt @@ -24,4 +24,45 @@ class NoTrailingSpacesRuleTest { assertThat(NoTrailingSpacesRule().format("fun main() {\n val a = 1 \n \n \n} ")) .isEqualTo("fun main() {\n val a = 1\n\n\n}") } + + @Test + fun `lint trailing spaces inside block comments`() { + val code = + """ + /*${" "} + * Some comment${" "} + */ + """.trimIndent() + + val actual = NoTrailingSpacesRule().lint(code) + + assertThat(actual) + .isEqualTo( + listOf( + LintError(1, 1, "no-trailing-spaces", "Trailing space(s)"), + LintError(2, 1, "no-trailing-spaces", "Trailing space(s)") + ) + ) + } + + @Test + fun `format trailing spaces inside block comments`() { + val code = + """ + /*${" "} + * Some comment${" "} + */ + """.trimIndent() + + val actual = NoTrailingSpacesRule().format(code) + + assertThat(actual) + .isEqualTo( + """ + /* + * Some comment + */ + """.trimIndent() + ) + } }