Skip to content

Commit

Permalink
Implement .ktlintigore for globally disabling rules
Browse files Browse the repository at this point in the history
Fixes pinterest#208

* Added support for .ktlintignore file - takes a list of rule Ids to disable (ignores comments)
* Currently only supports globally disabling rules, but added some plumbing so that it's easier to support per-file/per-path disabling, or multiple .ktlintignore files
* Re-enabled NoWildcardImports, PackageNameRule
* Un-commented AnnotationRule, MultiLineIfElseRule, and NoItParamInMultilineLambdaRule, and moved disabling into .ktlintignore
  • Loading branch information
shashachu committed Jun 6, 2019
1 parent b1cae89 commit 6f8bb56
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 18 deletions.
7 changes: 7 additions & 0 deletions .ktlintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// disabled ("./mvnw clean verify" fails with "Internal Error")
annotation
// disabled until auto-correct is working properly
// (e.g. try formatting "if (true)\n return { _ ->\n _\n}")
multiline-if-else
// disabled until it's clear what to do in case of `import _.it`
no-it-in-multiline-lambda
13 changes: 10 additions & 3 deletions ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/KtLint.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ object KtLint {
val EDITOR_CONFIG_USER_DATA_KEY = Key<EditorConfig>("EDITOR_CONFIG")
val ANDROID_USER_DATA_KEY = Key<Boolean>("ANDROID")
val FILE_PATH_USER_DATA_KEY = Key<String>("FILE_PATH")
val DISABLED_RULES = Key<Set<String>>("DISABLED_RULES")

private val psiFileFactory: PsiFileFactory
private val nullSuppression = { _: Int, _: String, _: Boolean -> false }
Expand Down Expand Up @@ -186,15 +187,17 @@ object KtLint {
userData
}
node.putUserData(FILE_PATH_USER_DATA_KEY, userData["file_path"])
node.putUserData(EDITOR_CONFIG_USER_DATA_KEY, EditorConfig.fromMap(editorConfigMap - "android" - "file_path"))
node.putUserData(EDITOR_CONFIG_USER_DATA_KEY, EditorConfig.fromMap(editorConfigMap - "android" - "file_path" - "disabled_rules"))
node.putUserData(ANDROID_USER_DATA_KEY, android)
node.putUserData(DISABLED_RULES, userData["disabled_rules"]?.split(",")?.toSet() ?: setOf())
}

