-
Notifications
You must be signed in to change notification settings - Fork 509
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
Implement .ktlintignore for globally disabling rules #459
Conversation
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
@@ -0,0 +1,7 @@ | |||
// disabled ("./mvnw clean verify" fails with "Internal Error") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is kind of goofy, but I liked the idea of allowing comments so that we can explain why a rule is disabled
) + | ||
cliUserData + | ||
// For now, use a global list | ||
("disabled_rules" to disabledRules.joinToString(",")) + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is where we'd handle logic around a .ktlintignore file that's formatted more like an .editorconfig file.
Open for suggestions on good ways to test this. |
@JLLeitschuh @jaredsburrows @jeremymailen thoughts? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of introducing this feature!
@@ -300,6 +307,10 @@ object Main { | |||
exitProcess(0) | |||
} | |||
val start = System.currentTimeMillis() | |||
|
|||
// Parse the .ktlintignore file | |||
parseKtlintIgnore(ktlintIgnorePath ?: ".") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be useful to put support classes in the core module to locate any .ktlintignore files and parse them into disabled rules userdata. This would allow tools not invoking the CLI portion of ktlint to have an easy way to support .ktlintignore exactly the same way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good. You actually know much more about the internals of ktlint
than I do... 🤦♀
@@ -234,6 +235,12 @@ object Main { | |||
) | |||
private var experimental: Boolean = false | |||
|
|||
@Option(names = arrayOf("--ktlintignore"), description = arrayOf("Path to .ktlintignore (defaults to working dir)")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would they pass in a path or would it happen by convention such as working directory plus home directory similar to .gitignore? I guess global prefs make less sense here -- possibly at each package level? Although I'm not sure if it's easy to support or even worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For kotlinter-gradle
I suppose I'd start by saying the file had to be in the gradle project root. Of course ktlint CLI is agnostic to the idea of a project.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you look a bit further down, it does default to ".".
And yes, I was unsure whether we want/need to support multiple ignore/config files. I can certainly imagine a scenario (eg codegen files) but I'm unsure how common it would be. It seems like the biggest ask is for global disabling.
I originally considered a .ktlintconfig
with the same syntax as .editorconfig
so you could easily disable rules on a per-path basis but thought maybe the simpler approach was fine for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would agree with @shashachu, that it should be possible to add additionally rules to exclude in subprojects and .ktlintconfig
should behave like .editorconfig
.
@@ -0,0 +1,7 @@ | |||
// disabled ("./mvnw clean verify" fails with "Internal Error") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: .xyzignore files are conventionally lists of file expressions to ignore. What if it was .ktlintconfig
and perhaps in something like toml?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes - it's goofy. Probably a better format is something like .editorconfig
:
[*]
disable_rules=no-wildcard-imports
[**/library/*]
disable_rules=no-wildcard-imports,package-name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes - it's goofy. Probably a better format is something like .editorconfig:
yes, this format of the file looks better and will allow in the future add more ktlint
specific configuration here.
@@ -254,6 +257,10 @@ object KtLint { | |||
} | |||
} | |||
|
|||
private fun filterDisabledRules(rootNode: ASTNode, fqRuleId: String): Boolean { | |||
return rootNode.getUserData(DISABLED_RULES)?.contains(fqRuleId) == false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: this will currently work only with the standard ruleset. If you have an experimental one (or any other custom ruleset), you have to specify the rule with the prefix inside .ktlintignore
(as you can see it's being added to the rule id at the line 207). So something like experimental:indent
- I guess this should be mentioned in the docs or something :) Or we could change this to any { fqRuleId.contains(it) }
, if we want to be independent of the ruleset (as I assume rule ids most of the time are unique)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's correct. I'd rather require fully namespaced rules than unexpectedly disabling a rule with a name collision. We would definitely update the docs if we move forward with this.
CC: @Tapchicoma |
This project already uses |
It felt like an abuse of |
Agreed that that would be an abuse of .editorconfig, which is a format that extends beyond just ktlint. On the other hand, each new configuration file required for ktlint makes integration with other systems a bit more difficult. Would it make sense to add a new custom configuration file that could handle both the ignore rules and the editorconfig rules? Ideally, editorconfig would still be supported, but have fewer features. |
That would be fine as well. I do think that the ignore rules are currently the only ktlint-specific config, though. |
/** | ||
* Parses the .ktlintignore file, a list of ids of rules to globally disable. One rule per line. | ||
*/ | ||
private fun parseKtlintIgnore(path: String) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, this function should repeat the logic of .editorconfig
lookup - https://editorconfig.org/#file-location
Implementation:
override fun of(dir: Path) = |
This would allow to define global ktlint rules in project root and have sub-project specific one, that will enhance/override global rules.
I agree with @jaredsburrows, from what I see - adding just custom property Though required change would be move detecting and parsing |
Thanks for the feedback, everyone. I'll close this PR and open another one using either |
Sounds good, thanks! |
How's this going @shashachu ? Are there plans on opening that alternative PR? Let me know if you need any help, this is a feature I'm interested in. |
@JorgeCastilloPrz yes, there are still plans to do the PR; things have just been extremely busy. I have a PR in-progress locally, so I will aim to put it up by the end of the week. |
Is there a place we can reach you for direct chat @shashachu ? Maybe Kotlinlang Slack? We can try to help on coding it if you're busy, we'd just need some indications since we're not familiar with the codebase. |
All, thanks for your patience. Pushed the updated editorconfig-based-PR here: #503 Please feel free to patch in and test locally. @JorgeCastilloPrz I am working on getting a slack channel setup in the Pinterest slack team so that I can invite external contributors. |
Thanks for your work on it! We'll keep a close eye on that PR :) |
Fixes #208