mirror of
https://github.com/realm/SwiftLint.git
synced 2026-06-06 20:18:40 +00:00
@@ -13,6 +13,11 @@
|
||||
[JP Simard](https://github.com/jpsim)
|
||||
[#277](https://github.com/realm/SwiftLint/issues/277)
|
||||
|
||||
* Support command comment modifiers (`previous`, `this` & `next`) to limit the
|
||||
command's scope to a single line.
|
||||
[JP Simard](https://github.com/jpsim)
|
||||
[#222](https://github.com/realm/SwiftLint/issues/222)
|
||||
|
||||
##### Bug Fixes
|
||||
|
||||
* Fix multibyte handling in many rules.
|
||||
|
||||
@@ -79,11 +79,13 @@ directory to see the currently implemented rules.
|
||||
|
||||
### Disable a rule in code
|
||||
|
||||
Rules can be disabled with a comment inside a source file with the following format:
|
||||
Rules can be disabled with a comment inside a source file with the following
|
||||
format:
|
||||
|
||||
`// swiftlint:disable <rule>`
|
||||
|
||||
The rule will be disabled until the end of the file or until the linter sees a matching enable comment:
|
||||
The rule will be disabled until the end of the file or until the linter sees a
|
||||
matching enable comment:
|
||||
|
||||
`// swiftlint:enable <rule>`
|
||||
|
||||
@@ -93,10 +95,26 @@ For example:
|
||||
// swiftlint:disable colon
|
||||
let noWarning :String = "" // No warning about colons immediately after variable names!
|
||||
// swiftlint:enable colon
|
||||
let yesWarning :String = "" // Warning generated about colons immediately after variable names
|
||||
let hasWarning :String = "" // Warning generated about colons immediately after variable names
|
||||
```
|
||||
|
||||
Run `swiftlint rules` to print a list of all available rules and their identifiers.
|
||||
It's also possible to modify a disable or enable command by appending
|
||||
`:previous`, `:this` or `:next` for only applying the command to the previous,
|
||||
this (current) or next line respectively.
|
||||
|
||||
For example:
|
||||
|
||||
```swift
|
||||
// swiftlint:disable:next force_cast
|
||||
let noWarning = NSNumber() as! Int
|
||||
let hasWarning = NSNumber() as! Int
|
||||
let noWarning2 = NSNumber() as! Int // swiftlint:disable:this force_cast
|
||||
let noWarning3 = NSNumber() as! Int
|
||||
// swiftlint:disable:previous force_cast
|
||||
```
|
||||
|
||||
Run `swiftlint rules` to print a list of all available rules and their
|
||||
identifiers.
|
||||
|
||||
### Configuration
|
||||
|
||||
@@ -125,14 +143,6 @@ line_length: 110
|
||||
type_body_length:
|
||||
- 300 # warning
|
||||
- 400 # error
|
||||
# parameterized rules are first parameterized as a warning level, then error level.
|
||||
variable_name_max_length:
|
||||
- 40 # warning
|
||||
- 60 # error
|
||||
# parameterized rules are first parameterized as a warning level, then error level.
|
||||
variable_name_min_length:
|
||||
- 3 # warning
|
||||
- 2 # error
|
||||
reporter: "csv" # reporter type (xcode, json, csv, checkstyle)
|
||||
```
|
||||
|
||||
|
||||
@@ -11,18 +11,22 @@ import SourceKittenFramework
|
||||
import SwiftXPC
|
||||
|
||||
internal func regex(pattern: String) -> NSRegularExpression {
|
||||
// all patterns used for regular expressions in SwiftLint are string literals which have
|
||||
// been confirmed to work, so it's ok to force-try here.
|
||||
// swiftlint:disable force_try
|
||||
// all patterns used for regular expressions in SwiftLint are string literals which have been
|
||||
// confirmed to work, so it's ok to force-try here.
|
||||
|
||||
// swiftlint:disable:next force_try
|
||||
return try! NSRegularExpression(pattern: pattern, options: [.AnchorsMatchLines])
|
||||
// swiftlint:enable force_try
|
||||
}
|
||||
|
||||
extension File {
|
||||
public func regions() -> [Region] {
|
||||
let contents = self.contents as NSString
|
||||
let commands = matchPattern("swiftlint:(enable|disable)\\ [^\\s]+",
|
||||
withSyntaxKinds: [.Comment]).flatMap { Command(string: contents, range: $0) }
|
||||
let commands = matchPattern("swiftlint:(enable|disable)(:previous|:this|:next)?\\ [^\\s]+",
|
||||
withSyntaxKinds: [.Comment]).flatMap { range in
|
||||
return Command(string: contents, range: range)
|
||||
}.flatMap { command in
|
||||
return command.expand()
|
||||
}
|
||||
let totalNumberOfLines = lines.count
|
||||
let numberOfCharactersInLastLine = lines.last?.content.characters.count
|
||||
var regions = [Region]()
|
||||
@@ -115,12 +119,12 @@ extension File {
|
||||
}
|
||||
|
||||
public func write(string: String) {
|
||||
guard let stringData = string.dataUsingEncoding(NSUTF8StringEncoding) else {
|
||||
fatalError("can't encode '\(string)' with UTF8")
|
||||
}
|
||||
guard let path = path else {
|
||||
fatalError("file needs a path to call write(_:)")
|
||||
}
|
||||
guard let stringData = string.dataUsingEncoding(NSUTF8StringEncoding) else {
|
||||
fatalError("can't encode '\(string)' with UTF8")
|
||||
}
|
||||
stringData.writeToFile(path, atomically: true)
|
||||
contents = string
|
||||
lines = contents.lines()
|
||||
|
||||
@@ -11,6 +11,19 @@ import Foundation
|
||||
public enum CommandAction: String {
|
||||
case Enable = "enable"
|
||||
case Disable = "disable"
|
||||
|
||||
private func inverse() -> CommandAction {
|
||||
switch self {
|
||||
case .Enable: return .Disable
|
||||
case .Disable: return .Enable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum CommandModifier: String {
|
||||
case Previous = "previous"
|
||||
case This = "this"
|
||||
case Next = "next"
|
||||
}
|
||||
|
||||
public struct Command {
|
||||
@@ -18,28 +31,71 @@ public struct Command {
|
||||
let ruleIdentifier: String
|
||||
let line: Int
|
||||
let character: Int
|
||||
let modifier: CommandModifier?
|
||||
|
||||
public init(action: CommandAction, ruleIdentifier: String, line: Int, character: Int) {
|
||||
public init(action: CommandAction, ruleIdentifier: String, line: Int = 0, character: Int = 0,
|
||||
modifier: CommandModifier? = nil) {
|
||||
self.action = action
|
||||
self.ruleIdentifier = ruleIdentifier
|
||||
self.line = line
|
||||
self.character = character
|
||||
self.modifier = modifier
|
||||
}
|
||||
|
||||
public init?(string: NSString, range: NSRange) {
|
||||
let scanner = NSScanner(string: string.substringWithRange(range))
|
||||
scanner.scanString("swiftlint:", intoString: nil)
|
||||
var optionalActionAndModifierNSString: NSString? = nil
|
||||
scanner.scanUpToString(" ", intoString: &optionalActionAndModifierNSString)
|
||||
guard let actionAndModifierString = optionalActionAndModifierNSString as String? else {
|
||||
return nil
|
||||
}
|
||||
let actionAndModifierScanner = NSScanner(string: actionAndModifierString)
|
||||
var actionNSString: NSString? = nil
|
||||
scanner.scanUpToString(" ", intoString: &actionNSString)
|
||||
actionAndModifierScanner.scanUpToString(":",
|
||||
intoString: &actionNSString)
|
||||
guard let actionString = actionNSString as String?,
|
||||
action = CommandAction(rawValue: actionString),
|
||||
lineAndCharacter = string.lineAndCharacterForCharacterOffset(NSMaxRange(range)) else {
|
||||
return nil
|
||||
}
|
||||
self.action = action
|
||||
let ruleStart = scanner.string.startIndex.advancedBy(scanner.scanLocation + 1)
|
||||
ruleIdentifier = scanner.string.substringFromIndex(ruleStart)
|
||||
ruleIdentifier = (scanner.string as NSString).substringFromIndex(scanner.scanLocation + 1)
|
||||
line = lineAndCharacter.line
|
||||
character = lineAndCharacter.character
|
||||
|
||||
let hasModifier = actionAndModifierScanner.scanString(":", intoString: nil)
|
||||
|
||||
// Modifier
|
||||
if hasModifier {
|
||||
let modifierString = (actionAndModifierScanner.string as NSString)
|
||||
.substringFromIndex(actionAndModifierScanner.scanLocation)
|
||||
modifier = CommandModifier(rawValue: modifierString)
|
||||
} else {
|
||||
modifier = nil
|
||||
}
|
||||
}
|
||||
|
||||
internal func expand() -> [Command] {
|
||||
guard let modifier = modifier else {
|
||||
return [self]
|
||||
}
|
||||
switch modifier {
|
||||
case .Previous:
|
||||
return [
|
||||
Command(action: action, ruleIdentifier: ruleIdentifier, line: line - 1),
|
||||
Command(action: action.inverse(), ruleIdentifier: ruleIdentifier, line: line)
|
||||
]
|
||||
case .This:
|
||||
return [
|
||||
Command(action: action, ruleIdentifier: ruleIdentifier, line: line),
|
||||
Command(action: action.inverse(), ruleIdentifier: ruleIdentifier, line: line + 1)
|
||||
]
|
||||
case .Next:
|
||||
return [
|
||||
Command(action: action, ruleIdentifier: ruleIdentifier, line: line + 1),
|
||||
Command(action: action.inverse(), ruleIdentifier: ruleIdentifier, line: line + 2)
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user