Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve insert of suppression #2546

Merged
merged 3 commits into from
Feb 11, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.pinterest.ktlint.rule.engine.api

import com.pinterest.ktlint.rule.engine.core.api.RuleId
import com.pinterest.ktlint.rule.engine.core.api.isWhiteSpace
import com.pinterest.ktlint.rule.engine.internal.RuleExecutionContext
import com.pinterest.ktlint.rule.engine.internal.insertKtlintRuleSuppression
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
@@ -38,6 +39,14 @@ private fun ASTNode.findLeafElementAt(suppression: KtlintSuppression): ASTNode =

is KtlintSuppressionAtOffset ->
findLeafElementAt(suppression.offsetFromStartOf(text))
?.let {
if (it.isWhiteSpace()) {
// A suppression can not be added at a whitespace element. Insert it at the parent instead
it.treeParent
} else {
it
}
}
?: throw KtlintSuppressionNoElementFoundException(suppression)
}

@@ -60,11 +69,22 @@ private fun KtlintSuppressionAtOffset.offsetFromStartOf(code: String): Int {
}

val codeLine = lines[line - 1]
if (col > codeLine.length) {
throw KtlintSuppressionOutOfBoundsException(this)
return when {
col == 1 && codeLine.isEmpty() -> {
startOffsetOfLineContainingLintError
}
col <= codeLine.length -> {
startOffsetOfLineContainingLintError + (col - 1)
}
col == codeLine.length + 1 -> {
// Offset of suppression is set at EOL of the line. This is visually correct for the reader. But the newline character was stripped
// from the line because the lines were split using that character.
startOffsetOfLineContainingLintError + col
}
else -> {
throw KtlintSuppressionOutOfBoundsException(this)
}
}

return startOffsetOfLineContainingLintError + (col - 1)
}

public sealed class KtlintSuppressionException(
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@ import com.pinterest.ktlint.rule.engine.core.api.Rule
import com.pinterest.ktlint.rule.engine.core.api.RuleId
import com.pinterest.ktlint.rule.engine.core.api.RuleProvider
import com.pinterest.ktlint.ruleset.standard.rules.CONDITION_WRAPPING_RULE_ID
import com.pinterest.ktlint.ruleset.standard.rules.NO_CONSECUTIVE_BLANK_LINES_RULE_ID
import com.pinterest.ktlint.ruleset.standard.rules.NO_LINE_BREAK_BEFORE_ASSIGNMENT_RULE_ID
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
@@ -275,6 +277,91 @@ class KtlintRuleEngineSuppressionKtTest {
}
}

@Test
fun `Given a violation with offset exactly at the EOL of a line`() {
val code =
"""
fun foo(): String // Some comment
= "some-result"
""".trimIndent()
val formattedCode =
"""
@Suppress("ktlint:standard:no-line-break-before-assignment")
fun foo(): String // Some comment
= "some-result"
""".trimIndent()
val actual =
ktLintRuleEngine
.insertSuppression(
Code.fromSnippet(code, false),
KtlintSuppressionAtOffset(1, 34, NO_LINE_BREAK_BEFORE_ASSIGNMENT_RULE_ID),
)

assertThat(actual).isEqualTo(formattedCode)
}

@Nested
inner class `Consecutive line suppression can not be placed at line` {
@Test
fun `Given some consecutive blank lines at top level`() {
val code =
"""
val foo = "foo"


val bar = "bar"
""".trimIndent()
val formattedCode =
"""
@file:Suppress("ktlint:standard:no-consecutive-blank-lines")

val foo = "foo"


val bar = "bar"
""".trimIndent()
val actual =
ktLintRuleEngine
.insertSuppression(
Code.fromSnippet(code, false),
KtlintSuppressionAtOffset(3, 1, NO_CONSECUTIVE_BLANK_LINES_RULE_ID),
)

assertThat(actual).isEqualTo(formattedCode)
}

@Test
fun `Given some consecutive blank lines inside a function`() {
val code =
"""
fun foobar() {
val foo = "foo"


val bar = "bar"
}
""".trimIndent()
val formattedCode =
"""
@Suppress("ktlint:standard:no-consecutive-blank-lines")
fun foobar() {
val foo = "foo"


val bar = "bar"
}
""".trimIndent()
val actual =
ktLintRuleEngine
.insertSuppression(
Code.fromSnippet(code, false),
KtlintSuppressionAtOffset(3, 1, NO_CONSECUTIVE_BLANK_LINES_RULE_ID),
)

assertThat(actual).isEqualTo(formattedCode)
}
}

private companion object {
val SOME_RULE_ID = RuleId("standard:some-rule-id")
}