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

Add property to disable ktlint for a glob in '.editorconfig' #2108

Merged
merged 2 commits into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
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
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