private fun visitor(
rootNode: ASTNode,
ruleSets: Iterable<RuleSet>,
concurrent: Boolean = true,
filter: (fqRuleId: String) -> Boolean = { true }
filter: (rootNode: ASTNode, fqRuleId: String) -> Boolean = this::filterDisabledRules

): ((node: ASTNode, rule: Rule, fqRuleId: String) -> Unit) -> Unit {
val fqrsRestrictedToRoot = mutableListOf<Pair<String, Rule>>()
val fqrs = mutableListOf<Pair<String, Rule>>()
Expand All @@ -204,7 +207,7 @@ object KtLint {
val prefix = if (ruleSet.id === "standard") "" else "${ruleSet.id}:"
for (rule in ruleSet) {
val fqRuleId = "$prefix${rule.id}"
if (!filter(fqRuleId)) {
if (!filter(rootNode, fqRuleId)) {
continue
}
val fqr = fqRuleId to rule
Expand Down Expand Up @@ -254,6 +257,10 @@ object KtLint {
}
}

private fun filterDisabledRules(rootNode: ASTNode, fqRuleId: String): Boolean {
return rootNode.getUserData(DISABLED_RULES)?.contains(fqRuleId) == false
}

private fun calculateLineColByOffset(text: String): (offset: Int) -> Pair<Int, Int> {
var i = -1
val e = text.length
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,28 @@ class StandardRuleSetProvider : RuleSetProvider {

override fun get(): RuleSet = RuleSet(
"standard",
// disabled ("./mvnw clean verify" fails with "Internal Error")
// AnnotationRule(),
AnnotationRule(),
ChainWrappingRule(),
CommentSpacingRule(),
FilenameRule(),
FinalNewlineRule(),
// disabled until there is a way to suppress rules globally (https://git.io/fhxnm)
// PackageNameRule(),
// disabled until auto-correct is working properly
// (e.g. try formatting "if (true)\n return { _ ->\n _\n}")
// MultiLineIfElseRule(),
PackageNameRule(),
MultiLineIfElseRule(),
IndentationRule(),
MaxLineLengthRule(),
ModifierOrderRule(),
NoBlankLineBeforeRbraceRule(),
NoConsecutiveBlankLinesRule(),
NoEmptyClassBodyRule(),
// disabled until it's clear what to do in case of `import _.it`
// NoItParamInMultilineLambdaRule(),
NoItParamInMultilineLambdaRule(),
NoLineBreakAfterElseRule(),
NoLineBreakBeforeAssignmentRule(),
NoMultipleSpacesRule(),
NoSemicolonsRule(),
NoTrailingSpacesRule(),
NoUnitReturnRule(),
NoUnusedImportsRule(),
// Disabling because it is now allowed by the Jetbrains styleguide, although it is still disallowed by
// the Android styleguide.
// Re-enable when there is a way to globally disable rules
// See discussion here: https://github.com/pinterest/ktlint/issues/48
// NoWildcardImportsRule(),
NoWildcardImportsRule(),
ParameterListWrappingRule(),
SpacingAroundColonRule(),
SpacingAroundCommaRule(),
Expand Down
40 changes: 39 additions & 1 deletion ktlint/src/main/kotlin/com/pinterest/ktlint/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import java.io.IOException
import java.io.PrintStream
import java.math.BigInteger
import java.net.URLDecoder
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.security.MessageDigest
Expand Down Expand Up @@ -234,6 +235,12 @@ object Main {
)
private var experimental: Boolean = false

@Option(names = arrayOf("--ktlintignore"), description = arrayOf("Path to .ktlintignore (defaults to working dir)"))
private var ktlintIgnorePath: String? = null

// Rules from .ktlintignore that will be globally disabled
private val disabledRules = mutableSetOf<String>()

@Parameters(hidden = true)
private var patterns = ArrayList<String>()

Expand Down Expand Up @@ -300,6 +307,10 @@ object Main {
exitProcess(0)
}
val start = System.currentTimeMillis()

// Parse the .ktlintignore file
parseKtlintIgnore(ktlintIgnorePath ?: ".")

// load 3rd party ruleset(s) (if any)
val dependencyResolver = lazy(LazyThreadSafetyMode.NONE) { buildDependencyResolver() }
if (!rulesets.isEmpty()) {
Expand Down Expand Up @@ -425,7 +436,11 @@ object Main {
}
}
?: emptyMap<String, String>()
) + cliUserData + ("file_path" to fileName)
) +
cliUserData +
// For now, use a global list
("disabled_rules" to disabledRules.joinToString(",")) +
("file_path" to fileName)
}
}

Expand Down Expand Up @@ -784,6 +799,29 @@ object Main {
map
}

/**
* Parses the .ktlintignore file, a list of ids of rules to globally disable. One rule per line.
*/
private fun parseKtlintIgnore(path: String) {
val ktlintIgnorePath = Paths.get(File(path).canonicalPath).resolve(".ktlintignore") ?: return
if (!Files.exists(ktlintIgnorePath)) {
return
}

ktlintIgnorePath.toFile().forEachLine {
val line = it.trim()
if (line.isNotBlank() && !line.startsWith("//")) {
disabledRules.add(line)
}
}
if (debug && disabledRules.isNotEmpty()) {
System.err.println("[DEBUG] Disabled rules:")
disabledRules.forEach {
System.err.println("[DEBUG] $it")
}
}
}

private fun lint(
fileName: String,
text: String,
Expand Down

0 comments on commit 6f8bb56

Please sign in to comment.