Skip to content

Commit

Permalink
Add property to disable ktlint for a glob in '.editorconfig' (#2108)
Browse files Browse the repository at this point in the history
This property makes it convenient to disable ktlint entirely for generated code by setting the property on globs related to the generated code.

Closes #2100
  • Loading branch information
paul-dingemans committed Jul 12, 2023
1 parent 306325b commit 7a2dee4
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).

### Fixed

* Allow to disable ktlint in `.editorconfig` for a glob ([#2100](https://github.com/pinterest/ktlint/issues/2100))
* Fix wrapping of nested function literals `wrapping` ([#2106](https://github.com/pinterest/ktlint/issues/2106))
* Do not indent class body for classes having a long super type list in code style `ktlint_official` as it is inconsistent compared to other class bodies `indent` [#2115](https://github.com/pinterest/ktlint/issues/2115)

Expand Down
13 changes: 13 additions & 0 deletions documentation/release-latest/docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,16 @@ ij_formatter_on_tag = some-custom-on-tag # Defaults to '@formatter:on'
```

When enabled, the ktlint rule checking is disabled for all code surrounded by the formatter tags.

# How do I disable ktlint for generated code?

Running ktlint on generated code is not useful. Fixing lint and format errors on generated code is a waste of time as errors will be re-introduced once that code is generated again. Given that generated code is located in a separate directory, you can disable ktlint for such directory by adding a glob for that directory:
```editorconfig
[some/path/to/generated/code/**/*]
ktlint = disabled
```

!!! warning
The `ec4j` library used by ktlint does not seem to work with globs starting with `**` followed by a chain of multiple directories (for example `**/path/to/generated/**/*`). But both `some/path/to/generated/**/*` and `**/generated/**/*` work fine.


13 changes: 13 additions & 0 deletions documentation/snapshot/docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,16 @@ ij_formatter_on_tag = some-custom-on-tag # Defaults to '@formatter:on'
```

When enabled, the ktlint rule checking is disabled for all code surrounded by the formatter tags.

# How do I disable ktlint for generated code?

Running ktlint on generated code is not useful. Fixing lint and format errors on generated code is a waste of time as errors will be re-introduced once that code is generated again. Given that generated code is located in a separate directory, you can disable ktlint for such directory by adding a glob for that directory:
```editorconfig
[some/path/to/generated/code/**/*]
ktlint = disabled
```

!!! warning
The `ec4j` library used by ktlint does not seem to work with globs starting with `**` followed by a chain of multiple directories (for example `**/path/to/generated/**/*`). But both `some/path/to/generated/**/*` and `**/generated/**/*` work fine.


Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ public val RULE_EXECUTION_PROPERTY_TYPE: PropertyType.LowerCasingPropertyType<Ru
RuleExecution.values().map { it.name }.toSet(),
)

/**
* When disabled, no ktlint rules are executed. This property can be used to disable all rulesets (including internal rules) for a given
* glob in the '.editorconfig'.
*/
public val ALL_RULES_EXECUTION_PROPERTY: EditorConfigProperty<RuleExecution> =
EditorConfigProperty(
// Explicitly name the rule as multiple properties exists for this property type
name = "ktlint",
type = RULE_EXECUTION_PROPERTY_TYPE,
defaultValue = RuleExecution.enabled,
)

/**
* When enabled, a rule that implements interface "Rule.Experimental" is executed unless that rule itself is explicitly disabled.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.pinterest.ktlint.logger.api.initKtLintKLogger
import com.pinterest.ktlint.rule.engine.api.KtLintRuleEngine
import com.pinterest.ktlint.rule.engine.core.api.Rule
import com.pinterest.ktlint.rule.engine.core.api.RuleProvider
import com.pinterest.ktlint.rule.engine.core.api.editorconfig.ALL_RULES_EXECUTION_PROPERTY
import com.pinterest.ktlint.rule.engine.core.api.editorconfig.CODE_STYLE_PROPERTY
import com.pinterest.ktlint.rule.engine.core.api.editorconfig.CodeStyleValue
import com.pinterest.ktlint.rule.engine.core.api.editorconfig.EXPERIMENTAL_RULES_EXECUTION_PROPERTY
Expand All @@ -24,16 +25,22 @@ private val LOGGER = KotlinLogging.logger {}.initKtLintKLogger()
internal class RuleExecutionRuleFilter(
private val editorConfig: EditorConfig,
) : RuleFilter {
override fun filter(ruleProviders: Set<RuleProvider>): Set<RuleProvider> {
val ruleExecutionFilter =
RuleExecutionFilter(
editorConfig.ruleExecutionProperties(ruleProviders),
editorConfig[CODE_STYLE_PROPERTY],
)
return ruleProviders
.filter { ruleExecutionFilter.isEnabled(it) }
.toSet()
}
override fun filter(ruleProviders: Set<RuleProvider>): Set<RuleProvider> =
if (disableKtlintEntirely()) {
emptySet()
} else {
val ruleExecutionFilter =
RuleExecutionFilter(
editorConfig.ruleExecutionProperties(ruleProviders),
editorConfig[CODE_STYLE_PROPERTY],
)
ruleProviders
.filter { ruleExecutionFilter.isEnabled(it) }
.toSet()
}

private fun disableKtlintEntirely() =
editorConfig.getEditorConfigValueOrNull(RULE_EXECUTION_PROPERTY_TYPE, ALL_RULES_EXECUTION_PROPERTY.name) == RuleExecution.disabled

private fun EditorConfig.ruleExecutionProperties(ruleProviders: Set<RuleProvider>): Map<String, RuleExecution> {
val ruleExecutionPropertyNames =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ 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.rule.engine.core.api.RuleSetId
import com.pinterest.ktlint.rule.engine.core.api.editorconfig.ALL_RULES_EXECUTION_PROPERTY
import com.pinterest.ktlint.rule.engine.core.api.editorconfig.CODE_STYLE_PROPERTY
import com.pinterest.ktlint.rule.engine.core.api.editorconfig.EditorConfig
import com.pinterest.ktlint.rule.engine.core.api.editorconfig.RULE_EXECUTION_PROPERTY_TYPE
Expand Down Expand Up @@ -176,6 +177,21 @@ class RuleExecutionRuleFilterTest {
assertThat(actual).containsExactly(KTLINT_SUPPRESSION_RULE_ID)
}

@Test
fun `Given that ktlint is disabled entirely then the internal rule for migrating the ktlint-disable directives is disabled`() {
val actual =
runWithRuleExecutionRuleFilter(
RuleProvider { NormalRule(STANDARD_RULE_A) },
RuleProvider { KtlintSuppressionRule(listOf(STANDARD_RULE_A)) },
editorConfig =
EditorConfig(
ktLintDisableAllRuleExecutionEditorConfigProperty(),
),
).toRuleIds()

assertThat(actual).isEmpty()
}

/**
* Create a [RuleExecutionRuleFilter] for a given set of [RuleProvider]s and an [EditorConfig].
*/
Expand All @@ -191,6 +207,14 @@ class RuleExecutionRuleFilterTest {

private fun Set<RuleProvider>.toRuleIds() = map { it.ruleId }

private fun ktLintDisableAllRuleExecutionEditorConfigProperty() =
Property
.builder()
.type(RULE_EXECUTION_PROPERTY_TYPE)
.name(ALL_RULES_EXECUTION_PROPERTY.name)
.value(RuleExecution.disabled.name)
.build()

private fun ktLintRuleExecutionEditorConfigProperty(
ktlintRuleExecutionPropertyName: String,
ruleExecution: RuleExecution,
Expand Down

0 comments on commit 7a2dee4

Please sign in to comment.