diff --git a/.gitignore b/.gitignore
index 2b9c66988..777cb057b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,12 @@
# Xcode
+#
+# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
+## Build generated
build/
+DerivedData
+
+## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
@@ -10,11 +16,32 @@ build/
*.perspectivev3
!default.perspectivev3
xcuserdata
+
+## Other
*.xccheckout
*.moved-aside
-DerivedData
+*.xcuserstate
+*.xcscmblueprint
+
+## Obj-C/Swift specific
*.hmap
*.ipa
-*.xcuserstate
+
+# CocoaPods
+#
+# We recommend against adding the Pods directory to your .gitignore. However
+# you should judge for yourself, the pros and cons are mentioned at:
+# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
+#
+#Pods/
+
+# Carthage
+#
+# Add this line if you want to avoid checking in source code from Carthage dependencies.
+# Carthage/Checkouts
+
+Carthage/Build
+
+# SwiftLint
SwiftLint.pkg
diff --git a/.gitmodules b/.gitmodules
index 32f887e87..5afa9b035 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -16,3 +16,9 @@
[submodule "Carthage/Checkouts/SourceKitten"]
path = Carthage/Checkouts/SourceKitten
url = https://github.com/jpsim/SourceKitten.git
+[submodule "Carthage/Checkouts/Result"]
+ path = Carthage/Checkouts/Result
+ url = https://github.com/antitypical/Result.git
+[submodule "Carthage/Checkouts/YamlSwift"]
+ path = Carthage/Checkouts/YamlSwift
+ url = https://github.com/behrang/YamlSwift.git
diff --git a/.swiftlint.yml b/.swiftlint.yml
new file mode 100644
index 000000000..4e8698361
--- /dev/null
+++ b/.swiftlint.yml
@@ -0,0 +1,2 @@
+included:
+ - Source
diff --git a/.travis.yml b/.travis.yml
index 065327299..4be693b54 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,5 @@
language: objective-c
-osx_image: beta-xcode6.3
+osx_image: xcode7
git:
submodules: false
branches:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6dabda01b..28a633632 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,24 @@
+## Master
+
+##### Breaking
+
+* SwiftLint now exclusively supports Swift 2.0.
+ [JP Simard](https://github.com/jpsim)
+ [#77](https://github.com/realm/SwiftLint/issues/77)
+
+##### Enhancements
+
+* Configure SwiftLint via a YAML file:
+ Supports `disabled_rules`, `included` and `excluded`.
+ Pass a configuration file path to `--config`, defaults to `.swiftlint.yml`.
+ [JP Simard](https://github.com/jpsim)
+ [#3](https://github.com/realm/SwiftLint/issues/3)
+
+##### Bug Fixes
+
+* None.
+
+
## 0.1.2: FabricSoftenerRule
##### Breaking
diff --git a/Cartfile b/Cartfile
index 66306c6c2..346878590 100644
--- a/Cartfile
+++ b/Cartfile
@@ -1 +1 @@
-github "jpsim/SourceKitten" ~> 0.4
+github "jpsim/SourceKitten" "master"
diff --git a/Cartfile.private b/Cartfile.private
index a99553424..e5831ffc3 100644
--- a/Cartfile.private
+++ b/Cartfile.private
@@ -1,2 +1,3 @@
-github "Carthage/Commandant" ~> 0.5
+github "Carthage/Commandant" "swift-2.0"
github "jspahrsummers/xcconfigs" >= 0.8
+github "behrang/YamlSwift" "master"
diff --git a/Cartfile.resolved b/Cartfile.resolved
index 8ed4b5a5a..1efd11e1f 100644
--- a/Cartfile.resolved
+++ b/Cartfile.resolved
@@ -1,6 +1,7 @@
-github "LlamaKit/LlamaKit" "v0.6.0"
-github "drmohundro/SWXMLHash" "1.0.0"
-github "jpsim/SwiftXPC" "1.0.0"
-github "jspahrsummers/xcconfigs" "0.8"
-github "Carthage/Commandant" "0.5"
-github "jpsim/SourceKitten" "0.4.5"
+github "antitypical/Result" "0.6-beta.1"
+github "drmohundro/SWXMLHash" "050154bfc56032f04fcca37464693a17f897200a"
+github "jpsim/SwiftXPC" "d32e70f1b35cfa833be85fd40e70401f4190f5b0"
+github "behrang/YamlSwift" "243ebbafb8ed60f57f9d5a7c2a4ff8099824644a"
+github "jspahrsummers/xcconfigs" "0.8.1"
+github "Carthage/Commandant" "40f503c33121431dc098adb7c44d9496e3a1de2f"
+github "jpsim/SourceKitten" "ace729472170a4ec2996b8f921fc66784e5ef4fe"
diff --git a/Carthage/Checkouts/Commandant b/Carthage/Checkouts/Commandant
index 3866cadd4..40f503c33 160000
--- a/Carthage/Checkouts/Commandant
+++ b/Carthage/Checkouts/Commandant
@@ -1 +1 @@
-Subproject commit 3866cadd431b1c3ba8091383b80ec023beb1897f
+Subproject commit 40f503c33121431dc098adb7c44d9496e3a1de2f
diff --git a/Carthage/Checkouts/LlamaKit b/Carthage/Checkouts/LlamaKit
deleted file mode 160000
index e28d7f6e8..000000000
--- a/Carthage/Checkouts/LlamaKit
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit e28d7f6e82fbd5dcd5388b36e2acf4eedb44b4e8
diff --git a/Carthage/Checkouts/Result b/Carthage/Checkouts/Result
new file mode 160000
index 000000000..18a10d680
--- /dev/null
+++ b/Carthage/Checkouts/Result
@@ -0,0 +1 @@
+Subproject commit 18a10d680af395d93b47ff4a3d8b0af3b8cad094
diff --git a/Carthage/Checkouts/SWXMLHash b/Carthage/Checkouts/SWXMLHash
index 3f64d009c..050154bfc 160000
--- a/Carthage/Checkouts/SWXMLHash
+++ b/Carthage/Checkouts/SWXMLHash
@@ -1 +1 @@
-Subproject commit 3f64d009ca1e2b737bf93d22bcaa837d3be1d90c
+Subproject commit 050154bfc56032f04fcca37464693a17f897200a
diff --git a/Carthage/Checkouts/SourceKitten b/Carthage/Checkouts/SourceKitten
index a9b100ab0..ace729472 160000
--- a/Carthage/Checkouts/SourceKitten
+++ b/Carthage/Checkouts/SourceKitten
@@ -1 +1 @@
-Subproject commit a9b100ab0803d79ef42c775895a40726d3128f07
+Subproject commit ace729472170a4ec2996b8f921fc66784e5ef4fe
diff --git a/Carthage/Checkouts/SwiftXPC b/Carthage/Checkouts/SwiftXPC
index bfc256492..d32e70f1b 160000
--- a/Carthage/Checkouts/SwiftXPC
+++ b/Carthage/Checkouts/SwiftXPC
@@ -1 +1 @@
-Subproject commit bfc256492840ff6e8d05b851cb57af38d83469bf
+Subproject commit d32e70f1b35cfa833be85fd40e70401f4190f5b0
diff --git a/Carthage/Checkouts/YamlSwift b/Carthage/Checkouts/YamlSwift
new file mode 160000
index 000000000..ed060df01
--- /dev/null
+++ b/Carthage/Checkouts/YamlSwift
@@ -0,0 +1 @@
+Subproject commit ed060df018b5693a045f207088b95ce15f433065
diff --git a/Carthage/Checkouts/xcconfigs b/Carthage/Checkouts/xcconfigs
index 813127f87..99624a6af 160000
--- a/Carthage/Checkouts/xcconfigs
+++ b/Carthage/Checkouts/xcconfigs
@@ -1 +1 @@
-Subproject commit 813127f87f66fa14a7da03d3fa8410c02d2075d6
+Subproject commit 99624a6af366c015b678a1135e4c558776a59be6
diff --git a/README.md b/README.md
index 2f347bc4d..307f0e5b4 100644
--- a/README.md
+++ b/README.md
@@ -18,9 +18,12 @@ Using [Homebrew](http://brew.sh/)
brew install swiftlint
```
-You can also install SwiftLint by downloading `SwiftLint.pkg` from the [latest GitHub release](https://github.com/realm/SwiftLint/releases/latest) and running it.
+You can also install SwiftLint by downloading `SwiftLint.pkg` from the
+[latest GitHub release](https://github.com/realm/SwiftLint/releases/latest) and
+running it.
-You can also build from source by cloning this project and running `make install`.
+You can also build from source by cloning this project and running
+`make install` (Xcode 7 Beta 6 required).
## Usage
@@ -36,7 +39,8 @@ as its contents. Like this:
### Atom
To integrate SwiftLint with [Atom](https://atom.io/) install the
-[`linter-swiftlint`](https://atom.io/packages/linter-swiftlint) package from APM.
+[`linter-swiftlint`](https://atom.io/packages/linter-swiftlint) package from
+APM.
### Command Line
@@ -62,8 +66,23 @@ encouraged.
The rules that *are* currently implemented are mostly there as a starting point
and are subject to change.
-See the [Source/SwiftLintFramework/Rules](Source/SwiftLintFramework/Rules) directory to see the currently
-implemented rules.
+See the [Source/SwiftLintFramework/Rules](Source/SwiftLintFramework/Rules)
+directory to see the currently implemented rules.
+
+### Configuration
+
+Configure SwiftLint by adding a `.swiftlint.yml` file from the directory you'll
+run SwiftLint from. The following parameters can be configured:
+
+```yaml
+disabled_rules: # rule identifiers to exclude from running
+ - todo
+included: # paths to include during linting. `--path` is ignored if present. takes precendence over `excluded`.
+ - Source
+excluded: # paths to ignore during linting. overridden by `included`.
+ - Carthage
+ - Pods
+```
## License
diff --git a/Source/SwiftLintFramework/Configuration.swift b/Source/SwiftLintFramework/Configuration.swift
new file mode 100644
index 000000000..3804bd4d7
--- /dev/null
+++ b/Source/SwiftLintFramework/Configuration.swift
@@ -0,0 +1,103 @@
+//
+// Configuration.swift
+// SwiftLint
+//
+// Created by JP Simard on 2015-08-23.
+// Copyright (c) 2015 Realm. All rights reserved.
+//
+
+import Yaml
+
+extension Yaml {
+ var arrayOfStrings: [Swift.String]? {
+ return array?.flatMap { $0.string }
+ }
+}
+
+public struct Configuration {
+ public let disabledRules: [String] // disabled_rules
+ public let included: [String] // included
+ public let excluded: [String] // excluded
+
+ public var rules: [Rule] {
+ return allRules.filter { !disabledRules.contains($0.identifier) }
+ }
+
+ public init?(disabledRules: [String] = [], included: [String] = [], excluded: [String] = []) {
+ self.disabledRules = disabledRules
+ self.included = included
+ self.excluded = excluded
+
+ // Validate that all rule identifiers map to a defined rule
+
+ let validRuleIdentifiers = allRules.map { $0.identifier }
+
+ let ruleSet = Set(disabledRules)
+ let invalidRules = ruleSet.filter({ !validRuleIdentifiers.contains($0) })
+ if invalidRules.count > 0 {
+ for invalidRule in invalidRules {
+ fputs("config error: '\(invalidRule)' is not a valid rule identifier\n", stderr)
+ let listOfValidRuleIdentifiers = validRuleIdentifiers.joinWithSeparator("\n")
+ fputs("Valid rule identifiers:\n\(listOfValidRuleIdentifiers)\n", stderr)
+ }
+ return nil
+ }
+
+ // Validate that rule identifiers aren't listed multiple times
+
+ if ruleSet.count != disabledRules.count {
+ let duplicateRules = disabledRules.reduce([String: Int]()) { (var accu, element) in
+ accu[element] = accu[element]?.successor() ?? 1
+ return accu
+ }.filter {
+ $0.1 > 1
+ }
+ for duplicateRule in duplicateRules {
+ fputs("config error: '\(duplicateRule.0)' is listed \(duplicateRule.1) times\n",
+ stderr)
+ }
+ return nil
+ }
+ }
+
+ public init?(yaml: String) {
+ guard let yamlConfig = Yaml.load(yaml).value else {
+ return nil
+ }
+ self.init(
+ disabledRules: yamlConfig["disabled_rules"].arrayOfStrings ?? [],
+ included: yamlConfig["included"].arrayOfStrings ?? [],
+ excluded: yamlConfig["excluded"].arrayOfStrings ?? []
+ )
+ }
+
+ public init(path: String = ".swiftlint.yml", optional: Bool = true) {
+ let fullPath = (path as NSString).absolutePathRepresentation()
+ let failIfRequired = {
+ if !optional { fatalError("Could not read configuration file at path '\(fullPath)'") }
+ }
+ if path.isEmpty {
+ failIfRequired()
+ self.init()!
+ } else {
+ if !NSFileManager.defaultManager().fileExistsAtPath(fullPath) {
+ failIfRequired()
+ self.init()!
+ return
+ }
+ do {
+ let yamlContents = try NSString(contentsOfFile: fullPath,
+ encoding: NSUTF8StringEncoding) as String
+ if let _ = Configuration(yaml: yamlContents) {
+ print("Loading configuration from '\(path)'")
+ self.init(yaml: yamlContents)!
+ } else {
+ self.init()!
+ }
+ } catch {
+ failIfRequired()
+ self.init()!
+ }
+ }
+ }
+}
diff --git a/Source/SwiftLintFramework/File+SwiftLint.swift b/Source/SwiftLintFramework/File+SwiftLint.swift
index e3571877e..59dd517fd 100644
--- a/Source/SwiftLintFramework/File+SwiftLint.swift
+++ b/Source/SwiftLintFramework/File+SwiftLint.swift
@@ -16,26 +16,23 @@ extension File {
withSyntaxKinds syntaxKinds: [SyntaxKind]) -> [NSRange] {
return matchPattern(pattern).filter { _, kindsInRange in
return kindsInRange.count == syntaxKinds.count &&
- filter(zip(kindsInRange, syntaxKinds), { $0.0 != $0.1 }).count == 0
+ zip(kindsInRange, syntaxKinds).filter({ $0.0 != $0.1 }).count == 0
}.map { $0.0 }
}
public func matchPattern(pattern: String) -> [(NSRange, [SyntaxKind])] {
- return flatMap(NSRegularExpression(pattern: pattern, options: nil, error: nil)) { regex in
- let range = NSRange(location: 0, length: count(contents.utf16))
- let syntax = syntaxMap
- let matches = regex.matchesInString(contents, options: nil, range: range)
- return map(matches as? [NSTextCheckingResult]) { matches in
- return matches.map { match in
- let tokensInRange = syntax.tokens.filter {
- NSLocationInRange($0.offset, match.range)
- }
- let kindsInRange = compact(map(tokensInRange) {
- SyntaxKind(rawValue: $0.type)
- })
- return (match.range, kindsInRange)
- }
+ let regex = try! NSRegularExpression(pattern: pattern, options: [])
+ let range = NSRange(location: 0, length: contents.utf16.count)
+ let syntax = syntaxMap
+ let matches = regex.matchesInString(contents, options: [], range: range)
+ return matches.map { match in
+ let tokensInRange = syntax.tokens.filter {
+ NSLocationInRange($0.offset, match.range)
}
- } ?? []
+ let kindsInRange = tokensInRange.flatMap {
+ SyntaxKind(rawValue: $0.type)
+ }
+ return (match.range, kindsInRange)
+ }
}
}
diff --git a/Source/SwiftLintFramework/Info.plist b/Source/SwiftLintFramework/Info.plist
index 8c798dbec..186eccf12 100644
--- a/Source/SwiftLintFramework/Info.plist
+++ b/Source/SwiftLintFramework/Info.plist
@@ -7,7 +7,7 @@
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
- io.realm.$(PRODUCT_NAME:rfc1034identifier)
+ $(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
diff --git a/Source/SwiftLintFramework/Linter.swift b/Source/SwiftLintFramework/Linter.swift
index e04e60c53..fcafcc94e 100644
--- a/Source/SwiftLintFramework/Linter.swift
+++ b/Source/SwiftLintFramework/Linter.swift
@@ -13,31 +13,14 @@ import SourceKittenFramework
public struct Linter {
private let file: File
- private let rules: [Rule] = [
- LineLengthRule(),
- LeadingWhitespaceRule(),
- TrailingWhitespaceRule(),
- ReturnArrowWhitespaceRule(),
- TrailingNewlineRule(),
- OperatorFunctionWhitespaceRule(),
- ForceCastRule(),
- FileLengthRule(),
- TodoRule(),
- ColonRule(),
- TypeNameRule(),
- VariableNameRule(),
- TypeBodyLengthRule(),
- FunctionBodyLengthRule(),
- NestingRule(),
- ControlStatementRule()
- ]
+ private let rules: [Rule]
public var styleViolations: [StyleViolation] {
- return rules.flatMap { $0.validateFile(file) }
+ return rules.flatMap { $0.validateFile(self.file) }
}
public var ruleExamples: [RuleExample] {
- return compact(rules.map { $0.example })
+ return rules.flatMap { $0.example }
}
/**
@@ -45,7 +28,8 @@ public struct Linter {
:param: file File to lint.
*/
- public init(file: File) {
+ public init(file: File, configuration: Configuration = Configuration()!) {
self.file = file
+ rules = configuration.rules
}
}
diff --git a/Source/SwiftLintFramework/Location.swift b/Source/SwiftLintFramework/Location.swift
index 9cb786dce..5c773d1ab 100644
--- a/Source/SwiftLintFramework/Location.swift
+++ b/Source/SwiftLintFramework/Location.swift
@@ -8,7 +8,7 @@
import SourceKittenFramework
-public struct Location: Printable, Equatable {
+public struct Location: CustomStringConvertible, Equatable {
public let file: String?
public let line: Int?
public let character: Int?
@@ -16,8 +16,8 @@ public struct Location: Printable, Equatable {
// Xcode likes warnings and errors in the following format:
// {full_path_to_file}{:line}{:character}: {error,warning}: {content}
return (file ?? "") +
- (map(line, { ":\($0)" }) ?? "") +
- (map(character, { ":\($0)" }) ?? "")
+ (line.map({ ":\($0)" }) ?? "") +
+ (character.map({ ":\($0)" }) ?? "")
}
public init(file: String?, line: Int? = nil, character: Int? = nil) {
diff --git a/Source/SwiftLintFramework/NSFileManager+SwiftLint.swift b/Source/SwiftLintFramework/NSFileManager+SwiftLint.swift
index 44a3944da..cf5f656af 100644
--- a/Source/SwiftLintFramework/NSFileManager+SwiftLint.swift
+++ b/Source/SwiftLintFramework/NSFileManager+SwiftLint.swift
@@ -7,14 +7,11 @@
//
import Foundation
-import SourceKittenFramework
extension NSFileManager {
- public func allFilesRecursively(# directory: String) -> [String] {
- let relativeFiles = (contentsOfDirectoryAtPath(directory, error: nil) as? [String] ?? []) +
- (subpathsOfDirectoryAtPath(directory, error: nil) as? [String] ?? [])
- return relativeFiles.map {
- directory.stringByAppendingPathComponent($0)
- }
+ public func allFilesRecursively(directory directory: String) -> [String] {
+ let relativeFiles = (try! contentsOfDirectoryAtPath(directory)) +
+ (try! subpathsOfDirectoryAtPath(directory))
+ return relativeFiles.map((directory as NSString).stringByAppendingPathComponent)
}
}
diff --git a/Source/SwiftLintFramework/Rule.swift b/Source/SwiftLintFramework/Rule.swift
index 5f5534e14..8a73f30ec 100644
--- a/Source/SwiftLintFramework/Rule.swift
+++ b/Source/SwiftLintFramework/Rule.swift
@@ -18,3 +18,22 @@ public protocol ParameterizedRule: Rule {
typealias ParameterType
var parameters: [RuleParameter] { get }
}
+
+public let allRules: [Rule] = [
+ LineLengthRule(),
+ LeadingWhitespaceRule(),
+ TrailingWhitespaceRule(),
+ ReturnArrowWhitespaceRule(),
+ TrailingNewlineRule(),
+ OperatorFunctionWhitespaceRule(),
+ ForceCastRule(),
+ FileLengthRule(),
+ TodoRule(),
+ ColonRule(),
+ TypeNameRule(),
+ VariableNameRule(),
+ TypeBodyLengthRule(),
+ FunctionBodyLengthRule(),
+ NestingRule(),
+ ControlStatementRule()
+]
diff --git a/Source/SwiftLintFramework/Rules/ControlStatementRule.swift b/Source/SwiftLintFramework/Rules/ControlStatementRule.swift
index 8c78c6fb7..7218c3f59 100644
--- a/Source/SwiftLintFramework/Rules/ControlStatementRule.swift
+++ b/Source/SwiftLintFramework/Rules/ControlStatementRule.swift
@@ -14,9 +14,9 @@ public struct ControlStatementRule: Rule {
public let identifier = "control_statement"
public func validateFile(file: File) -> [StyleViolation] {
- return ["if", "for", "switch", "while"].flatMap { statementKind in
+ return ["if", "for", "switch", "while"].flatMap { statementKind -> [StyleViolation] in
let pattern = "\(statementKind)\\s*\\([^,]*\\)\\s*\\{"
- return compact(file.matchPattern(pattern).map { match, syntaxKinds in
+ return file.matchPattern(pattern).flatMap { match, syntaxKinds in
if syntaxKinds.first != .Keyword {
return nil
}
@@ -25,7 +25,7 @@ public struct ControlStatementRule: Rule {
severity: .Low,
reason: "\(statementKind) statements shouldn't wrap their conditionals in " +
"parentheses.")
- })
+ }
}
}
diff --git a/Source/SwiftLintFramework/Rules/FileLengthRule.swift b/Source/SwiftLintFramework/Rules/FileLengthRule.swift
index 6b6088711..d7099a380 100644
--- a/Source/SwiftLintFramework/Rules/FileLengthRule.swift
+++ b/Source/SwiftLintFramework/Rules/FileLengthRule.swift
@@ -23,7 +23,7 @@ public struct FileLengthRule: ParameterizedRule {
public func validateFile(file: File) -> [StyleViolation] {
let lines = file.contents.lines()
- for parameter in reverse(parameters) {
+ for parameter in parameters.reverse() {
if lines.count > parameter.value {
return [StyleViolation(type: .Length,
location: Location(file: file.path, line: lines.count),
diff --git a/Source/SwiftLintFramework/Rules/FunctionBodyLengthRule.swift b/Source/SwiftLintFramework/Rules/FunctionBodyLengthRule.swift
index 46e0991c3..8fb60d37d 100644
--- a/Source/SwiftLintFramework/Rules/FunctionBodyLengthRule.swift
+++ b/Source/SwiftLintFramework/Rules/FunctionBodyLengthRule.swift
@@ -27,13 +27,16 @@ public struct FunctionBodyLengthRule: ASTRule, ParameterizedRule {
}
public func validateFile(file: File, dictionary: XPCDictionary) -> [StyleViolation] {
- return (dictionary["key.substructure"] as? XPCArray ?? []).flatMap { subItem in
+ let substructure = dictionary["key.substructure"] as? XPCArray ?? []
+ return substructure.flatMap { subItem -> [StyleViolation] in
var violations = [StyleViolation]()
if let subDict = subItem as? XPCDictionary,
let kindString = subDict["key.kind"] as? String,
- let kind = flatMap(kindString, { SwiftDeclarationKind(rawValue: $0) }) {
- violations.extend(validateFile(file, dictionary: subDict))
- violations.extend(validateFile(file, kind: kind, dictionary: subDict))
+ let kind = SwiftDeclarationKind(rawValue: kindString) {
+ violations.appendContentsOf(
+ self.validateFile(file, dictionary: subDict) +
+ self.validateFile(file, kind: kind, dictionary: subDict)
+ )
}
return violations
}
@@ -58,16 +61,16 @@ public struct FunctionBodyLengthRule: ASTRule, ParameterizedRule {
.FunctionOperator,
.FunctionSubscript
]
- if !contains(functionKinds, kind) {
+ if !functionKinds.contains(kind) {
return []
}
- if let offset = flatMap(dictionary["key.offset"] as? Int64, { Int($0) }),
- let bodyOffset = flatMap(dictionary["key.bodyoffset"] as? Int64, { Int($0) }),
- let bodyLength = flatMap(dictionary["key.bodylength"] as? Int64, { Int($0) }) {
+ if let offset = (dictionary["key.offset"] as? Int64).flatMap({ Int($0) }),
+ let bodyOffset = (dictionary["key.bodyoffset"] as? Int64).flatMap({ Int($0) }),
+ let bodyLength = (dictionary["key.bodylength"] as? Int64).flatMap({ Int($0) }) {
let location = Location(file: file, offset: offset)
let startLine = file.contents.lineAndCharacterForByteOffset(bodyOffset)
let endLine = file.contents.lineAndCharacterForByteOffset(bodyOffset + bodyLength)
- for parameter in reverse(parameters) {
+ for parameter in parameters.reverse() {
if let startLine = startLine?.line, let endLine = endLine?.line
where endLine - startLine > parameter.value {
return [StyleViolation(type: .Length,
diff --git a/Source/SwiftLintFramework/Rules/LineLengthRule.swift b/Source/SwiftLintFramework/Rules/LineLengthRule.swift
index fb0b9ef6e..26549e76d 100644
--- a/Source/SwiftLintFramework/Rules/LineLengthRule.swift
+++ b/Source/SwiftLintFramework/Rules/LineLengthRule.swift
@@ -22,18 +22,18 @@ public struct LineLengthRule: ParameterizedRule {
]
public func validateFile(file: File) -> [StyleViolation] {
- return compact(file.contents.lines().map { line in
- for parameter in reverse(self.parameters) {
- if count(line.content) > parameter.value {
+ return file.contents.lines().flatMap { line in
+ for parameter in parameters.reverse() {
+ if line.content.characters.count > parameter.value {
return StyleViolation(type: .Length,
location: Location(file: file.path, line: line.index),
severity: parameter.severity,
reason: "Line should be 100 characters or less: currently " +
- "\(count(line.content)) characters")
+ "\(line.content.characters.count) characters")
}
}
return nil
- })
+ }
}
public let example = RuleExample(
diff --git a/Source/SwiftLintFramework/Rules/NestingRule.swift b/Source/SwiftLintFramework/Rules/NestingRule.swift
index ea792e135..04c759530 100644
--- a/Source/SwiftLintFramework/Rules/NestingRule.swift
+++ b/Source/SwiftLintFramework/Rules/NestingRule.swift
@@ -19,13 +19,16 @@ public struct NestingRule: ASTRule {
}
public func validateFile(file: File, dictionary: XPCDictionary) -> [StyleViolation] {
- return (dictionary["key.substructure"] as? XPCArray ?? []).flatMap { subItem in
+ let substructure = dictionary["key.substructure"] as? XPCArray ?? []
+ return substructure.flatMap { subItem -> [StyleViolation] in
var violations = [StyleViolation]()
if let subDict = subItem as? XPCDictionary,
let kindString = subDict["key.kind"] as? String,
- let kind = flatMap(kindString, { SwiftDeclarationKind(rawValue: $0) }) {
- violations.extend(validateFile(file, dictionary: subDict))
- violations.extend(validateFile(file, kind: kind, dictionary: subDict))
+ let kind = SwiftDeclarationKind(rawValue: kindString) {
+ violations.appendContentsOf(
+ self.validateFile(file, dictionary: subDict) +
+ self.validateFile(file, kind: kind, dictionary: subDict)
+ )
}
return violations
}
@@ -34,7 +37,7 @@ public struct NestingRule: ASTRule {
public func validateFile(file: File,
kind: SwiftDeclarationKind,
dictionary: XPCDictionary) -> [StyleViolation] {
- return self.validateFile(file, kind: kind, dictionary: dictionary, level: 0)
+ return validateFile(file, kind: kind, dictionary: dictionary, level: 0)
}
func validateFile(file: File,
@@ -47,10 +50,15 @@ public struct NestingRule: ASTRule {
.Struct,
.Typealias,
.Enum,
- .Enumelement
+ .Enumcase
]
- if let offset = flatMap(dictionary["key.offset"] as? Int64, { Int($0) }) {
- if level > 1 && contains(typeKinds, kind) {
+ if let offset = (dictionary["key.offset"] as? Int64).flatMap({ Int($0) }) {
+ if level > 1 && typeKinds.contains(kind) {
+ violations.append(StyleViolation(type: .Nesting,
+ location: Location(file: file, offset: offset),
+ reason: "Types should be nested at most 1 level deep"))
+ } else if level > 2 && kind == .Enumelement {
+ // Enum elements are implicitly wrapped in an .Enumcase
violations.append(StyleViolation(type: .Nesting,
location: Location(file: file, offset: offset),
reason: "Types should be nested at most 1 level deep"))
@@ -61,18 +69,18 @@ public struct NestingRule: ASTRule {
}
}
let substructure = dictionary["key.substructure"] as? XPCArray ?? []
- violations.extend(compact(substructure.map { subItem in
+ violations.appendContentsOf(substructure.flatMap { subItem in
let subDict = subItem as? XPCDictionary
let kindString = subDict?["key.kind"] as? String
- let kind = flatMap(kindString) { kindString in
+ let kind = kindString.flatMap { kindString in
return SwiftDeclarationKind(rawValue: kindString)
}
if let kind = kind, subDict = subDict {
return (kind, subDict)
}
return nil
- } as [(SwiftDeclarationKind, XPCDictionary)?]).flatMap { (kind, dict) in
- return validateFile(file, kind: kind, dictionary: dict, level: level + 1)
+ }.flatMap { (kind, dict) -> [StyleViolation] in
+ return self.validateFile(file, kind: kind, dictionary: dict, level: level + 1)
})
return violations
}
diff --git a/Source/SwiftLintFramework/Rules/OperatorFunctionWhitespaceRule.swift b/Source/SwiftLintFramework/Rules/OperatorFunctionWhitespaceRule.swift
index 1e87f166c..95aae2bb7 100644
--- a/Source/SwiftLintFramework/Rules/OperatorFunctionWhitespaceRule.swift
+++ b/Source/SwiftLintFramework/Rules/OperatorFunctionWhitespaceRule.swift
@@ -17,15 +17,19 @@ public struct OperatorFunctionWhitespaceRule: Rule {
let operators = ["/", "=", "-", "+", "!", "*", "|", "^", "~", "?", "."].map({"\\\($0)"}) +
["%", "<", ">", "&"]
let zeroOrManySpaces = "(\\s{0}|\\s{2,})"
- let pattern1 = "func\\s+[" + "".join(operators) + "]+\(zeroOrManySpaces)(<[A-Z]+>)?\\("
- let pattern2 = "func\(zeroOrManySpaces)[" + "".join(operators) + "]+\\s+(<[A-Z]+>)?\\("
+ let pattern1 = "func\\s+[" +
+ operators.joinWithSeparator("") +
+ "]+\(zeroOrManySpaces)(<[A-Z]+>)?\\("
+ let pattern2 = "func\(zeroOrManySpaces)[" +
+ operators.joinWithSeparator("") +
+ "]+\\s+(<[A-Z]+>)?\\("
return file.matchPattern("(\(pattern1)|\(pattern2))").filter { _, syntaxKinds in
return syntaxKinds.first == .Keyword
}.map { range, _ in
return StyleViolation(type: .OperatorFunctionWhitespace,
location: Location(file: file, offset: range.location),
severity: .Medium,
- reason: self.example.ruleDescription)
+ reason: example.ruleDescription)
}
}
diff --git a/Source/SwiftLintFramework/Rules/ReturnArrowWhitespaceRule.swift b/Source/SwiftLintFramework/Rules/ReturnArrowWhitespaceRule.swift
index e8d6a0fcb..a5003cd98 100644
--- a/Source/SwiftLintFramework/Rules/ReturnArrowWhitespaceRule.swift
+++ b/Source/SwiftLintFramework/Rules/ReturnArrowWhitespaceRule.swift
@@ -6,6 +6,7 @@
// Copyright (c) 2015 Realm. All rights reserved.
//
+import Foundation
import SourceKittenFramework
public struct ReturnArrowWhitespaceRule: Rule {
diff --git a/Source/SwiftLintFramework/Rules/TrailingNewlineRule.swift b/Source/SwiftLintFramework/Rules/TrailingNewlineRule.swift
index eccc53fc4..e8751c247 100644
--- a/Source/SwiftLintFramework/Rules/TrailingNewlineRule.swift
+++ b/Source/SwiftLintFramework/Rules/TrailingNewlineRule.swift
@@ -15,13 +15,13 @@ public struct TrailingNewlineRule: Rule {
public func validateFile(file: File) -> [StyleViolation] {
let string = file.contents
- let start = advance(string.endIndex, -2, string.startIndex)
+ let start = string.endIndex.advancedBy(-2, limit: string.startIndex)
let range = Range(start: start, end: string.endIndex)
let substring = string[range].utf16
let newLineSet = NSCharacterSet.newlineCharacterSet()
- let slices = split(substring, allowEmptySlices: true) { !newLineSet.characterIsMember($0) }
+ let slices = substring.split(allowEmptySlices: true) { !newLineSet.characterIsMember($0) }
- if let slice = slices.last where count(slice) != 1 {
+ if let slice = slices.last where slice.count != 1 {
return [StyleViolation(type: .TrailingNewline,
location: Location(file: file.path, line: file.contents.lines().count + 1),
severity: .Medium,
diff --git a/Source/SwiftLintFramework/Rules/TypeBodyLengthRule.swift b/Source/SwiftLintFramework/Rules/TypeBodyLengthRule.swift
index bf2f0fef2..5a2d12613 100644
--- a/Source/SwiftLintFramework/Rules/TypeBodyLengthRule.swift
+++ b/Source/SwiftLintFramework/Rules/TypeBodyLengthRule.swift
@@ -27,13 +27,16 @@ public struct TypeBodyLengthRule: ASTRule, ParameterizedRule {
}
public func validateFile(file: File, dictionary: XPCDictionary) -> [StyleViolation] {
- return (dictionary["key.substructure"] as? XPCArray ?? []).flatMap { subItem in
+ let substructure = dictionary["key.substructure"] as? XPCArray ?? []
+ return substructure.flatMap { subItem -> [StyleViolation] in
var violations = [StyleViolation]()
if let subDict = subItem as? XPCDictionary,
let kindString = subDict["key.kind"] as? String,
- let kind = flatMap(kindString, { SwiftDeclarationKind(rawValue: $0) }) {
- violations.extend(validateFile(file, dictionary: subDict))
- violations.extend(validateFile(file, kind: kind, dictionary: subDict))
+ let kind = SwiftDeclarationKind(rawValue: kindString) {
+ violations.appendContentsOf(
+ self.validateFile(file, dictionary: subDict) +
+ self.validateFile(file, kind: kind, dictionary: subDict)
+ )
}
return violations
}
@@ -47,16 +50,16 @@ public struct TypeBodyLengthRule: ASTRule, ParameterizedRule {
.Struct,
.Enum
]
- if !contains(typeKinds, kind) {
+ if !typeKinds.contains(kind) {
return []
}
- if let offset = flatMap(dictionary["key.offset"] as? Int64, { Int($0) }),
- let bodyOffset = flatMap(dictionary["key.bodyoffset"] as? Int64, { Int($0) }),
- let bodyLength = flatMap(dictionary["key.bodylength"] as? Int64, { Int($0) }) {
+ if let offset = (dictionary["key.offset"] as? Int64).flatMap({ Int($0) }),
+ let bodyOffset = (dictionary["key.bodyoffset"] as? Int64).flatMap({ Int($0) }),
+ let bodyLength = (dictionary["key.bodylength"] as? Int64).flatMap({ Int($0) }) {
let location = Location(file: file, offset: offset)
let startLine = file.contents.lineAndCharacterForByteOffset(bodyOffset)
let endLine = file.contents.lineAndCharacterForByteOffset(bodyOffset + bodyLength)
- for parameter in reverse(parameters) {
+ for parameter in parameters.reverse() {
if let startLine = startLine?.line, let endLine = endLine?.line
where endLine - startLine > parameter.value {
return [StyleViolation(type: .Length,
diff --git a/Source/SwiftLintFramework/Rules/TypeNameRule.swift b/Source/SwiftLintFramework/Rules/TypeNameRule.swift
index 510452101..a3af178b3 100644
--- a/Source/SwiftLintFramework/Rules/TypeNameRule.swift
+++ b/Source/SwiftLintFramework/Rules/TypeNameRule.swift
@@ -19,13 +19,16 @@ public struct TypeNameRule: ASTRule {
}
public func validateFile(file: File, dictionary: XPCDictionary) -> [StyleViolation] {
- return (dictionary["key.substructure"] as? XPCArray ?? []).flatMap { subItem in
+ let substructure = dictionary["key.substructure"] as? XPCArray ?? []
+ return substructure.flatMap { subItem -> [StyleViolation] in
var violations = [StyleViolation]()
if let subDict = subItem as? XPCDictionary,
let kindString = subDict["key.kind"] as? String,
- let kind = flatMap(kindString, { SwiftDeclarationKind(rawValue: $0) }) {
- violations.extend(validateFile(file, dictionary: subDict))
- violations.extend(validateFile(file, kind: kind, dictionary: subDict))
+ let kind = SwiftDeclarationKind(rawValue: kindString) {
+ violations.appendContentsOf(
+ self.validateFile(file, dictionary: subDict) +
+ self.validateFile(file, kind: kind, dictionary: subDict)
+ )
}
return violations
}
@@ -41,12 +44,12 @@ public struct TypeNameRule: ASTRule {
.Enum,
.Enumelement
]
- if !contains(typeKinds, kind) {
+ if !typeKinds.contains(kind) {
return []
}
var violations = [StyleViolation]()
if let name = dictionary["key.name"] as? String,
- let offset = flatMap(dictionary["key.offset"] as? Int64, { Int($0) }) {
+ let offset = (dictionary["key.offset"] as? Int64).flatMap({ Int($0) }) {
let location = Location(file: file, offset: offset)
let nameCharacterSet = NSCharacterSet(charactersInString: name)
if !NSCharacterSet.alphanumericCharacterSet().isSupersetOfSet(nameCharacterSet) {
@@ -59,7 +62,7 @@ public struct TypeNameRule: ASTRule {
location: location,
severity: .High,
reason: "Type name should start with an uppercase character: '\(name)'"))
- } else if count(name) < 3 || count(name) > 40 {
+ } else if name.characters.count < 3 || name.characters.count > 40 {
violations.append(StyleViolation(type: .NameFormat,
location: location,
severity: .Medium,
diff --git a/Source/SwiftLintFramework/Rules/VariableNameRule.swift b/Source/SwiftLintFramework/Rules/VariableNameRule.swift
index 9e5a9a4d1..5ebea50ac 100644
--- a/Source/SwiftLintFramework/Rules/VariableNameRule.swift
+++ b/Source/SwiftLintFramework/Rules/VariableNameRule.swift
@@ -19,13 +19,16 @@ public struct VariableNameRule: ASTRule {
}
public func validateFile(file: File, dictionary: XPCDictionary) -> [StyleViolation] {
- return (dictionary["key.substructure"] as? XPCArray ?? []).flatMap { subItem in
+ let substructure = dictionary["key.substructure"] as? XPCArray ?? []
+ return substructure.flatMap { subItem -> [StyleViolation] in
var violations = [StyleViolation]()
if let subDict = subItem as? XPCDictionary,
let kindString = subDict["key.kind"] as? String,
- let kind = flatMap(kindString, { SwiftDeclarationKind(rawValue: $0) }) {
- violations.extend(validateFile(file, dictionary: subDict))
- violations.extend(validateFile(file, kind: kind, dictionary: subDict))
+ let kind = SwiftDeclarationKind(rawValue: kindString) {
+ violations.appendContentsOf(
+ self.validateFile(file, dictionary: subDict) +
+ self.validateFile(file, kind: kind, dictionary: subDict)
+ )
}
return violations
}
@@ -42,12 +45,12 @@ public struct VariableNameRule: ASTRule {
.VarParameter,
.VarStatic
]
- if !contains(variableKinds, kind) {
+ if !variableKinds.contains(kind) {
return []
}
var violations = [StyleViolation]()
if let name = dictionary["key.name"] as? String,
- let offset = flatMap(dictionary["key.offset"] as? Int64, { Int($0) }) {
+ let offset = (dictionary["key.offset"] as? Int64).flatMap({ Int($0) }) {
let location = Location(file: file, offset: offset)
let nameCharacterSet = NSCharacterSet(charactersInString: name)
if !NSCharacterSet.alphanumericCharacterSet().isSupersetOfSet(nameCharacterSet) {
@@ -60,7 +63,7 @@ public struct VariableNameRule: ASTRule {
location: location,
severity: .High,
reason: "Variable name should start with a lowercase character: '\(name)'"))
- } else if count(name) < 3 || count(name) > 40 {
+ } else if name.characters.count < 3 || name.characters.count > 40 {
violations.append(StyleViolation(type: .NameFormat,
location: location,
severity: .Medium,
diff --git a/Source/SwiftLintFramework/String+SwiftLint.swift b/Source/SwiftLintFramework/String+SwiftLint.swift
index 4bf232773..7ce54bd76 100644
--- a/Source/SwiftLintFramework/String+SwiftLint.swift
+++ b/Source/SwiftLintFramework/String+SwiftLint.swift
@@ -24,7 +24,7 @@ extension String {
}
func countOfTailingCharactersInSet(characterSet: NSCharacterSet) -> Int {
- return String(reverse(self)).countOfLeadingCharactersInSet(characterSet)
+ return String(characters.reverse()).countOfLeadingCharactersInSet(characterSet)
}
public var chomped: String {
@@ -34,20 +34,16 @@ extension String {
extension NSString {
public func lineAndCharacterForByteOffset(offset: Int) -> (line: Int, character: Int)? {
- return flatMap(byteRangeToNSRange(start: offset, length: 0)) { range in
- var numberOfLines = 0
- var index = 0
- var lineRangeStart = 0
- var previousIndex = 0
+ return byteRangeToNSRange(start: offset, length: 0).flatMap { range in
+ var numberOfLines = 0, index = 0, lineRangeStart = 0, previousIndex = 0
while index < length {
numberOfLines++
- if index <= range.location {
- lineRangeStart = numberOfLines
- previousIndex = index
- index = NSMaxRange(self.lineRangeForRange(NSRange(location: index, length: 1)))
- } else {
+ if index > range.location {
break
}
+ lineRangeStart = numberOfLines
+ previousIndex = index
+ index = NSMaxRange(lineRangeForRange(NSRange(location: index, length: 1)))
}
return (lineRangeStart, range.location - previousIndex + 1)
}
diff --git a/Source/SwiftLintFramework/StyleViolation.swift b/Source/SwiftLintFramework/StyleViolation.swift
index 1fe1dfb08..8a1795f17 100644
--- a/Source/SwiftLintFramework/StyleViolation.swift
+++ b/Source/SwiftLintFramework/StyleViolation.swift
@@ -6,7 +6,7 @@
// Copyright (c) 2015 Realm. All rights reserved.
//
-public struct StyleViolation: Printable, Equatable {
+public struct StyleViolation: CustomStringConvertible, Equatable {
public let type: StyleViolationType
public let severity: ViolationSeverity
public let location: Location
diff --git a/Source/SwiftLintFramework/StyleViolationType.swift b/Source/SwiftLintFramework/StyleViolationType.swift
index 0d7036e8e..6dd2a5445 100644
--- a/Source/SwiftLintFramework/StyleViolationType.swift
+++ b/Source/SwiftLintFramework/StyleViolationType.swift
@@ -6,7 +6,7 @@
// Copyright (c) 2015 Realm. All rights reserved.
//
-public enum StyleViolationType: String, Printable {
+public enum StyleViolationType: String, CustomStringConvertible {
case NameFormat = "Name Format"
case Length = "Length"
case TrailingNewline = "Trailing Newline"
diff --git a/Source/SwiftLintFramework/ViolationSeverity.swift b/Source/SwiftLintFramework/ViolationSeverity.swift
index 823e21f45..6cb15a0ee 100644
--- a/Source/SwiftLintFramework/ViolationSeverity.swift
+++ b/Source/SwiftLintFramework/ViolationSeverity.swift
@@ -6,7 +6,7 @@
// Copyright (c) 2015 Realm. All rights reserved.
//
-public enum ViolationSeverity: Int, Printable, Comparable {
+public enum ViolationSeverity: Int, CustomStringConvertible, Comparable {
case VeryLow
case Low
case Medium
diff --git a/Source/SwiftLintFrameworkTests/ASTRuleTests.swift b/Source/SwiftLintFrameworkTests/ASTRuleTests.swift
index 3c6eb9f15..82000f13d 100644
--- a/Source/SwiftLintFrameworkTests/ASTRuleTests.swift
+++ b/Source/SwiftLintFrameworkTests/ASTRuleTests.swift
@@ -29,7 +29,7 @@ class ASTRuleTests: XCTestCase {
severity: .Medium,
reason: "Type name should be between 3 and 40 characters in length: 'Ab'")])
- let longName = join("", Array(count: 40, repeatedValue: "A"))
+ let longName = Repeat(count: 40, repeatedValue: "A").joinWithSeparator("")
XCTAssertEqual(violations("\(kind) \(longName) {}\n"), [])
let longerName = longName + "A"
XCTAssertEqual(violations("\(kind) \(longerName) {}\n"), [
@@ -57,7 +57,7 @@ class ASTRuleTests: XCTestCase {
func testVariableNames() {
for kind in ["class", "struct"] {
for varType in ["var", "let"] {
- let characterOffset = 8 + count(kind)
+ let characterOffset = 8 + kind.characters.count
XCTAssertEqual(violations("\(kind) Abc { \(varType) def: Void }\n"), [])
XCTAssertEqual(violations("\(kind) Abc { \(varType) de_: Void }\n"), [
@@ -82,7 +82,7 @@ class ASTRuleTests: XCTestCase {
"'de'")
])
- let longName = join("", Array(count: 40, repeatedValue: "d"))
+ let longName = Repeat(count: 40, repeatedValue: "d").joinWithSeparator("")
XCTAssertEqual(violations("\(kind) Abc { \(varType) \(longName): Void }\n"), [])
let longerName = longName + "d"
XCTAssertEqual(violations("\(kind) Abc { \(varType) \(longerName): Void }\n"), [
@@ -98,11 +98,11 @@ class ASTRuleTests: XCTestCase {
func testFunctionBodyLengths() {
let longFunctionBody = "func abc() {" +
- join("", Array(count: 40, repeatedValue: "\n")) +
+ Repeat(count: 40, repeatedValue: "\n").joinWithSeparator("") +
"}\n"
XCTAssertEqual(violations(longFunctionBody), [])
let longerFunctionBody = "func abc() {" +
- join("", Array(count: 41, repeatedValue: "\n")) +
+ Repeat(count: 41, repeatedValue: "\n").joinWithSeparator("") +
"}\n"
XCTAssertEqual(violations(longerFunctionBody), [StyleViolation(type: .Length,
location: Location(file: nil, line: 1, character: 1),
@@ -113,11 +113,11 @@ class ASTRuleTests: XCTestCase {
func testTypeBodyLengths() {
for kind in ["class", "struct", "enum"] {
let longTypeBody = "\(kind) Abc {" +
- join("", Array(count: 200, repeatedValue: "\n")) +
+ Repeat(count: 200, repeatedValue: "\n").joinWithSeparator("") +
"}\n"
XCTAssertEqual(violations(longTypeBody), [])
let longerTypeBody = "\(kind) Abc {" +
- join("", Array(count: 201, repeatedValue: "\n")) +
+ Repeat(count: 201, repeatedValue: "\n").joinWithSeparator("") +
"}\n"
XCTAssertEqual(violations(longerTypeBody), [StyleViolation(type: .Length,
location: Location(file: nil, line: 1, character: 1),
diff --git a/Source/SwiftLintFrameworkTests/ConfigurationTests.swift b/Source/SwiftLintFrameworkTests/ConfigurationTests.swift
new file mode 100644
index 000000000..0af7e51e0
--- /dev/null
+++ b/Source/SwiftLintFrameworkTests/ConfigurationTests.swift
@@ -0,0 +1,50 @@
+//
+// ConfigurationTests.swift
+// SwiftLint
+//
+// Created by JP Simard on 8/23/15.
+// Copyright © 2015 Realm. All rights reserved.
+//
+
+import SwiftLintFramework
+import XCTest
+
+class ConfigurationTests: XCTestCase {
+ func testInit() {
+ XCTAssert(Configuration(yaml: "") != nil,
+ "initializing Configuration with empty YAML string should succeed")
+ XCTAssert(Configuration(yaml: "a: 1\nb: 2") != nil,
+ "initializing Configuration with valid YAML string should succeed")
+ XCTAssert(Configuration(yaml: "|\na") == nil,
+ "initializing Configuration with invalid YAML string should fail")
+ }
+
+ func testEmptyConfiguration() {
+ guard let config = Configuration(yaml: "") else {
+ XCTFail("empty YAML string should yield non-nil Configuration")
+ return
+ }
+ XCTAssertEqual(config.disabledRules, [])
+ XCTAssertEqual(config.included, [])
+ XCTAssertEqual(config.excluded, [])
+ }
+
+ func testDisabledRules() {
+ XCTAssert(Configuration(yaml: "disabled_rules:\n - a") == nil,
+ "initializing Configuration with invalid rules in YAML string should fail")
+ let disabledConfig = Configuration(yaml: "disabled_rules:\n - nesting\n - todo")!
+ XCTAssertEqual(disabledConfig.disabledRules,
+ ["nesting", "todo"],
+ "initializing Configuration with valid rules in YAML string should succeed")
+ let expectedIdentifiers = allRules
+ .map({ $0.identifier })
+ .filter({ !["nesting", "todo"].contains($0) })
+ let configuredIdentifiers = disabledConfig.rules.map({ $0.identifier })
+ XCTAssertEqual(expectedIdentifiers, configuredIdentifiers)
+
+ // Duplicate
+ let duplicateConfig = Configuration( yaml: "disabled_rules:\n - todo\n - todo")
+ XCTAssert(duplicateConfig == nil, "initializing Configuration with duplicate rules in " +
+ " YAML string should fail")
+ }
+}
diff --git a/Source/SwiftLintFrameworkTests/Info.plist b/Source/SwiftLintFrameworkTests/Info.plist
index 3e5a88fb0..e90c12e6a 100644
--- a/Source/SwiftLintFrameworkTests/Info.plist
+++ b/Source/SwiftLintFrameworkTests/Info.plist
@@ -7,7 +7,7 @@
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
- io.realm.$(PRODUCT_NAME:rfc1034identifier)
+ $(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
diff --git a/Source/SwiftLintFrameworkTests/IntegrationTests.swift b/Source/SwiftLintFrameworkTests/IntegrationTests.swift
index 704f1c7c6..c66c9e90c 100644
--- a/Source/SwiftLintFrameworkTests/IntegrationTests.swift
+++ b/Source/SwiftLintFrameworkTests/IntegrationTests.swift
@@ -15,12 +15,14 @@ class IntegrationTests: XCTestCase {
func testSwiftLintLints() {
// This is as close as we're ever going to get to a self-hosting linter.
let fileManager = NSFileManager.defaultManager()
- let directory = fileManager.currentDirectoryPath.stringByAppendingPathComponent("Source")
+ let directory = ((((__FILE__ as NSString)
+ .stringByDeletingLastPathComponent as NSString)
+ .stringByDeletingLastPathComponent as NSString)
+ .stringByDeletingLastPathComponent as NSString)
+ .stringByAppendingPathComponent("Source")
let allFiles = fileManager.allFilesRecursively(directory: directory)
- let swiftFiles = allFiles.filter {
- $0.isSwiftFile()
- }
- XCTAssert(contains(swiftFiles, __FILE__), "current file should be included")
+ let swiftFiles = allFiles.filter { $0.isSwiftFile() }
+ XCTAssert(swiftFiles.contains(__FILE__), "current file should be included")
XCTAssertEqual(swiftFiles.flatMap({Linter(file: File(path: $0)!).styleViolations}), [])
}
}
diff --git a/Source/SwiftLintFrameworkTests/StringRuleTests.swift b/Source/SwiftLintFrameworkTests/StringRuleTests.swift
index eac23b0db..20476fbdc 100644
--- a/Source/SwiftLintFrameworkTests/StringRuleTests.swift
+++ b/Source/SwiftLintFrameworkTests/StringRuleTests.swift
@@ -11,14 +11,14 @@ import XCTest
class StringRuleTests: XCTestCase {
func testLineLengths() {
- let longLine = join("", Array(count: 100, repeatedValue: "/")) + "\n"
+ let longLine = Repeat(count: 100, repeatedValue: "/").joinWithSeparator("") + "\n"
XCTAssertEqual(violations(longLine), [])
let testCases: [(String, Int, ViolationSeverity)] = [
("/", 101, .VeryLow),
- (join("", Array(count: 21, repeatedValue: "/")), 121, .Low),
- (join("", Array(count: 51, repeatedValue: "/")), 151, .Medium),
- (join("", Array(count: 101, repeatedValue: "/")), 201, .High),
- (join("", Array(count: 151, repeatedValue: "/")), 251, .VeryHigh)
+ (Repeat(count: 21, repeatedValue: "/").joinWithSeparator(""), 121, .Low),
+ (Repeat(count: 51, repeatedValue: "/").joinWithSeparator(""), 151, .Medium),
+ (Repeat(count: 101, repeatedValue: "/").joinWithSeparator(""), 201, .High),
+ (Repeat(count: 151, repeatedValue: "/").joinWithSeparator(""), 251, .VeryHigh)
]
for testCase in testCases {
XCTAssertEqual(violations(testCase.0 + longLine), [StyleViolation(type: .Length,
@@ -42,13 +42,16 @@ class StringRuleTests: XCTestCase {
}
func testFileLengths() {
- XCTAssertEqual(violations(join("", Array(count: 400, repeatedValue: "//\n"))), [])
+ XCTAssertEqual(
+ violations(Repeat(count: 400, repeatedValue: "//\n").joinWithSeparator("")),
+ []
+ )
let testCases: [(String, Int, ViolationSeverity)] = [
- (join("", Array(count: 401, repeatedValue: "//\n")), 401, .VeryLow),
- (join("", Array(count: 501, repeatedValue: "//\n")), 501, .Low),
- (join("", Array(count: 751, repeatedValue: "//\n")), 751, .Medium),
- (join("", Array(count: 1001, repeatedValue: "//\n")), 1001, .High),
- (join("", Array(count: 2001, repeatedValue: "//\n")), 2001, .VeryHigh)
+ (Repeat(count: 401, repeatedValue: "//\n").joinWithSeparator(""), 401, .VeryLow),
+ (Repeat(count: 501, repeatedValue: "//\n").joinWithSeparator(""), 501, .Low),
+ (Repeat(count: 751, repeatedValue: "//\n").joinWithSeparator(""), 751, .Medium),
+ (Repeat(count: 1001, repeatedValue: "//\n").joinWithSeparator(""), 1001, .High),
+ (Repeat(count: 2001, repeatedValue: "//\n").joinWithSeparator(""), 2001, .VeryHigh)
]
for testCase in testCases {
XCTAssertEqual(violations(testCase.0), [StyleViolation(type: .Length,
diff --git a/Source/SwiftLintFrameworkTests/TestHelpers.swift b/Source/SwiftLintFrameworkTests/TestHelpers.swift
index fdd1182bd..837524da5 100644
--- a/Source/SwiftLintFrameworkTests/TestHelpers.swift
+++ b/Source/SwiftLintFrameworkTests/TestHelpers.swift
@@ -14,7 +14,7 @@ func violations(string: String) -> [StyleViolation] {
return Linter(file: File(contents: string)).styleViolations
}
-private func violations(string: String, type: StyleViolationType) -> [StyleViolation] {
+private func violations(string: String, _ type: StyleViolationType) -> [StyleViolation] {
return violations(string).filter { $0.type == type }
}
diff --git a/Source/swiftlint/Components.plist b/Source/swiftlint/Components.plist
index 6c7141e76..8d3a3a1b0 100644
--- a/Source/swiftlint/Components.plist
+++ b/Source/swiftlint/Components.plist
@@ -7,27 +7,6 @@
BundleOverwriteAction
upgrade
- ChildBundles
-
-
- BundleOverwriteAction
-
- RootRelativeBundlePath
- Library/Frameworks/SwiftLintFramework.framework/Versions/A/Frameworks/SourceKittenFramework.framework
-
-
- BundleOverwriteAction
-
- RootRelativeBundlePath
- Library/Frameworks/SwiftLintFramework.framework/Versions/A/Frameworks/LlamaKit.framework
-
-
- BundleOverwriteAction
-
- RootRelativeBundlePath
- Library/Frameworks/SwiftLintFramework.framework/Versions/A/Frameworks/Commandant.framework
-
-
RootRelativeBundlePath
Library/Frameworks/SwiftLintFramework.framework
diff --git a/Source/swiftlint/Info.plist b/Source/swiftlint/Info.plist
index 52ede2e8a..afdd63f3c 100644
--- a/Source/swiftlint/Info.plist
+++ b/Source/swiftlint/Info.plist
@@ -9,7 +9,7 @@
CFBundleIconFile
CFBundleIdentifier
- io.realm.$(PRODUCT_NAME:rfc1034identifier)
+ $(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
diff --git a/Source/swiftlint/LintCommand.swift b/Source/swiftlint/LintCommand.swift
index 34820d349..63ea59ec1 100644
--- a/Source/swiftlint/LintCommand.swift
+++ b/Source/swiftlint/LintCommand.swift
@@ -8,7 +8,7 @@
import Commandant
import Foundation
-import LlamaKit
+import Result
import SourceKittenFramework
import SwiftLintFramework
@@ -21,38 +21,44 @@ struct LintCommand: CommandType {
func run(mode: CommandMode) -> Result<(), CommandantError<()>> {
return LintOptions.evaluate(mode).flatMap { options in
+ let configuration = Configuration(path: options.configurationFile,
+ optional: !Process.arguments.contains("--config"))
if options.useSTDIN {
let standardInput = NSFileHandle.fileHandleWithStandardInput()
let stdinData = standardInput.readDataToEndOfFile()
let stdinNSString = NSString(data: stdinData, encoding: NSUTF8StringEncoding)
if let stdinString = stdinNSString as? String {
- let violations = Linter(file: File(contents: stdinString)).styleViolations
- println(join("\n", violations.map { $0.description }))
- return success()
+ let file = File(contents: stdinString)
+ let linter = Linter(file: file, configuration: configuration)
+ print(linter.styleViolations.map({ $0.description }).joinWithSeparator("\n"))
+ return .Success()
}
- return failure(CommandantError<()>.CommandError(Box()))
+ return .Failure(CommandantError<()>.CommandError())
}
// Otherwise parse path.
- return self.lint(options.path)
+ return lint(options.path, configuration: configuration)
}
}
- private func lint(path: String) -> Result<(), CommandantError<()>> {
- let filesToLint = filesToLintAtPath(path)
+ private func lint(path: String,
+ configuration: Configuration) -> Result<(), CommandantError<()>> {
+ let filesToLint = (configuration.included.count == 0 ? filesToLintAtPath(path) : [])
+ .filter({ !configuration.excluded.flatMap(filesToLintAtPath).contains($0) }) +
+ configuration.included.flatMap(filesToLintAtPath)
if filesToLint.count > 0 {
-
- if path == "" {
- println("Linting Swift files in current working directory")
+ if path.isEmpty {
+ print("Linting Swift files in current working directory")
} else {
- println("Linting Swift files at path \(path)")
+ print("Linting Swift files at path \(path)")
}
-
var numberOfViolations = 0, numberOfSeriousViolations = 0
- for (index, file) in enumerate(filesToLint) {
- println("Linting '\(file.lastPathComponent)' (\(index + 1)/\(filesToLint.count))")
- for violation in Linter(file: File(path: file)!).styleViolations {
- println(violation)
+ for (index, path) in filesToLint.enumerate() {
+ let filename = (path as NSString).lastPathComponent
+ print("Linting '\(filename)' (\(index + 1)/\(filesToLint.count))")
+ let file = File(path: path)!
+ for violation in Linter(file: file, configuration: configuration).styleViolations {
+ print(violation)
numberOfViolations++
if violation.severity.isError {
numberOfSeriousViolations++
@@ -61,27 +67,23 @@ struct LintCommand: CommandType {
}
let violationSuffix = (numberOfViolations != 1 ? "s" : "")
let filesSuffix = (filesToLint.count != 1 ? "s." : ".")
- println(
+ print(
"Done linting!" +
" Found \(numberOfViolations) violation\(violationSuffix)," +
" \(numberOfSeriousViolations) serious" +
" in \(filesToLint.count) file\(filesSuffix)"
)
if numberOfSeriousViolations <= 0 {
- return success()
- } else {
- // This represents failure of the content (i.e. violations in the files linted)
- // and not failure of the scanning process itself. The current command architecture
- // doesn't discriminate between these types.
- return failure(CommandantError<()>.CommandError(Box()))
+ return .Success()
}
+ return .Failure(CommandantError<()>.CommandError())
}
- return failure(CommandantError<()>.UsageError(description: "No lintable files found at" +
+ return .Failure(CommandantError<()>.UsageError(description: "No lintable files found at" +
" path \(path)"))
}
private func filesToLintAtPath(path: String) -> [String] {
- let absolutePath = path.absolutePathRepresentation()
+ let absolutePath = (path.absolutePathRepresentation() as NSString).stringByStandardizingPath
var isDirectory: ObjCBool = false
if fileManager.fileExistsAtPath(absolutePath, isDirectory: &isDirectory) {
if isDirectory {
@@ -99,15 +101,22 @@ struct LintCommand: CommandType {
struct LintOptions: OptionsType {
let path: String
let useSTDIN: Bool
+ let configurationFile: String
- static func create(path: String)(useSTDIN: Bool) -> LintOptions {
- return LintOptions(path: path, useSTDIN: useSTDIN)
+ static func create(path: String)(useSTDIN: Bool)(configurationFile: String) -> LintOptions {
+ return LintOptions(path: path, useSTDIN: useSTDIN, configurationFile: configurationFile)
}
static func evaluate(m: CommandMode) -> Result> {
return create
- <*> m <| Option(key: "path", defaultValue: "", usage: "the path to the file or" +
- " directory to lint")
- <*> m <| Option(key: "use-stdin", defaultValue: false, usage: "lint standard input")
+ <*> m <| Option(key: "path",
+ defaultValue: "",
+ usage: "the path to the file or directory to lint")
+ <*> m <| Option(key: "use-stdin",
+ defaultValue: false,
+ usage: "lint standard input")
+ <*> m <| Option(key: "config",
+ defaultValue: ".swiftlint.yml",
+ usage: "the path to SwiftLint's configuration file")
}
}
diff --git a/Source/swiftlint/RulesCommand.swift b/Source/swiftlint/RulesCommand.swift
index f9323061a..ff46a2373 100644
--- a/Source/swiftlint/RulesCommand.swift
+++ b/Source/swiftlint/RulesCommand.swift
@@ -8,7 +8,7 @@
import Foundation
import Commandant
-import LlamaKit
+import Result
import SwiftLintFramework
import SourceKittenFramework
@@ -34,15 +34,15 @@ struct RulesCommand: CommandType {
func run(mode: CommandMode) -> Result<(), CommandantError<()>> {
switch mode {
- case let .Arguments:
+ case .Arguments:
let ruleExamples = Linter(file: File(contents: "")).ruleExamples
let text = StructuredText.Joined(ruleExamples.map(describeExample))
- println(text.ansi)
+ print(text.ansi)
default:
break
}
- return success()
+ return .Success()
}
}
diff --git a/Source/swiftlint/StructuredText.swift b/Source/swiftlint/StructuredText.swift
index c3dcb15ac..7423f3740 100644
--- a/Source/swiftlint/StructuredText.swift
+++ b/Source/swiftlint/StructuredText.swift
@@ -19,23 +19,23 @@ enum StructuredText {
var markdown: String {
switch self {
case let .Header(level, t):
- return join("", Array(count: level, repeatedValue: "#")) + " \(t)"
+ return String(Repeat(count: level, repeatedValue: "#")) + " \(t)"
case .Paragraph(let t):
return t
case .List(let items):
- return "\n".join(items.map { "* " + $0.markdown })
+ return items.map({ "* " + $0.markdown }).joinWithSeparator("\n")
case .Joined(let items):
- return "\n\n".join(items.map { $0.markdown } )
+ return items.map({ $0.markdown }).joinWithSeparator("\n\n")
}
}
var ansi: String {
switch self {
case .Header(1, let t): return t.uppercaseString
- case let .Header(other, t): return t
+ case .Header(_, let t): return t
case .Paragraph(let t): return t
- case .List(let items): return "\n".join(items.map { "* " + $0.ansi })
- case .Joined(let items): return "\n\n".join(items.map { $0.ansi } )
+ case .List(let items): return items.map({ "* " + $0.ansi }).joinWithSeparator("\n")
+ case .Joined(let items): return items.map({ $0.ansi }).joinWithSeparator("\n\n")
}
}
}
diff --git a/Source/swiftlint/VersionCommand.swift b/Source/swiftlint/VersionCommand.swift
index 5a5df025d..21bdf2333 100644
--- a/Source/swiftlint/VersionCommand.swift
+++ b/Source/swiftlint/VersionCommand.swift
@@ -7,7 +7,7 @@
//
import Commandant
-import LlamaKit
+import Result
private let version = "0.1.2"
@@ -17,12 +17,12 @@ struct VersionCommand: CommandType {
func run(mode: CommandMode) -> Result<(), CommandantError<()>> {
switch mode {
- case let .Arguments:
- println(version)
+ case .Arguments:
+ print(version)
default:
break
}
- return success()
+ return .Success()
}
}
diff --git a/SwiftLint.xcodeproj/project.pbxproj b/SwiftLint.xcodeproj/project.pbxproj
index 1d1605e6a..15dd91249 100644
--- a/SwiftLint.xcodeproj/project.pbxproj
+++ b/SwiftLint.xcodeproj/project.pbxproj
@@ -19,6 +19,8 @@
D0E7B65619E9C76900EDBA4D /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D1211B19E87861005E4BAA /* main.swift */; };
E57B23C11B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E57B23C01B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift */; };
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 */; };
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 */; };
@@ -52,10 +54,12 @@
E88DEA921B099B1F00A66CB0 /* TypeNameRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88DEA911B099B1F00A66CB0 /* TypeNameRule.swift */; };
E88DEA941B099C0900A66CB0 /* VariableNameRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88DEA931B099C0900A66CB0 /* VariableNameRule.swift */; };
E88DEA961B099CF200A66CB0 /* NestingRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88DEA951B099CF200A66CB0 /* NestingRule.swift */; };
+ E89376AD1B8A701E0025708E /* Yaml.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E89376AC1B8A701E0025708E /* Yaml.framework */; };
+ E89376AE1B8A70400025708E /* Yaml.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = E89376AC1B8A701E0025708E /* Yaml.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
E8AB1A2E1A649F2100452012 /* libclang.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E8AB1A2D1A649F2100452012 /* libclang.dylib */; };
E8BA7E111B07A3EC003E02D0 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8BA7E101B07A3EC003E02D0 /* Commandant.framework */; };
- E8BA7E131B07A3F3003E02D0 /* LlamaKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8BA7E121B07A3F3003E02D0 /* LlamaKit.framework */; };
- E8BA7E141B07A400003E02D0 /* LlamaKit.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = E8BA7E121B07A3F3003E02D0 /* LlamaKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ E8BA7E131B07A3F3003E02D0 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8BA7E121B07A3F3003E02D0 /* Result.framework */; };
+ E8BA7E141B07A400003E02D0 /* Result.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = E8BA7E121B07A3F3003E02D0 /* Result.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
E8BA7E151B07A400003E02D0 /* Commandant.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = E8BA7E101B07A3EC003E02D0 /* Commandant.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
E8BB8F9A1B17DDB200199606 /* ASTRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8BB8F991B17DDB200199606 /* ASTRuleTests.swift */; };
E8BB8F9C1B17DE3B00199606 /* StringRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8BB8F9B1B17DE3B00199606 /* StringRuleTests.swift */; };
@@ -87,7 +91,8 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
- E8BA7E141B07A400003E02D0 /* LlamaKit.framework in Copy Frameworks */,
+ E89376AE1B8A70400025708E /* Yaml.framework in Copy Frameworks */,
+ E8BA7E141B07A400003E02D0 /* Result.framework in Copy Frameworks */,
E8BA7E151B07A400003E02D0 /* Commandant.framework in Copy Frameworks */,
E876BFBF1B0782AA00114ED5 /* SourceKittenFramework.framework in Copy Frameworks */,
E8C0DFCE1AD349E5007EE3D4 /* SWXMLHash.framework in Copy Frameworks */,
@@ -142,9 +147,10 @@
D0D1217719E87B05005E4BAA /* SwiftLintFrameworkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftLintFrameworkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
D0D1217D19E87B05005E4BAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
D0E7B63219E9C64500EDBA4D /* swiftlint.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = swiftlint.app; sourceTree = BUILT_PRODUCTS_DIR; };
- D0E7B65819E9CA0800EDBA4D /* swiftlint */ = {isa = PBXFileReference; lastKnownFileType = text; path = swiftlint; sourceTree = BUILT_PRODUCTS_DIR; };
E57B23C01B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReturnArrowWhitespaceRule.swift; sourceTree = ""; };
E5A167C81B25A0B000CF2D03 /* OperatorFunctionWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorFunctionWhitespaceRule.swift; sourceTree = ""; };
+ E809EDA01B8A71DF00399043 /* Configuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; };
+ E809EDA21B8A73FB00399043 /* ConfigurationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurationTests.swift; sourceTree = ""; };
E81224991B04F85B001783D2 /* TestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestHelpers.swift; sourceTree = ""; };
E812249B1B04FADC001783D2 /* Linter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Linter.swift; sourceTree = ""; };
E832F10A1B17E2F5003F265F /* NSFileManager+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFileManager+SwiftLint.swift"; sourceTree = ""; };
@@ -176,9 +182,10 @@
E88DEA911B099B1F00A66CB0 /* TypeNameRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypeNameRule.swift; sourceTree = ""; };
E88DEA931B099C0900A66CB0 /* VariableNameRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VariableNameRule.swift; sourceTree = ""; };
E88DEA951B099CF200A66CB0 /* NestingRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NestingRule.swift; sourceTree = ""; };
+ E89376AC1B8A701E0025708E /* Yaml.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Yaml.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E8AB1A2D1A649F2100452012 /* libclang.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libclang.dylib; path = Toolchains/XcodeDefault.xctoolchain/usr/lib/libclang.dylib; sourceTree = DEVELOPER_DIR; };
E8BA7E101B07A3EC003E02D0 /* Commandant.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Commandant.framework; sourceTree = BUILT_PRODUCTS_DIR; };
- E8BA7E121B07A3F3003E02D0 /* LlamaKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = LlamaKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ E8BA7E121B07A3F3003E02D0 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E8BB8F991B17DDB200199606 /* ASTRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASTRuleTests.swift; sourceTree = ""; };
E8BB8F9B1B17DE3B00199606 /* StringRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringRuleTests.swift; sourceTree = ""; };
E8C0DFCC1AD349DB007EE3D4 /* SWXMLHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = SWXMLHash.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -189,7 +196,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- E8BA7E131B07A3F3003E02D0 /* LlamaKit.framework in Frameworks */,
+ E89376AD1B8A701E0025708E /* Yaml.framework in Frameworks */,
+ E8BA7E131B07A3F3003E02D0 /* Result.framework in Frameworks */,
E8BA7E111B07A3EC003E02D0 /* Commandant.framework in Frameworks */,
E876BFBE1B07828500114ED5 /* SourceKittenFramework.framework in Frameworks */,
E8AB1A2E1A649F2100452012 /* libclang.dylib in Frameworks */,
@@ -244,7 +252,6 @@
D0D1216E19E87B05005E4BAA /* SwiftLintFramework */,
D0D1217B19E87B05005E4BAA /* SwiftLintFrameworkTests */,
D0D1211919E87861005E4BAA /* Products */,
- D0E7B65819E9CA0800EDBA4D /* swiftlint */,
);
sourceTree = "";
usesTabs = 0;
@@ -343,6 +350,7 @@
isa = PBXGroup;
children = (
E88DEA8B1B0999A000A66CB0 /* ASTRule.swift */,
+ E809EDA01B8A71DF00399043 /* Configuration.swift */,
24E17F701B1481FF008195BE /* File+Cache.swift */,
E88DEA741B09852000A66CB0 /* File+SwiftLint.swift */,
E812249B1B04FADC001783D2 /* Linter.swift */,
@@ -365,7 +373,8 @@
D0D1216F19E87B05005E4BAA /* Supporting Files */ = {
isa = PBXGroup;
children = (
- E8BA7E121B07A3F3003E02D0 /* LlamaKit.framework */,
+ E89376AC1B8A701E0025708E /* Yaml.framework */,
+ E8BA7E121B07A3F3003E02D0 /* Result.framework */,
E8BA7E101B07A3EC003E02D0 /* Commandant.framework */,
E876BFBD1B07828500114ED5 /* SourceKittenFramework.framework */,
E8AB1A2D1A649F2100452012 /* libclang.dylib */,
@@ -381,6 +390,7 @@
isa = PBXGroup;
children = (
E8BB8F991B17DDB200199606 /* ASTRuleTests.swift */,
+ E809EDA21B8A73FB00399043 /* ConfigurationTests.swift */,
E832F10C1B17E725003F265F /* IntegrationTests.swift */,
E8BB8F9B1B17DE3B00199606 /* StringRuleTests.swift */,
E81224991B04F85B001783D2 /* TestHelpers.swift */,
@@ -497,7 +507,8 @@
D0D1211019E87861005E4BAA /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0630;
+ LastSwiftUpdateCheck = 0700;
+ LastUpgradeCheck = 0700;
ORGANIZATIONNAME = Realm;
TargetAttributes = {
D0D1216C19E87B05005E4BAA = {
@@ -574,7 +585,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "if which swiftlint >/dev/null; then\n cd Source && swiftlint\nelse\n echo \"SwiftLint not installed. Skipping lint.\"\nfi";
+ shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"SwiftLint not installed. Skipping lint.\"\nfi";
};
/* End PBXShellScriptBuildPhase section */
@@ -589,6 +600,7 @@
E57B23C11B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift in Sources */,
E88DEA841B0990F500A66CB0 /* ColonRule.swift in Sources */,
E88DEA791B098D4400A66CB0 /* RuleParameter.swift in Sources */,
+ E809EDA11B8A71DF00399043 /* Configuration.swift in Sources */,
E88DEA731B0984C400A66CB0 /* String+SwiftLint.swift in Sources */,
24E17F721B14BB3F008195BE /* File+Cache.swift in Sources */,
E88DEA6D1B09842200A66CB0 /* StyleViolationType.swift in Sources */,
@@ -623,6 +635,7 @@
E812249A1B04F85B001783D2 /* TestHelpers.swift in Sources */,
E8BB8F9C1B17DE3B00199606 /* StringRuleTests.swift in Sources */,
E8BB8F9A1B17DDB200199606 /* ASTRuleTests.swift in Sources */,
+ E809EDA31B8A73FB00399043 /* ConfigurationTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -659,6 +672,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = D0D1212619E878CC005E4BAA /* Debug.xcconfig */;
buildSettings = {
+ ENABLE_TESTABILITY = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
@@ -688,15 +702,15 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib",
- "$(PROJECT_DIR)/build/DerivedData/SwiftLint/Build/Products/Debug",
);
FRAMEWORK_VERSION = A;
- INFOPLIST_FILE = "$(SRCROOT)/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)",
"$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib",
);
+ PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFramework;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -720,15 +734,15 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib",
- "$(PROJECT_DIR)/build/DerivedData/SwiftLint/Build/Products/Debug",
);
FRAMEWORK_VERSION = A;
- INFOPLIST_FILE = "$(SRCROOT)/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)",
"$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib",
);
+ PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFramework;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -749,6 +763,7 @@
"$(inherited)",
);
INFOPLIST_FILE = Source/SwiftLintFrameworkTests/Info.plist;
+ PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFrameworkTests;
};
name = Debug;
@@ -762,6 +777,7 @@
"$(inherited)",
);
INFOPLIST_FILE = Source/SwiftLintFrameworkTests/Info.plist;
+ PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFrameworkTests;
};
name = Release;
@@ -788,15 +804,15 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib",
- "$(PROJECT_DIR)/build/DerivedData/SwiftLint/Build/Products/Debug",
);
FRAMEWORK_VERSION = A;
- INFOPLIST_FILE = "$(SRCROOT)/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)",
"$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib",
);
+ PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFramework;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -817,6 +833,7 @@
"$(inherited)",
);
INFOPLIST_FILE = Source/SwiftLintFrameworkTests/Info.plist;
+ PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFrameworkTests;
};
name = Profile;
@@ -843,15 +860,15 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib",
- "$(PROJECT_DIR)/build/DerivedData/SwiftLint/Build/Products/Debug",
);
FRAMEWORK_VERSION = A;
- INFOPLIST_FILE = "$(SRCROOT)/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)",
"$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib",
);
+ PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFramework;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -872,6 +889,7 @@
"$(inherited)",
);
INFOPLIST_FILE = Source/SwiftLintFrameworkTests/Info.plist;
+ PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFrameworkTests;
};
name = Test;
@@ -881,8 +899,9 @@
baseConfigurationReference = D0D1213419E878CC005E4BAA /* Mac-Application.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
- INFOPLIST_FILE = "$(SRCROOT)/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)";
};
name = Debug;
@@ -892,8 +911,9 @@
baseConfigurationReference = D0D1213419E878CC005E4BAA /* Mac-Application.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
- INFOPLIST_FILE = "$(SRCROOT)/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)";
};
name = Test;
@@ -903,8 +923,9 @@
baseConfigurationReference = D0D1213419E878CC005E4BAA /* Mac-Application.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
- INFOPLIST_FILE = "$(SRCROOT)/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)";
};
name = Release;
@@ -914,8 +935,9 @@
baseConfigurationReference = D0D1213419E878CC005E4BAA /* Mac-Application.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
- INFOPLIST_FILE = "$(SRCROOT)/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)";
};
name = Profile;
diff --git a/SwiftLint.xcodeproj/xcshareddata/xcschemes/SwiftLintFramework.xcscheme b/SwiftLint.xcodeproj/xcshareddata/xcschemes/SwiftLintFramework.xcscheme
index b1868e335..8a181e818 100644
--- a/SwiftLint.xcodeproj/xcshareddata/xcschemes/SwiftLintFramework.xcscheme
+++ b/SwiftLint.xcodeproj/xcshareddata/xcschemes/SwiftLintFramework.xcscheme
@@ -1,6 +1,6 @@
+ shouldUseLaunchSchemeArgsEnv = "YES">
@@ -62,15 +62,18 @@
ReferencedContainer = "container:SwiftLint.xcodeproj">
+
+
+ shouldUseLaunchSchemeArgsEnv = "YES">
@@ -48,16 +48,19 @@
ReferencedContainer = "container:SwiftLint.xcodeproj">
+
+
diff --git a/SwiftLint.xcworkspace/contents.xcworkspacedata b/SwiftLint.xcworkspace/contents.xcworkspacedata
index 36f152236..84b11a5ed 100644
--- a/SwiftLint.xcworkspace/contents.xcworkspacedata
+++ b/SwiftLint.xcworkspace/contents.xcworkspacedata
@@ -14,9 +14,12 @@
location = "group:Carthage/Checkouts/Commandant/Commandant.xcodeproj">
+ location = "group:Carthage/Checkouts/Commandant/Carthage/Checkouts/Result/Result.xcodeproj">
+
+