Skip to content

Commit

Permalink
Trailing spaces should not delete the indent of the next line
Browse files Browse the repository at this point in the history
In most cases this is probably fixed by the indent rule but at least not
when next line contains a KDoc

Closes pinterest#1334
  • Loading branch information
Paul Dingemans committed Jan 23, 2022
1 parent 637ef2c commit 3807a3c
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Fix alignment of arrow when trailing comma is missing in when entry (`trailing-comma`) ([#1312](https://github.com/pinterest/ktlint/issues/1312))
- Fix indent of delegated super type entry (`indent`) ([#1210](https://github.com/pinterest/ktlint/issues/1210))
- Improve indentation of closing quotes of a multiline raw string literal (`indent`) ([#1262](https://github.com/pinterest/ktlint/pull/1262))
- Trailing space should not lead to delete of indent of next line (`no-trailing-spaces`) ([#1334](https://github.com/pinterest/ktlint/pull/1334))

### Changed
- Update Kotlin version to `1.6.0` release
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package com.pinterest.ktlint.ruleset.standard

import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.ast.ElementType.EOL_COMMENT
import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE
import com.pinterest.ktlint.core.ast.isPartOfComment
import com.pinterest.ktlint.core.ast.nextLeaf
import com.pinterest.ktlint.core.ast.parent
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.kdoc.psi.api.KDoc

class NoTrailingSpacesRule : Rule("no-trailing-spaces") {

override fun visit(
node: ASTNode,
autoCorrect: Boolean,
Expand All @@ -28,29 +27,29 @@ class NoTrailingSpacesRule : Rule("no-trailing-spaces") {
val lines = node.text.split("\n")
var violated = false
var violationOffset = node.startOffset
lines
.head()
.forEach { line ->
if (line.hasTrailingSpace()) {
val firstTrailingSpaceOffset = violationOffset + line.trimEnd().length
emit(firstTrailingSpaceOffset, "Trailing space(s)", true)
violated = true

val modifiedLines =
lines
.mapIndexed { index, line ->
val modifiedLine = when {
node.elementType != EOL_COMMENT && index == lines.size - 1 && node.nextLeaf() != null ->
// Do not change the last line as it contains the indentation of the next element except
// when it is an EOL comment which may also not contain trailing spaces
line
line.hasTrailingSpace() -> {
val modifiedLine = line.trimEnd()
val firstTrailingSpaceOffset = violationOffset + modifiedLine.length
emit(firstTrailingSpaceOffset, "Trailing space(s)", true)
violated = true
modifiedLine
}
else -> line
}
violationOffset += line.length + 1
modifiedLine
}
violationOffset += line.length + 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() -> {
val firstTrailingSpaceOffset = violationOffset + lines.last().trimEnd().length
emit(firstTrailingSpaceOffset, "Trailing space(s)", true)
violated = true
}
}
if (violated && autoCorrect) {
val modifiedLines = lines.joinToString(separator = "\n") { it.trimEnd() }
(node as LeafPsiElement).rawReplaceWithText(modifiedLines)
(node as LeafPsiElement).rawReplaceWithText(modifiedLines.joinToString(separator = "\n"))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,45 @@ class NoTrailingSpacesRuleTest {
)
)
}

@Test
fun `Issue 1334 - trailing spaces should not delete indent of the next line`() {
val code =
"""
class Foo {
// something
${" "}
/**
* Some KDoc
*/
val bar: String
${" "}
val foo = "foo"
}
""".trimIndent()
val codeExpected =
"""
class Foo {
// something
/**
* Some KDoc
*/
val bar: String
val foo = "foo"
}
""".trimIndent()
assertThat(
NoTrailingSpacesRule().format(code)
).isEqualTo(codeExpected)
assertThat(
NoTrailingSpacesRule().lint(code)
).isEqualTo(
listOf(
LintError(3, 1, "no-trailing-spaces", "Trailing space(s)"),
LintError(8, 1, "no-trailing-spaces", "Trailing space(s)")
)
)
}
}

0 comments on commit 3807a3c

Please sign in to comment.