Add blank line check between package and import statements#3266
Add blank line check between package and import statements#3266maheen8q wants to merge 24 commits intopinterest:masterfrom
Conversation
…, and resolve TOOD's
Remove deprecated methods which were marked for removal in Ktlint 2.0, and resolve TODO's
If a files starts with the UTF BOM character, it is removed before the file is formatted, and restored after formatting. When the UTF BOM character is not at the start of the file, it should not be removed before formatting, and has to be preserved in the formatted file. The existing test for a file starting with UTF BOM character was not effective because the file was not modified at all. In that case, the unmodified input is returned by ktlint format. Closes pinterest#3220
paul-dingemans left a comment
There was a problem hiding this comment.
Tnx for giving this a try so quickly. Please try to adhere more with existing code patterns and standards in current ktlint code.
| } | ||
| } | ||
| // https://developer.android.com/kotlin/style-guide#structure | ||
| if (node.elementType == IMPORT_DIRECTIVE) { |
There was a problem hiding this comment.
Looking backwards. (or up) in the AST to find the spot where to fix the AST causes problems. You need to find the PACKAGE statement, and then look forwards whether it is followed by a blank line instead.
| if (newlineCount < 2) { | ||
| val decision = emit( | ||
| node.startOffset, | ||
| "Missing blank line between package statement and import statements", |
There was a problem hiding this comment.
Follow the existing patterns in other rules, and use the .ifAutocorrectAllowed extension to fix the violation.
| package com.example | ||
| import foo.bar | ||
| """.trimIndent() | ||
| val formattedCode = """ |
There was a problem hiding this comment.
It looks like that you did not apply Ktlint formatting.
| } | ||
| | ||
| @Test | ||
| fun `passes when blank line exists between package and import`() { |
There was a problem hiding this comment.
Use naming patterns consisting with rest of ktlint, eg Given ... then (all tests)
| } | ||
| | ||
| @Test | ||
| fun `autocorrects missing blank line between package and import`() { |
There was a problem hiding this comment.
This test should be merged with previous test. There is no need to have separate tests for report and fixing.
| .hasLintViolation( | ||
| line = 2, | ||
| col = 1, | ||
| detail = "Missing blank line between package statement and import statements", |
There was a problem hiding this comment.
Don use named arguments for hasLintViolation
| """.trimIndent() | ||
| packageNameRuleAssertThat(code) | ||
| .hasLintViolation(2, 1, "Missing blank line between package statement and import statements") | ||
| .isFixedTo(formattedCode) |
There was a problem hiding this comment.
This is a non-existing extension function in the Ktlint AssertThat library. Probably you meant isFormattedAs/
| Review comments addressed, please take another look |
…terest#3267) Fix backwards compatibility with Ktlint 1.x rulesets by readding the RuleAutocorrectApproveHandler, and overriding the methods of the RuleV2 method to fallback to the actual implementation of the Rule (V1). In Ktlint CLI ensure that custom ruleset with RuleSetProviderV3 interface is loaded successful, and a deprecation warning is printed. Fix Ktlint CLI to load the custom rule sets only once by initialized the ruleProviders lazily. Remove the main,kt.test file from the custom-ruleset resource directory as it is not used.
paul-dingemans left a comment
There was a problem hiding this comment.
Tnx for follow-up. I have some more remarks.
| val nextCodeSibling = packageNode.nextCodeSibling20 | ||
| if (nextCodeSibling?.elementType == IMPORT_DIRECTIVE) { | ||
| val newlineCount = nextSibling.text.count { it == '\n' } | ||
| if (newlineCount < 2) { |
There was a problem hiding this comment.
The style guide describes that there should be exactly 1 blank line between package and imports. So test on on "newLineCount != 2, and add a test:
package foo import bar.* Also, tests corner case with comment above imports
package foo // Some comment import bar.* | } | ||
| } | ||
| | ||
| // https://developer.android.com/kotlin/style-guide#structure |
There was a problem hiding this comment.
In hindsight this should be in separate rule. I asked you change extend the package rule if it existed. When I wrote that comment, I did not have access to the repository to check that. Now I see that the new check is added to the PackageNameRule which might be confusing.
| } | ||
| } | ||
| | ||
| // FIX: Renamed using "Given ... then" pattern |
There was a problem hiding this comment.
Remove all "FIX" comments
…results in a compilation error (pinterest#3268) Closes pinterest#3213
| Hi @paul-dingemans , thanks for the feedback! I've moved the blank line check into a separate PackageImportSpacingRule as suggested. Here's a summary of all changes made: Moved blank line between package and import check to new PackageImportSpacingRule No blank line between package and import Removed blank line tests from PackageNameRuleTest Please take another look, happy to make any further changes! |
| * https://developer.android.com/kotlin/style-guide#structure | ||
| */ | ||
| @SinceKtlint("1.x", EXPERIMENTAL) | ||
| public class PackageImportSpacingRule : StandardRule("package-import-spacing") { |
There was a problem hiding this comment.
This should have resulted in a failing test. The rule is only annotated with an EXPERIMENTAL tag, but has not implemented the marker interface Experimental.
Please change to:
@SinceKtlint("2.,0", EXPERIMENTAL) public class PackageImportSpacingRule : StandardRule("package-import-spacing"), RuleV2.Experimental { ...dard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/PackageImportSpacingRule.kt Show resolved Hide resolved
| val VALID_PACKAGE_NAME_REGEXP = | ||
| "[a-z_][a-zA-Z\\d_]*(\\.[a-z_][a-zA-Z\\d_]*)*" | ||
| .regExIgnoringDiacriticsAndStrokesOnLetters() |
There was a problem hiding this comment.
Please revert all changes on the PackageName rule.
| ) { | ||
| node | ||
| .takeIf { node.elementType == PACKAGE_DIRECTIVE } | ||
| .takeIf { it.elementType == PACKAGE_DIRECTIVE } |
There was a problem hiding this comment.
Please revert all changes on the PackageName rule.
| // The Kotlin inspections (preference > Editor > Inspections) for 'Package naming convention' allows | ||
| // underscores as well. But as this has been forbidden by KtLint since early versions, this is still | ||
| // prohibited. |
There was a problem hiding this comment.
Please revert all changes on the PackageName rule.
…results in a compilation error (pinterest#3269) Closes pinterest#3213
| Hi Paul, thank you for the detailed feedback and the AST explanation! |
…blank-line' into pr/3266 # Conflicts: # ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/PackageImportSpacingRule.kt # ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/PackageImportSpacingRuleTest.kt
| Hmm, I had to make quite some changes to make it actually work. Did you run the tests on your local machine? Also, documentation was missing. |
Description
Add blank line check between package and import statements
The Android Kotlin Style Guide requires exactly one blank line between
the package statement and import statements:
https://developer.android.com/kotlin/style-guide#structure
ktlint was not enforcing this rule. This PR extends the existing
PackageNameRuleto also check for the missing blank line, withautocorrect support.
Fixes #3251
Checklist
Before submitting the PR, please check following (checks which are not relevant may be ignored):
Closes #<xxx>orFixes #<xxx>(replace<xxx>with issue number)Documentation is updated. See difference between snapshot and release documentation