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

Support file-level ignore directive for specific rules #950

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

TTOzzi
Copy link
Member

@TTOzzi TTOzzi commented Mar 1, 2025

Resolve #927

I have modified the function that disables specific rules in node-level directive so that it can also be reused for file-level directive, ensuring both follow the same logic.

Previously, if a file-level directive appeared in the topmost comment, we would always skip visiting nodes. However, with this change, we now visit child nodes when only specific rules are disabled. As a result, this caused an unintended side effect in cases where the OrderedImports rule was enabled. Specifically, a directive included in the leadingTrivia of a sorted import statement was being reordered along with the imports.
To resolve this, I modified the OrderedImports rule to treat the swift-format-ignore-file directive as part of the file header.

Additionally, to avoid simple string comparisons like:

if line.description.contains("swift-format-ignore-file") {

I have created an IgnoreDirective enum to handle ignore directives more cleanly.

For easier review, I have split the commits.
Once the review is complete, I will squash and force push them before merging. 🙂

@ahoppen
Copy link
Member

ahoppen commented Mar 3, 2025

@TTOzzi The Windows CI failures should be addressed by #951. Could you rebase your changes on top of main so that we can pick up that fix for CI?

@TTOzzi TTOzzi force-pushed the ignore-specific-rules-in-file branch from 618e38e to ab12d60 Compare March 3, 2025 23:11
@TTOzzi
Copy link
Member Author

TTOzzi commented Mar 3, 2025

@TTOzzi The Windows CI failures should be addressed by #951. Could you rebase your changes on top of main so that we can pick up that fix for CI?

Oh, thank you for identifying the cause of the failure 😃
I’ve rebased it.

Copy link
Member

@ahoppen ahoppen 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 and thanks for remembering to not re-order the ignore directive in ordered imports. I’ve got a couple of thoughts inline.

@@ -651,4 +651,36 @@ final class OrderedImportsTests: LintOrFormatRuleTestCase {
]
)
}

func testImportsOrderWithFileIgnoreDirective() {
assertFormatting(
Copy link
Member

Choose a reason for hiding this comment

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

Does this also end up adding a newline after // swift-format-ignore-file if no re-ordering is necessary? Eg. for

// swift-format-ignore-file
import LibA
import LibB

To be clear, I’m fine with that, just want to check and record the behavior in a test case.


One thing I did notice is that I think this flips comments order around if you have eg.

// We need to ignore this file because it is generated
// swift-format-ignore-line

import Foundation

Maybe swift-format-ignore-line just needs to flush the commentBuffer into the headerBuffer similar to what a blank line does.

Comment on lines +116 to +123
private var pattern: String {
return #"^\s*\/\/\s*"# + description + #"((:\s+(([A-z0-9]+[,\s]*)+))?$|\s+$)"#
}

/// Rule ignore regex object.
fileprivate var regex: NSRegularExpression {
return try! NSRegularExpression(pattern: pattern, options: [])
}
Copy link
Member

Choose a reason for hiding this comment

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

Since you are working on this already, I’ve got a few thoughts:

  • The regex restriction after the : seems a little restrictive to me. Eg. I imagine it would be fine to try and debug why a future rule that contains a _ cannot be ignored using a directive. Maybe we can just make the regex a prefix match. @allevato Do you remember why the regex is this specific?
  • This re-compiles the regex every time regex is accessed. Compiling regular expressions is fairly expensive, so I’d prefer to cache that.
  • Could we use Swift’s Regex instead of NSRegularExpression?
  • Or, alternatively, would it be easier to write a simple line matcher and avoid going through regex matching at all?

All except for avoiding to re-compile the regex don’t need to be in this PR.

Copy link
Member

Choose a reason for hiding this comment

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

@allevato Do you remember why the regex is this specific?

Not off the top of my head. It may have just been to capture precisely what we expected rule names to look like at the time. I think it would be fine to be a little less prescriptive in the regex itself, if it simplifies things.

Could we use Swift’s Regex instead of NSRegularExpression?

We'd have to raise our minimum deployment version, which is macOS 12.0 right now, since Regex requires 13.0. If that aligns with other binaries in the Swift toolchain, I'd love to drop NSRegularExpression (holistically, in a separate 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.

No syntax to disable rule for file
3 participants