Skip to content

Commit

Permalink
Allow suppressing of klint rules using qualified rule ids which are p…
Browse files Browse the repository at this point in the history
…refixed by `ktlint:`

Standard rules can be suppressed using `@Suppress("ktlint:max-line-length")` while non-standard rules need to be suppressed with `@Suppress("ktlint:experimental:trailing-comma")` Also allow to use `@Suppress("ktlint")` to suppress all rules. (#1463)

Closes #765
Closes #1458
  • Loading branch information
paul-dingemans authored May 20, 2022
1 parent 5eef6a7 commit 1badff6
Show file tree
Hide file tree
Showing 5 changed files with 328 additions and 116 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ An AssertJ style API for testing KtLint rules ([#1444](https://github.com/pinter
- Add experimental rule for unexpected spaces in a nullable type (`nullable-type-spacing`) ([#1341](https://github.com/pinterest/ktlint/issues/1341))
- Do not add a space after the typealias name (`type-parameter-list-spacing`) ([#1435](https://github.com/pinterest/ktlint/issues/1435))
- Add experimental rule for consistent spacing before the start of the function body (`function-start-of-body-spacing`) ([#1341](https://github.com/pinterest/ktlint/issues/1341))
- Suppress ktlint rules using `@Suppress` ([more information](https://github.com/pinterest/ktlint#disabling-for-a-statement-using-suppress)) ([#765](https://github.com/pinterest/ktlint/issues/765))
- Add experimental rule for rewriting the function signature (`function-signature`) ([#1341](https://github.com/pinterest/ktlint/issues/1341))

### Fixed
Expand Down
78 changes: 73 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -616,29 +616,97 @@ Absolutely, "no configuration" doesn't mean "no extensibility". You can add your

See [Creating A Ruleset](#creating-a-ruleset).

### How do I suppress an error for a line/block/file?
### How do I suppress an errors for a line/block/file?

> This is meant primarily as an escape latch for the rare cases when **ktlint** is not able
to produce the correct result (please report any such instances using [GitHub Issues](https://github.com/pinterest/ktlint/issues)).

To disable a specific rule you'll need to turn on the verbose mode (`ktlint --verbose ...`). At the end of each line
you'll see an error code. Use it as an argument for `ktlint-disable` directive (shown below).
To disable a specific rule you'll need the rule identifier which is displayed at the end of the lint error. Note that when the rule id is prefixed with a rule set id like `experimental`, you will need to use that fully qualified rule id.
An error can be suppressed using:
* EOL comments
* Block comments
* @Suppress annotations
From a consistency perspective seen, it might be best to **not** mix the (EOL/Block) comment style with the annotation style in the same project.
Important notice: some rules like the `indent` rule do not yet support disabling of the rule per line of block.
#### Disabling for one specific line using EOL comment
An error for a specific rule on a specific line can be disabled with an EOL comment on that line:
```kotlin
import package.* // ktlint-disable no-wildcard-imports
```
In case lint errors for different rules on the same line need to be ignored, then specify multiple rule ids (separated by a space):
```kotlin
import package.* // ktlint-disable no-wildcard-imports other-rule-id
```
In case all lint errors on a line need to be ignored, then do not specify the rule id at all:
```kotlin
import package.* // ktlint-disable
```
#### Disabling for a block of lines using Block comments
An error for a specific rule in a block of lines can be disabled with an block comment like:
```kotlin
/* ktlint-disable no-wildcard-imports */
import package.a.*
import package.b.*
/* ktlint-enable no-wildcard-imports */
```
To disable all checks:
In case lint errors for different rules in the same block of lines need to be ignored, then specify multiple rule ids (separated by a space):
```kotlin
import package.* // ktlint-disable
/* ktlint-disable no-wildcard-imports other-rule-id */
import package.a.*
import package.b.*
/* ktlint-enable no-wildcard-imports,other-rule-id */
```
Note that the `ktlint-enable` directive needs to specify the exact same rule-id's and in the same order as the `ktlint-disable` directive.

In case all lint errors in a block of lines needs to be ignored, then do not specify the rule id at all:

```kotlin
/* ktlint-disable */
import package.a.*
import package.b.*
/* ktlint-enable */
```

#### Disabling for a statement using @Suppress

> As of ktlint version 0.46, it is possible to specify any ktlint rule id via the `@Suppress` annotation in order to suppress errors found by that rule. Note that some rules like `indent` still do not support disabling for parts of a file.

An error for a specific rule on a specific line can be disabled with a `@Suppress` annotation:

```kotlin
@Suppress("ktlint:max-line-length","ktlint:experimental:trailing-comma")
val foo = listOf(
"some really looooooooooooooooong string exceeding the max line length",
)
```

Note that when using `@Suppress` each qualified rule id needs to be prefixed with `ktlint:`.

To suppress the violations of all ktlint rules, use:
```kotlin
@Suppress("ktlint")
val foo = "some really looooooooooooooooong string exceeding the max line length"
```

Like with other `@Suppress` annotations, it can be placed on targets supported by the annotation.

### How do I globally disable a rule?
See the [EditorConfig section](https://github.com/pinterest/ktlint#editorconfig) for details on how to use the `disabled_rules` property.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.jetbrains.kotlin.com.intellij.psi.PsiComment
import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.psi.KtAnnotated
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset

Expand All @@ -24,6 +25,8 @@ private val suppressAnnotationRuleMap = mapOf(
"RemoveCurlyBracesFromTemplate" to "string-template"
)
private val suppressAnnotations = setOf("Suppress", "SuppressWarnings")
private const val suppresAllKtlintRules = "ktlint-all"

private val commentRegex = Regex("\\s")

/**
Expand Down Expand Up @@ -150,24 +153,48 @@ private fun createSuppressionHintFromAnnotations(
psi: KtAnnotated,
targetAnnotations: Collection<String>,
annotationValueToRuleMapping: Map<String, String>
): SuppressionHint? = psi.annotationEntries
.filter {
it.calleeExpression
?.constructorReferenceExpression
?.getReferencedName() in targetAnnotations
}
.flatMap(KtAnnotationEntry::getValueArguments)
.mapNotNull {
it.getArgumentExpression()?.text?.removeSurrounding("\"")
}
.mapNotNull(annotationValueToRuleMapping::get)
.let { suppressedRules ->
if (suppressedRules.isNotEmpty()) {
SuppressionHint(
IntRange(psi.startOffset, psi.endOffset),
suppressedRules.toSet()
)
} else {
null
): SuppressionHint? =
psi
.annotationEntries
.filter {
it.calleeExpression
?.constructorReferenceExpression
?.getReferencedName() in targetAnnotations
}.flatMap(KtAnnotationEntry::getValueArguments)
.mapNotNull { it.toRuleId(annotationValueToRuleMapping) }
.let { suppressedRules ->
when {
suppressedRules.isEmpty() -> null
suppressedRules.contains(suppresAllKtlintRules) ->
SuppressionHint(
IntRange(psi.startOffset, psi.endOffset),
emptySet()
)
else ->
SuppressionHint(
IntRange(psi.startOffset, psi.endOffset),
suppressedRules.toSet()
)
}
}

private fun ValueArgument.toRuleId(annotationValueToRuleMapping: Map<String, String>): String? =
getArgumentExpression()
?.text
?.removeSurrounding("\"")
?.let {
when {
it == "ktlint" -> {
// Disable all rules
suppresAllKtlintRules
}
it.startsWith("ktlint:") -> {
// Disable specific rule
it.removePrefix("ktlint:")
}
else -> {
// Disable specific rule if it the annotion value is mapped to a specific rule
annotationValueToRuleMapping.get(it)
}
}
}
}

This file was deleted.

Loading

0 comments on commit 1badff6

Please sign in to comment.