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

Disable/re-enable rules from within source code comments. Fixes #4. #111

Merged
merged 6 commits into from
Sep 1, 2015
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
names to start with an underscore.
[JP Simard](https://github.com/jpsim)

* Disable and re-enable rules from within source code comments using
`// swiftlint:disable:$IDENTIFIER` and `// swiftlint:enable:$IDENTIFIER`.
Copy link
Contributor

Choose a reason for hiding this comment

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

i'd prefer // swiftlint:disable force_unwrap

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

that would make it more similar to rubocop, and I have no main reason to keep that separator a colon... so ok!

[JP Simard](https://github.com/jpsim)
[#4](https://github.com/realm/SwiftLint/issues/4)

##### Bug Fixes

* None.
Expand Down
44 changes: 43 additions & 1 deletion Source/SwiftLintFramework/File+SwiftLint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,51 @@
import SourceKittenFramework
import SwiftXPC

typealias Line = (index: Int, content: String)
public typealias Line = (index: Int, content: String)

public typealias Region = (startLine: Int, endLine: Int, disabledRules: [String])

public enum CommandAction: String {
case Enable = "enable"
case Disable = "disable"
}

public typealias Command = (CommandAction, String, Int)

extension File {
public func regions() -> [Region] {
let nsStringContents = contents as NSString
let commands = matchPattern("swiftlint:(enable|disable):force_cast")
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't force_cast be .+ and then captured to determine which rule it is?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the rule capturing was already being done by NSScanner, but I had accidentally hardcoded force_cast in here as part of my testing.

.flatMap { range, syntaxKinds -> Command? in
let scanner = NSScanner(string: nsStringContents.substringWithRange(range))
scanner.scanString("swiftlint:", intoString: nil)
var actionString: NSString? = nil
scanner.scanUpToString(":", intoString: &actionString)
let start = range.location
if let actionString = actionString as String?,
action = CommandAction(rawValue: actionString),
lineRange = nsStringContents.lineRangeWithByteRange(start: start, length: 0) {
scanner.scanString(":", intoString: nil)
let ruleStart = scanner.string.startIndex.advancedBy(scanner.scanLocation)
let rule = scanner.string.substringFromIndex(ruleStart)
return (action, rule, lineRange.start)
}
return nil
}
let totalNumberOfLines = contents.lines().count
var regions: [Region] = [(1, commands.first?.2 ?? totalNumberOfLines, [])]
var disabledRules = Set<String>()
let commandPairs = zip(commands, Array(commands.dropFirst().map({Optional($0)})) + [nil])
for (command, nextCommand) in commandPairs {
switch command.0 {
case .Disable: disabledRules.insert(command.1)
case .Enable: disabledRules.remove(command.1)
}
regions.append((command.2, nextCommand?.2 ?? totalNumberOfLines, Array(disabledRules)))
}
return regions
}

public func matchPattern(pattern: String,
withSyntaxKinds syntaxKinds: [SyntaxKind]) -> [NSRange] {
return matchPattern(pattern).filter { _, kindsInRange in
Expand Down
15 changes: 14 additions & 1 deletion Source/SwiftLintFramework/Linter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,20 @@ public struct Linter {
private let rules: [Rule]

public var styleViolations: [StyleViolation] {
return rules.flatMap { $0.validateFile(self.file) }
let regions = file.regions()
return rules.flatMap { rule in
return rule.validateFile(self.file).filter { styleViolation in
guard let line = styleViolation.location.line else {
return true
}
guard let violationRegion = regions.filter({
$0.startLine < line && $0.endLine > line
}).first else {
return true
}
return !violationRegion.disabledRules.contains(rule.identifier)
}
}
}

public var ruleExamples: [RuleExample] {
Expand Down