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

Add rule requiring imports be sorted #991

Closed
wants to merge 7 commits into from
Prev Previous commit
Next Next commit
fixup! fixup! fixup! Add rule requiring imports be sorted
sberrevoets committed Dec 22, 2016

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit af792c28eb7d7b31959d41c429d2e08f9f514684
2 changes: 1 addition & 1 deletion Source/SwiftLintFramework/Rules/SortedImportsRule.swift
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ public struct SortedImportsRule: ConfigurationProviderRule, OptInRule {
)

public func validateFile(_ file: File) -> [StyleViolation] {
let pattern = "import (\\w+)"
let pattern = "import\\s+\\w+"
Copy link
Collaborator

Choose a reason for hiding this comment

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

What do you think of this implementation instead?

let importRanges = file.matchPattern("import\\s+\\w+",
                                     withSyntaxKinds: [.keyword, .identifier])
let nsstringContents = file.contents.bridge()
let importLength = 6
let modulesAndOffsets: [(String, Int)] = importRanges.map { range in
    let rangeAfterImport = NSRange(location: range.location + importLength,
        length: range.length - importLength)
    let module = nsstringContents.substring(with: rangeAfterImport)
        .trimmingCharacters(in: .whitespacesAndNewlines)
    let offset = NSMaxRange(range) - module.bridge().length
    return (module, offset)
}
let modulePairs = zip(modulesAndOffsets, modulesAndOffsets.dropFirst())
let violatingOffsets = modulePairs.flatMap { previous, current in
    return current < previous ? current.1 : nil
}
return violatingOffsets.map {
    StyleViolation(ruleDescription: type(of: self).description,
                          severity: configuration.severity,
                          location: Location(file: file, characterOffset: $0))
}

It avoids the flatMap/previousMatch side-effect mutation, avoids some of the bridging operations, leverages the existing matchPattern(_:withSyntaxKind:) method and avoids the cutsey use of defer.

Copy link
Author

Choose a reason for hiding this comment

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

To be completely honest, for me personally the hit on readability wouldn't be worth the benefits in this case:

  • Not needing previousMatch is definitely nice, no argument there
  • The bridging is reduced to once for every import - which is a decent win but probably not very noticeable considering the matches are short and there aren't many of them
  • I wasn't aware of matchPattern(_:withSyntaxKind:), but it appears that would even work with the current implementation (which I agree would definitely be nicer!)
  • I personally don't have a huge problem with the defer, but I can see how that can require a double-take

That said, I'm totally onboard with following the general coding practices of the existing codebase (which your proposal seems more in line with) so I've pushed another commit with that implementation.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I actually agree with all your points, I didn't share that sample thinking it was necessarily superior, just had some different ideas and I wanted to spark a discussion.


var previousMatch = ""
return file.matchPattern(pattern).flatMap { range, kinds in