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

Fix ktlint-disable directive on package statement #1038

Conversation

paul-dingemans
Copy link
Collaborator

  • Split unit tests for error suppression into multiple tests
  • Extract the creation of the SuppressionHints to extension
    methods for readability and reuseability

Description

According to the documentation the ktlint-disable can be appended as an EOL comment to indicate that all rules for this file should be disabled. However that didn't work

                package com.pinterest.ktlint // ktlint-disable

                import something.*

Adding it as block comment before the package statement resulted in an internal error on the import rule. I have not tried to fix that.

Now it is possible to:

  • Disable all rules for this file by adding // ktlint-disable after the package statement
  • Disable specific rules for this file by adding // ktlint-disable rule-id after the package statement
  • After disabling a or all rules via the package statement, the rules can be enabled again.

Paul Dingemans added 2 commits December 27, 2020 19:42
* Split unit tests for error suppression into multiple tests
* Extract the creation of the SuppressionHints to extension
  methods for readability and reuseability
paul-dingemans pushed a commit to paul-dingemans/ktlint that referenced this pull request Jan 9, 2021
…dentTest.kt.txt

Avoid breaking the build as long as the ktlint-disable directive on the package
statement is not recognized. See pull request pinterest#1038
PsiWhiteSpace?
)?.let { it.node.startOffset + it.text.lastIndexOf('\n') + 1 } ?: 0
result.add(SuppressionHint(IntRange(lineStart, node.startOffset), HashSet(args)))
if (node.isDisabledOnPackageStatement()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

KtLint readme on this case is not very clear.

import package.* // ktlint-disable

Should disable any rule check on this particular line.

It doesn't make sense to disable all the rules for the whole file - better to either not pass it to KtLint or exclude it via GLOB pattern. To disable all the rules for the region, better to use:

/* ktlint-disable */
<some code>
/* ktlint-enable */

So, for the case <some code> // ktlint-disable please use createLineDisableSupressionHint and pass emptySet() as disabledRules.

Copy link
Collaborator Author

@paul-dingemans paul-dingemans Jan 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like puzzles. But this review remark really confused me at first. I have the feeling that we were discussing different, albeit related, topics. Let's try to unravel this.

KtLint readme on this case is not very clear.

import package.* // ktlint-disable

Should disable any rule check on this particular line.

This code example is confusing for different reasons:

  • There is no apparent reason why this statement should be excluded by ktlint as there is no rule violated.
  • The word package after import took precedence for me. So I read this statement as being the package statement:
package com.example.mypackage // ktlint-disable

I have modified this.

It doesn't make sense to disable all the rules for the whole file - better to either not pass it to KtLint or exclude it via GLOB pattern.
It is only possible to follow this approach when you know which files need to be excluded from processing by ktlint. In bigger code bases with which you are not familiar you may just not know which files would need to be excluded. When you are able to specify it explicitly in the file itself, you can also document the reasoning for this. This approach allows to lint/format the entire code base without having to know the files which need to be excluded.

So, for the case <some code> // ktlint-disable please use createLineDisableSupressionHint and pass emptySet() as disabledRules.

I have removed the code for the ktlint-disable directive on the package statement as I no longer needed it after fixing some other bugs.

I found out that certain bugs are caused by the fact that some rules perform a kind of initialization as soon as the rootNode is visited. If for some reasons, for example disabling a rule, the rootNode is not visited then the rule would not have been initialized correctly. I have split initialization and visiting.

Next problem was that the IndentationRule modifies the ASTNode hierarchy by inserting additional node. Disabling the indentation rule was not always recognized by the SupressedRegionLocator. I have fixed and simplified this locator.

The changes can best be reviewed per commit.

Paul Dingemans added 5 commits January 17, 2021 09:43
Make a clearer distinction between the initialization of a rule
versus processing (e.g. visiting) the rule with a node. A rule
that implements the Rule.Modifier.InitializeRoot interface will
be called with the rootNode to initialize the rule. After that
the rule will be visited for each node (including the root
node) unless the node is suppressed by a ktlint-disable
directive.
When starting a new block in which a rule is disabled, then define the
range of this block from the startOffset of that block until eternity
(Int.MAX_VALUE). When the block is closed explicitly by a ktlint-enable
directive, or when closing all open blocks at the end of the collect
phase, the end position of the block is overwritten with the offset of
the end of the file.

This fixes a very specific bug in the IndentationRule which on occasion
modifies the structure of the ASTNodes by inserting new nodes. As of
such, the rootNode can contain offsets which are not equal to zero but
which still need to be suppressed. This bug can not be tested in the
unit test of the SupressedRegionLocator but is verified in the unit
test IndentationRuleTest.
The special disable directive on the package statement is no
longer required because disabling via the block comment has
been improved. The latter is more clear and consistent.
Copy link
Collaborator

@Tapchicoma Tapchicoma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your effort, but it seems too much changes trying to fix #1029

This issue could be fixed by changing SuppressedRegionLocator.kt#74 into:

        if (node is PsiComment && node.prevSibling != null) {

that will ignore all lines containing only // ktlint-disabled comment.

@pauldingemans
Copy link

As stated in my previous comment, my changes also fix other problems. Please take that into account as well.

@paul-dingemans
Copy link
Collaborator Author

PR is too far out of sync with current master.

romtsn pushed a commit that referenced this pull request Oct 24, 2021
* Fix multiline string indentation

The indenting margin is determined analog to the trimIndent function. Spaces and
tabs are both handled as single indent characters. The indentation of the closing
quotes is not relevant unless the opening and closing quotes are on different
lines but does not contain any content which is weird but still valid Kotlin
code. The 'IndentationRuleTrimIndentTest' is added to clarify and validate the
behavior of the trimIndent function.

Content of a multiline string should not be indented with respect to the closing
quotes (note that the opening quotes can be on a previous line, for example
after an assignment).

File 'format-raw-string-trim-indent.kt.spec' is changed for following reasons:
* Example code was not valid Kotlin code
* Changed a comment in an example to explain why the autocorrected code
  actually looks worse than the original. This will be fixed in a next PR.

* Fix code which does not comply to changed indentation rules

* Rename file IndentationRuleTrimIndentTest.kt to IndentationRuleTrimIndentTest.kt.txt

Avoid breaking the build as long as the ktlint-disable directive on the package
statement is not recognized. See pull request #1038

* Fix indentation in unit tests

* Remove changing the indentation margin of a multiline raw string literal except for the line with the closing quotes

* Change message when closing quotes of multiline raw string literal are incorrectly indented

* Remove IndentationRuleTrimIndentTest

The indentation margin is no longer been altered by the indent rule. So there is no need anymore
to verify the behavior of the trimIndent function.

Co-authored-by: Paul Dingemans <pdingemans@bol.com>
@paul-dingemans paul-dingemans deleted the fix-ktlint-disable-on-package branch October 30, 2021 10:11
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.

3 participants