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

Implement .ktlintignore for globally disabling rules #459

Closed
wants to merge 1 commit into from

Conversation

shashachu
Copy link
Contributor

Fixes #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

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")
Copy link
Contributor Author

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(",")) +
Copy link
Contributor Author

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.

@shashachu
Copy link
Contributor Author

Open for suggestions on good ways to test this.

@shashachu shashachu changed the title Implement .ktlintigore for globally disabling rules Implement .ktlintignore for globally disabling rules Jun 6, 2019
@shashachu
Copy link
Contributor Author

@JLLeitschuh @jaredsburrows @jeremymailen thoughts?

Copy link
Contributor

@jeremymailen jeremymailen left a 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 ?: ".")
Copy link
Contributor

@jeremymailen jeremymailen Jun 7, 2019

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.

Copy link
Contributor Author

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)"))
Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Collaborator

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")
Copy link
Contributor

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?

Copy link
Contributor Author

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

Copy link
Collaborator

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
Copy link
Collaborator

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)

Copy link
Contributor Author

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.

@JLLeitschuh
Copy link
Contributor

CC: @Tapchicoma

@jaredsburrows
Copy link
Contributor

This project already uses .editorconfig, why not add this functionality to .editorconfig? This way we do not have to have another file to configure ktlint.

@shashachu
Copy link
Contributor Author

This project already uses .editorconfig, why not add this functionality to .editorconfig? This way we do not have to have another file to configure ktlint.

It felt like an abuse of .editorconfig. I suppose disabling lint rules falls loosely under 'coding style', but it doesn't really seem like it fits the spirit of what an .editorconfig is supposed to do. I'm more on the side of it being a separate file, but it's not a dealbreaker for me.

@bethcutler
Copy link
Contributor

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.

@shashachu
Copy link
Contributor Author

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) {
Copy link
Collaborator

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:

This would allow to define global ktlint rules in project root and have sub-project specific one, that will enhance/override global rules.

@Tapchicoma
Copy link
Collaborator

This project already uses .editorconfig, why not add this functionality to .editorconfig? This way we do not have to have another file to configure ktlint.

I agree with @jaredsburrows, from what I see - adding just custom property ktlint-disabled-rules to .editorconfig that falls under domain-specific-properties should be enough.

Though required change would be move detecting and parsing .editorconfig files to ktlint-core, so @jeremymailen plugin could also support this.

@shashachu
Copy link
Contributor Author

Thanks for the feedback, everyone. I'll close this PR and open another one using either .editorconfig or a .ktlintconfig file.

@shashachu shashachu closed this Jun 10, 2019
@jaredsburrows
Copy link
Contributor

Sounds good, thanks!

@JorgeCastilloPrz
Copy link

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.

@shashachu
Copy link
Contributor Author

@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.

@JorgeCastilloPrz
Copy link

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.

@shashachu
Copy link
Contributor Author

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.

@JorgeCastilloPrz
Copy link

JorgeCastilloPrz commented Jun 28, 2019

Thanks for your work on it! We'll keep a close eye on that PR :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for globally disabling a rule
8 participants