converted Command/Region to structs and made Location Comparable

This commit is contained in:
JP Simard
2015-08-29 21:45:55 -07:00
parent 61d46c6c29
commit 7d85fe3261
6 changed files with 123 additions and 56 deletions
+45
View File
@@ -0,0 +1,45 @@
//
// Command.swift
// SwiftLint
//
// Created by JP Simard on 8/29/15.
// Copyright © 2015 Realm. All rights reserved.
//
import Foundation
public enum CommandAction: String {
case Enable = "enable"
case Disable = "disable"
}
public struct Command {
let action: CommandAction
let ruleIdentifier: String
let line: Int
let character: Int
public init(action: CommandAction, ruleIdentifier: String, line: Int, character: Int) {
self.action = action
self.ruleIdentifier = ruleIdentifier
self.line = line
self.character = character
}
public init?(string: NSString, range: NSRange) {
let scanner = NSScanner(string: string.substringWithRange(range))
scanner.scanString("swiftlint:", intoString: nil)
var actionNSString: NSString? = nil
scanner.scanUpToString(" ", intoString: &actionNSString)
guard let actionString = actionNSString as String?,
action = CommandAction(rawValue: actionString),
lineAndCharacter = string.lineAndCharacterForByteOffset(NSMaxRange(range)) else {
return nil
}
self.action = action
let ruleStart = scanner.string.startIndex.advancedBy(scanner.scanLocation + 1)
ruleIdentifier = scanner.string.substringFromIndex(ruleStart)
line = lineAndCharacter.line
character = lineAndCharacter.character
}
}
+26 -33
View File
@@ -9,47 +9,40 @@
import SourceKittenFramework
import SwiftXPC
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)
internal typealias Line = (index: Int, content: String)
extension File {
public func regions() -> [Region] {
let nsStringContents = contents as NSString
let commands = matchPattern("swiftlint:(enable|disable)\\ .+",
withSyntaxKinds: [.Comment]).flatMap { range -> 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) {
let ruleLocation = scanner.scanLocation + 1
let ruleStart = scanner.string.startIndex.advancedBy(ruleLocation)
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, [])]
let commands = matchPattern("swiftlint:(enable|disable)\\ [^\\s]+",
withSyntaxKinds: [.Comment]).flatMap { Command(string: nsStringContents, range: $0) }
let lines = contents.lines()
let totalNumberOfLines = lines.count
let numberOfCharactersInLastLine = lines.last?.content.characters.count
let firstRegion = Region(start:
Location(file: path, line: 1, character: 0),
end: Location(file: path,
line: commands.first?.line ?? totalNumberOfLines,
character: commands.first?.character ?? numberOfCharactersInLastLine),
disabledRuleIdentifiers: [])
var regions = [firstRegion]
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)
switch command.action {
case .Disable: disabledRules.insert(command.ruleIdentifier)
case .Enable: disabledRules.remove(command.ruleIdentifier)
}
regions.append((command.2, nextCommand?.2 ?? totalNumberOfLines, Array(disabledRules)))
regions.append(
Region(
start: Location(file: path,
line: command.line,
character: command.character),
end: Location(file: path,
line: nextCommand?.line ?? totalNumberOfLines,
character: nextCommand?.character ?? numberOfCharactersInLastLine),
disabledRuleIdentifiers: disabledRules)
)
}
return regions
}
+2 -5
View File
@@ -19,15 +19,12 @@ public struct Linter {
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
$0.start <= styleViolation.location && $0.end >= styleViolation.location
}).first else {
return true
}
return !violationRegion.disabledRules.contains(rule.identifier)
return !violationRegion.disabledRuleIdentifiers.contains(rule.identifier)
}
}
}
+12 -10
View File
@@ -8,7 +8,7 @@
import SourceKittenFramework
public struct Location: CustomStringConvertible, Equatable {
public struct Location: CustomStringConvertible, Comparable {
public let file: String?
public let line: Int?
public let character: Int?
@@ -38,18 +38,20 @@ public struct Location: CustomStringConvertible, Equatable {
}
}
// MARK: Equatable
// MARK: Comparable
/**
Returns true if `lhs` Location is equal to `rhs` Location.
:param: lhs Location to compare to `rhs`.
:param: rhs Location to compare to `lhs`.
:returns: True if `lhs` Location is equal to `rhs` Location.
*/
public func == (lhs: Location, rhs: Location) -> Bool {
return lhs.file == rhs.file &&
lhs.line == rhs.line &&
lhs.character == rhs.character
}
public func < (lhs: Location, rhs: Location) -> Bool {
if lhs.file != rhs.file {
return lhs.file < rhs.file
}
if lhs.line != rhs.line {
return lhs.line < rhs.line
}
return lhs.character < rhs.character
}
+22
View File
@@ -0,0 +1,22 @@
//
// Region.swift
// SwiftLint
//
// Created by JP Simard on 8/29/15.
// Copyright © 2015 Realm. All rights reserved.
//
import Foundation
import SourceKittenFramework
public struct Region {
let start: Location
let end: Location
let disabledRuleIdentifiers: Set<String>
public init(start: Location, end: Location, disabledRuleIdentifiers: Set<String>) {
self.start = start
self.end = end
self.disabledRuleIdentifiers = disabledRuleIdentifiers
}
}
+16 -8
View File
@@ -21,6 +21,8 @@
E5A167C91B25A0B000CF2D03 /* OperatorFunctionWhitespaceRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5A167C81B25A0B000CF2D03 /* OperatorFunctionWhitespaceRule.swift */; };
E809EDA11B8A71DF00399043 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E809EDA01B8A71DF00399043 /* Configuration.swift */; };
E809EDA31B8A73FB00399043 /* ConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E809EDA21B8A73FB00399043 /* ConfigurationTests.swift */; };
E80E018D1B92C0F60078EB70 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = E80E018C1B92C0F60078EB70 /* Command.swift */; settings = {ASSET_TAGS = (); }; };
E80E018F1B92C1350078EB70 /* Region.swift in Sources */ = {isa = PBXBuildFile; fileRef = E80E018E1B92C1350078EB70 /* Region.swift */; settings = {ASSET_TAGS = (); }; };
E812249A1B04F85B001783D2 /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = E81224991B04F85B001783D2 /* TestHelpers.swift */; };
E812249C1B04FADC001783D2 /* Linter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E812249B1B04FADC001783D2 /* Linter.swift */; };
E832F10B1B17E2F5003F265F /* NSFileManager+SwiftLint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E832F10A1B17E2F5003F265F /* NSFileManager+SwiftLint.swift */; };
@@ -151,6 +153,8 @@
E5A167C81B25A0B000CF2D03 /* OperatorFunctionWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorFunctionWhitespaceRule.swift; sourceTree = "<group>"; };
E809EDA01B8A71DF00399043 /* Configuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
E809EDA21B8A73FB00399043 /* ConfigurationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurationTests.swift; sourceTree = "<group>"; };
E80E018C1B92C0F60078EB70 /* Command.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = "<group>"; };
E80E018E1B92C1350078EB70 /* Region.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Region.swift; sourceTree = "<group>"; };
E81224991B04F85B001783D2 /* TestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestHelpers.swift; sourceTree = "<group>"; };
E812249B1B04FADC001783D2 /* Linter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Linter.swift; sourceTree = "<group>"; };
E832F10A1B17E2F5003F265F /* NSFileManager+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFileManager+SwiftLint.swift"; sourceTree = "<group>"; };
@@ -350,12 +354,14 @@
isa = PBXGroup;
children = (
E88DEA8B1B0999A000A66CB0 /* ASTRule.swift */,
E80E018C1B92C0F60078EB70 /* Command.swift */,
E809EDA01B8A71DF00399043 /* Configuration.swift */,
24E17F701B1481FF008195BE /* File+Cache.swift */,
E88DEA741B09852000A66CB0 /* File+SwiftLint.swift */,
E812249B1B04FADC001783D2 /* Linter.swift */,
E88DEA6E1B09843F00A66CB0 /* Location.swift */,
E832F10A1B17E2F5003F265F /* NSFileManager+SwiftLint.swift */,
E80E018E1B92C1350078EB70 /* Region.swift */,
E88DEA761B098D0C00A66CB0 /* Rule.swift */,
83D71E261B131EB5000395DE /* RuleExample.swift */,
E88DEA781B098D4400A66CB0 /* RuleParameter.swift */,
@@ -594,6 +600,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E80E018D1B92C0F60078EB70 /* Command.swift in Sources */,
83D71E281B131ECE000395DE /* RuleExample.swift in Sources */,
E812249C1B04FADC001783D2 /* Linter.swift in Sources */,
E88DEA861B0991BF00A66CB0 /* TrailingWhitespaceRule.swift in Sources */,
@@ -604,6 +611,7 @@
E88DEA731B0984C400A66CB0 /* String+SwiftLint.swift in Sources */,
24E17F721B14BB3F008195BE /* File+Cache.swift in Sources */,
E88DEA6D1B09842200A66CB0 /* StyleViolationType.swift in Sources */,
E80E018F1B92C1350078EB70 /* Region.swift in Sources */,
E88DEA941B099C0900A66CB0 /* VariableNameRule.swift in Sources */,
E88DEA8A1B0992B300A66CB0 /* FileLengthRule.swift in Sources */,
E88DEA751B09852000A66CB0 /* File+SwiftLint.swift in Sources */,
@@ -704,7 +712,7 @@
"$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib",
);
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Source/SwiftLintFramework/Info.plist";
INFOPLIST_FILE = Source/SwiftLintFramework/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks $(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
@@ -736,7 +744,7 @@
"$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib",
);
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Source/SwiftLintFramework/Info.plist";
INFOPLIST_FILE = Source/SwiftLintFramework/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks $(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
@@ -806,7 +814,7 @@
"$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib",
);
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Source/SwiftLintFramework/Info.plist";
INFOPLIST_FILE = Source/SwiftLintFramework/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks $(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
@@ -862,7 +870,7 @@
"$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib",
);
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Source/SwiftLintFramework/Info.plist";
INFOPLIST_FILE = Source/SwiftLintFramework/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks $(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
@@ -899,7 +907,7 @@
baseConfigurationReference = D0D1213419E878CC005E4BAA /* Mac-Application.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = "Source/swiftlint/Info.plist";
INFOPLIST_FILE = Source/swiftlint/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/. @executable_path/../Frameworks @executable_path/SwiftLintFramework.framework/Versions/Current/Frameworks @executable_path/SwiftLintFramework.framework/Versions/Current/Frameworks/SourceKittenFramework.framework/Versions/Current/Frameworks /Library/Frameworks /Library/Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks /Library/Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks/SourceKittenFramework.framework/Versions/Current/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -911,7 +919,7 @@
baseConfigurationReference = D0D1213419E878CC005E4BAA /* Mac-Application.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = "Source/swiftlint/Info.plist";
INFOPLIST_FILE = Source/swiftlint/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/. @executable_path/../Frameworks @executable_path/SwiftLintFramework.framework/Versions/Current/Frameworks @executable_path/SwiftLintFramework.framework/Versions/Current/Frameworks/SourceKittenFramework.framework/Versions/Current/Frameworks /Library/Frameworks /Library/Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks /Library/Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks/SourceKittenFramework.framework/Versions/Current/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -923,7 +931,7 @@
baseConfigurationReference = D0D1213419E878CC005E4BAA /* Mac-Application.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = "Source/swiftlint/Info.plist";
INFOPLIST_FILE = Source/swiftlint/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/. @executable_path/../Frameworks @executable_path/SwiftLintFramework.framework/Versions/Current/Frameworks @executable_path/SwiftLintFramework.framework/Versions/Current/Frameworks/SourceKittenFramework.framework/Versions/Current/Frameworks /Library/Frameworks /Library/Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks /Library/Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks/SourceKittenFramework.framework/Versions/Current/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -935,7 +943,7 @@
baseConfigurationReference = D0D1213419E878CC005E4BAA /* Mac-Application.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = "Source/swiftlint/Info.plist";
INFOPLIST_FILE = Source/swiftlint/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/. @executable_path/../Frameworks @executable_path/SwiftLintFramework.framework/Versions/Current/Frameworks @executable_path/SwiftLintFramework.framework/Versions/Current/Frameworks/SourceKittenFramework.framework/Versions/Current/Frameworks /Library/Frameworks /Library/Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks /Library/Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks/SourceKittenFramework.framework/Versions/Current/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";