Compare commits

...

15 Commits

Author SHA1 Message Date
JP Simard ad90413304
use latest Swift snapshot 2017-05-29 16:40:31 -07:00
JP Simard 0f9a0a3f52
remove .swift-version that wasn't there in master 2017-05-29 16:27:07 -07:00
JP Simard f53383f88f
update Cartfile dependencies 2017-05-29 16:26:34 -07:00
JP Simard 0b8bb4cc3a
Package.swift v4 2017-05-29 16:20:29 -07:00
JP Simard 3058fa3353
rm Package.resolved 2017-05-29 16:20:29 -07:00
JP Simard c5279f1891
root 2017-05-29 16:20:29 -07:00
JP Simard 5d56f2f96e
update swiftlint executable target to Swift 4 2017-05-29 16:20:29 -07:00
JP Simard 70c30f181c
different commits 2017-05-29 16:20:29 -07:00
JP Simard 892cd76bb0
point to local repos 2017-05-29 16:20:28 -07:00
JP Simard d5380d5690
revert 2017-05-29 16:20:28 -07:00
JP Simard cf44bcf5c6
import PackageDescription4 2017-05-29 16:20:28 -07:00
JP Simard 508723c595
add swift version 2017-05-29 16:20:28 -07:00
JP Simard d2e5b4b576
update Package.swift 2017-05-29 16:20:28 -07:00
JP Simard 6d26dd2a05
update Cartfile to point dependencies to their jp-swift-4 branches 2017-05-29 16:20:28 -07:00
JP Simard aaed908a8b
Swift 4 support 2017-05-29 16:20:28 -07:00
55 changed files with 300 additions and 117 deletions

2
.gitmodules vendored
View File

@ -15,7 +15,7 @@
url = https://github.com/jpsim/SourceKitten.git url = https://github.com/jpsim/SourceKitten.git
[submodule "Carthage/Checkouts/SwiftyTextTable"] [submodule "Carthage/Checkouts/SwiftyTextTable"]
path = Carthage/Checkouts/SwiftyTextTable path = Carthage/Checkouts/SwiftyTextTable
url = https://github.com/scottrhoyt/SwiftyTextTable.git url = https://github.com/jpsim/SwiftyTextTable.git
[submodule "Carthage/Checkouts/Yams"] [submodule "Carthage/Checkouts/Yams"]
path = Carthage/Checkouts/Yams path = Carthage/Checkouts/Yams
url = https://github.com/jpsim/Yams.git url = https://github.com/jpsim/Yams.git

View File

@ -1,2 +1,2 @@
github "jpsim/SourceKitten" ~> 0.17 github "jpsim/SourceKitten" "jp-swift-4"
github "scottrhoyt/SwiftyTextTable" ~> 0.5.0 github "jpsim/SwiftyTextTable" "jp-swift-4"

View File

@ -1,3 +1,3 @@
github "Carthage/Commandant" "master" github "Carthage/Commandant" "master"
github "jspahrsummers/xcconfigs" "master" github "jspahrsummers/xcconfigs" "master"
github "jpsim/Yams" ~> 0.3 github "jpsim/Yams" "master"

View File

@ -1,7 +1,7 @@
github "Carthage/Commandant" "16bcee12f48564c87bb13830f5320d21257e15b8" github "Carthage/Commandant" "16bcee12f48564c87bb13830f5320d21257e15b8"
github "antitypical/Result" "3.2.2" github "antitypical/Result" "3.2.3"
github "drmohundro/SWXMLHash" "3.1.0" github "drmohundro/SWXMLHash" "4cb1b72d406b4309aed6e6b2f11f46aa83dacbf7"
github "jpsim/SourceKitten" "0.17.6" github "jpsim/SourceKitten" "6e60ee7d6e9885ad6e674d55a5f540b0e52def09"
github "jpsim/Yams" "0.3.2" github "jpsim/SwiftyTextTable" "15f72002eea8e3b446d104d18225b6a828218d32"
github "jpsim/Yams" "b53284ba4c8bdece9ec8aad2e0010602dac588e9"
github "jspahrsummers/xcconfigs" "2055f18efbe18e77408f7f43947f7ad92b2d4ff0" github "jspahrsummers/xcconfigs" "2055f18efbe18e77408f7f43947f7ad92b2d4ff0"
github "scottrhoyt/SwiftyTextTable" "0.5.0"

@ -1 +1 @@
Subproject commit f460dee9c9de710463c91a505c1b4a566de7621c Subproject commit c8446185238659a2b27c0261f64ff1254291d07d

@ -1 +1 @@
Subproject commit 10b0b412a39542d19d002d6ff9f00d1a158332d9 Subproject commit 4cb1b72d406b4309aed6e6b2f11f46aa83dacbf7

@ -1 +1 @@
Subproject commit 91d9d5b20876da2afcbf34664bccc0bfd26088c7 Subproject commit 6e60ee7d6e9885ad6e674d55a5f540b0e52def09

@ -1 +1 @@
Subproject commit 13489587b932674addd93fdfca8e627a76e6a6db Subproject commit 15f72002eea8e3b446d104d18225b6a828218d32

@ -1 +1 @@
Subproject commit acf403cb0d950a2d58ea8c63ce001deac2fde222 Subproject commit b53284ba4c8bdece9ec8aad2e0010602dac588e9

View File

@ -91,6 +91,9 @@ release: package archive portable_zip
docker_test: docker_test:
docker run -v `pwd`:`pwd` -w `pwd` --name swiftlint --rm norionomura/sourcekit:311 swift test docker run -v `pwd`:`pwd` -w `pwd` --name swiftlint --rm norionomura/sourcekit:311 swift test
docker_test_4:
docker run -v `pwd`:`pwd` -w `pwd` --name swiftlint --rm norionomura/swift:4020170524a swift test
docker_htop: docker_htop:
docker run -it --rm --pid=container:swiftlint terencewestphal/htop || reset docker run -it --rm --pid=container:swiftlint terencewestphal/htop || reset

79
Package.resolved Normal file
View File

@ -0,0 +1,79 @@
{
"object": {
"pins": [
{
"package": "Clang_C",
"repositoryURL": "https://github.com/norio-nomura/Clang_C.git",
"state": {
"branch": null,
"revision": "90a9574276f0fd17f02f58979423c3fd4d73b59e",
"version": "1.0.2"
}
},
{
"package": "Commandant",
"repositoryURL": "https://github.com/Carthage/Commandant.git",
"state": {
"branch": null,
"revision": "c281992c31c3f41c48b5036c5a38185eaec32626",
"version": "0.12.0"
}
},
{
"package": "Result",
"repositoryURL": "https://github.com/antitypical/Result.git",
"state": {
"branch": null,
"revision": "c8446185238659a2b27c0261f64ff1254291d07d",
"version": "3.2.3"
}
},
{
"package": "SourceKit",
"repositoryURL": "https://github.com/norio-nomura/SourceKit.git",
"state": {
"branch": null,
"revision": "18eaa67ca44443bbe39646916792b9f0c98dbaa1",
"version": "1.0.1"
}
},
{
"package": "SourceKitten",
"repositoryURL": "https://github.com/jpsim/SourceKitten.git",
"state": {
"branch": "jp-swift-4",
"revision": "6632fb43284436ab77c709fb4c8c5e55de42f6f5",
"version": null
}
},
{
"package": "SwiftyTextTable",
"repositoryURL": "https://github.com/jpsim/SwiftyTextTable.git",
"state": {
"branch": "jp-swift-4",
"revision": "15f72002eea8e3b446d104d18225b6a828218d32",
"version": null
}
},
{
"package": "SWXMLHash",
"repositoryURL": "https://github.com/drmohundro/SWXMLHash.git",
"state": {
"branch": "version-4.0-changes",
"revision": "4cb1b72d406b4309aed6e6b2f11f46aa83dacbf7",
"version": null
}
},
{
"package": "Yams",
"repositoryURL": "https://github.com/jpsim/Yams.git",
"state": {
"branch": "master",
"revision": "b53284ba4c8bdece9ec8aad2e0010602dac588e9",
"version": null
}
}
]
},
"version": 1
}

View File

@ -1,17 +1,39 @@
// swift-tools-version:4.0
import PackageDescription import PackageDescription
let package = Package( let package = Package(
name: "SwiftLint", name: "SwiftLint",
targets: [ products: [
Target(name: "SwiftLintFramework"), .executable(name: "swiftlint", targets: ["swiftlint"]),
Target(name: "swiftlint", .library(name: "SwiftLintFramework", targets: ["SwiftLintFramework"])
dependencies: [
.Target(name: "SwiftLintFramework")
]),
], ],
dependencies: [ dependencies: [
.Package(url: "https://github.com/jpsim/SourceKitten.git", majorVersion: 0, minor: 17), .package(url: "https://github.com/Carthage/Commandant.git", from: "0.12.0"),
.Package(url: "https://github.com/jpsim/Yams.git", majorVersion: 0, minor: 3), .package(url: "https://github.com/jpsim/Yams.git", .branch("master")),
.Package(url: "https://github.com/scottrhoyt/SwiftyTextTable.git", majorVersion: 0, minor: 5), .package(url: "https://github.com/jpsim/SourceKitten.git", .branch("jp-swift-4")),
.package(url: "https://github.com/jpsim/SwiftyTextTable.git", .branch("jp-swift-4")),
],
targets: [
.target(
name: "swiftlint",
dependencies: [
"Commandant",
"SwiftLintFramework",
"SwiftyTextTable"
] ]
),
.target(
name: "SwiftLintFramework",
dependencies: [
"SourceKittenFramework"
]
),
.testTarget(
name: "SwiftLintFrameworkTests",
dependencies: [
"SwiftLintFramework"
]
)
],
swiftLanguageVersions: [3, 4]
) )

View File

@ -35,7 +35,7 @@ extension Array {
return nil return nil
} }
func group<U: Hashable>(by transform: (Element) -> U) -> [U: [Element]] { func group<U>(by transform: (Element) -> U) -> [U: [Element]] {
return reduce([:]) { dictionary, element in return reduce([:]) { dictionary, element in
var dictionary = dictionary var dictionary = dictionary
let key = transform(element) let key = transform(element)
@ -52,11 +52,33 @@ extension Array {
} }
func parallelFlatMap<T>(transform: @escaping ((Element) -> [T])) -> [T] { func parallelFlatMap<T>(transform: @escaping ((Element) -> [T])) -> [T] {
return parallelMap(transform: transform).flatMap { $0 } var result = [(Int, [T])]()
result.reserveCapacity(count)
let queueLabelPrefix = "io.realm.SwiftLintFramework.map.\(NSUUID().uuidString)"
let resultAccumulatorQueue = DispatchQueue(label: "\(queueLabelPrefix).resultAccumulator")
DispatchQueue.concurrentPerform(iterations: count) { index in
let jobIndexAndResults = (index, transform(self[index]))
resultAccumulatorQueue.sync {
result.append(jobIndexAndResults)
}
}
return result.sorted { $0.0 < $1.0 }.flatMap { $0.1 }
} }
func parallelFlatMap<T>(transform: @escaping ((Element) -> T?)) -> [T] { func parallelFlatMap<T>(transform: @escaping ((Element) -> T?)) -> [T] {
return parallelMap(transform: transform).flatMap { $0 } var result = [(Int, T?)]()
result.reserveCapacity(count)
let queueLabelPrefix = "io.realm.SwiftLintFramework.map.\(NSUUID().uuidString)"
let resultAccumulatorQueue = DispatchQueue(label: "\(queueLabelPrefix).resultAccumulator")
DispatchQueue.concurrentPerform(iterations: count) { index in
let jobIndexAndResults = (index, transform(self[index]))
resultAccumulatorQueue.sync {
result.append(jobIndexAndResults)
}
}
return result.sorted { $0.0 < $1.0 }.flatMap { $0.1 }
} }
func parallelMap<T>(transform: @escaping ((Element) -> T)) -> [T] { func parallelMap<T>(transform: @escaping ((Element) -> T)) -> [T] {

View File

@ -100,8 +100,9 @@ extension File {
internal func matchesAndSyntaxKinds(matching pattern: String, internal func matchesAndSyntaxKinds(matching pattern: String,
range: NSRange? = nil) -> [(NSTextCheckingResult, [SyntaxKind])] { range: NSRange? = nil) -> [(NSTextCheckingResult, [SyntaxKind])] {
return matchesAndTokens(matching: pattern, range: range).map { textCheckingResult, tokens in return matchesAndTokens(matching: pattern, range: range).map { textCheckingResultAndTokens in
(textCheckingResult, tokens.flatMap { SyntaxKind(rawValue: $0.type) }) let (textCheckingResult, tokens) = textCheckingResultAndTokens
return (textCheckingResult, tokens.flatMap { SyntaxKind(rawValue: $0.type) })
} }
} }
@ -111,8 +112,9 @@ extension File {
} }
internal func match(pattern: String, range: NSRange? = nil) -> [(NSRange, [SyntaxKind])] { internal func match(pattern: String, range: NSRange? = nil) -> [(NSRange, [SyntaxKind])] {
return matchesAndSyntaxKinds(matching: pattern, range: range).map { textCheckingResult, syntaxKinds in return matchesAndSyntaxKinds(matching: pattern, range: range).map { textCheckingResultAndKinds in
(textCheckingResult.range, syntaxKinds) let (textCheckingResult, syntaxKinds) = textCheckingResultAndKinds
return (textCheckingResult.range, syntaxKinds)
} }
} }
@ -279,8 +281,10 @@ extension File {
internal func correct<R: Rule>(legacyRule: R, patterns: [String: String]) -> [Correction] { internal func correct<R: Rule>(legacyRule: R, patterns: [String: String]) -> [Correction] {
typealias RangePatternTemplate = (NSRange, String, String) typealias RangePatternTemplate = (NSRange, String, String)
let matches: [RangePatternTemplate] let matches: [RangePatternTemplate]
matches = patterns.flatMap({ pattern, template -> [RangePatternTemplate] in matches = patterns.flatMap({ arg -> [RangePatternTemplate] in
return match(pattern: pattern).filter { range, kinds in let (pattern, template) = arg
return match(pattern: pattern).filter { arg -> Bool in
let (range, kinds) = arg
return kinds.first == .identifier && return kinds.first == .identifier &&
!ruleEnabled(violatingRanges: [range], for: legacyRule).isEmpty !ruleEnabled(violatingRanges: [range], for: legacyRule).isEmpty
}.map { ($0.0, pattern, template) } }.map { ($0.0, pattern, template) }

View File

@ -12,8 +12,10 @@ import Foundation
#if !swift(>=3.1) #if !swift(>=3.1)
public typealias NSRegularExpression = RegularExpression public typealias NSRegularExpression = RegularExpression
#endif #endif
#if !swift(>=4.0)
public typealias NSTextCheckingResult = TextCheckingResult public typealias NSTextCheckingResult = TextCheckingResult
#endif #endif
#endif
private var regexCache = [RegexCacheKey: NSRegularExpression]() private var regexCache = [RegexCacheKey: NSRegularExpression]()
private let regexCacheLock = NSLock() private let regexCacheLock = NSLock()

View File

@ -294,12 +294,14 @@ private func warnAboutDeprecations(configurationDictionary dict: [String: Any],
} }
// Deprecation warning for rules // Deprecation warning for rules
let deprecatedRulesIdentifiers = ruleList.list.flatMap { (identifier, rule) -> [(String, String)] in let deprecatedRulesIdentifiers = ruleList.list.flatMap { arg -> [(String, String)] in
let (identifier, rule) = arg
return rule.description.deprecatedAliases.map { ($0, identifier) } return rule.description.deprecatedAliases.map { ($0, identifier) }
} }
let userProvidedRuleIDs = Set(disabledRules + optInRules + whitelistRules) let userProvidedRuleIDs = Set(disabledRules + optInRules + whitelistRules)
let deprecatedUsages = deprecatedRulesIdentifiers.filter { deprecatedIdentifier, _ in let deprecatedUsages = deprecatedRulesIdentifiers.filter { arg -> Bool in
let (deprecatedIdentifier, _) = arg
return dict[deprecatedIdentifier] != nil || userProvidedRuleIDs.contains(deprecatedIdentifier) return dict[deprecatedIdentifier] != nil || userProvidedRuleIDs.contains(deprecatedIdentifier)
} }

View File

@ -36,12 +36,14 @@ extension Rule {
let (disabledViolationsAndRegions, enabledViolationsAndRegions) = violations.map { violation in let (disabledViolationsAndRegions, enabledViolationsAndRegions) = violations.map { violation in
return (violation, regions.first(where: { $0.contains(violation.location) })) return (violation, regions.first(where: { $0.contains(violation.location) }))
}.partitioned { _, region in }.partitioned { arg -> Bool in
let (_, region) = arg
return region?.isRuleEnabled(self) ?? true return region?.isRuleEnabled(self) ?? true
} }
let enabledViolations = enabledViolationsAndRegions.map { $0.0 } let enabledViolations = enabledViolationsAndRegions.map { $0.0 }
let deprecatedToValidIDPairs = disabledViolationsAndRegions.flatMap { _, region -> [(String, String)] in let deprecatedToValidIDPairs = disabledViolationsAndRegions.flatMap { arg -> [(String, String)] in
let (_, region) = arg
let identifiers = region?.deprecatedAliasesDisabling(rule: self) ?? [] let identifiers = region?.deprecatedAliasesDisabling(rule: self) ?? []
return identifiers.map { ($0, type(of: self).description.identifier) } return identifiers.map { ($0, type(of: self).description.identifier) }
} }

View File

@ -67,8 +67,9 @@ public struct RuleList {
} }
internal func allValidIdentifiers() -> [String] { internal func allValidIdentifiers() -> [String] {
return list.flatMap { (_, rule) -> [String] in return list.flatMap { arg -> [String] in
rule.description.allIdentifiers let (_, rule) = arg
return rule.description.allIdentifiers
} }
} }
} }

View File

@ -18,6 +18,6 @@ public struct RuleParameter<T: Equatable>: Equatable {
// MARK: - Equatable // MARK: - Equatable
public func ==<T: Equatable>(lhs: RuleParameter<T>, rhs: RuleParameter<T>) -> Bool { public func ==<T> (lhs: RuleParameter<T>, rhs: RuleParameter<T>) -> Bool {
return lhs.value == rhs.value && lhs.severity == rhs.severity return lhs.value == rhs.value && lhs.severity == rhs.severity
} }

View File

@ -64,7 +64,7 @@ public extension ConfigurationProviderRule {
public func == (lhs: [Rule], rhs: [Rule]) -> Bool { public func == (lhs: [Rule], rhs: [Rule]) -> Bool {
if lhs.count == rhs.count { if lhs.count == rhs.count {
return zip(lhs, rhs).map { $0.isEqualTo($1) }.reduce(true) { $0 && $1 } return zip(lhs, rhs).map { $0.0.isEqualTo($0.1) }.reduce(true) { $0 && $1 }
} }
return false return false

View File

@ -22,7 +22,7 @@ public struct CheckstyleReporter: Reporter {
violations violations
.group(by: { ($0.location.file ?? "<nopath>").escapedForXML() }) .group(by: { ($0.location.file ?? "<nopath>").escapedForXML() })
.sorted(by: { $0.key < $1.key }) .sorted(by: { $0.key < $1.key })
.map(generateForViolationFile).joined(), .map({ generateForViolationFile($0.0, violations: $0.1) }).joined(),
"\n</checkstyle>" "\n</checkstyle>"
].joined() ].joined()
} }

View File

@ -20,7 +20,8 @@ public struct EmojiReporter: Reporter {
return violations return violations
.group(by: { $0.location.file ?? "Other" }) .group(by: { $0.location.file ?? "Other" })
.sorted(by: { $0.key < $1.key }) .sorted(by: { $0.key < $1.key })
.map(report).joined(separator: "\n") .map({ report(for: $0.0, with: $0.1) })
.joined(separator: "\n")
} }
private static func report(for file: String, with violations: [StyleViolation]) -> String { private static func report(for file: String, with violations: [StyleViolation]) -> String {

View File

@ -61,7 +61,8 @@ public struct AttributesRule: ASTRule, OptInRule, ConfigurationProviderRule {
private func validateTestableImport(file: File) -> [StyleViolation] { private func validateTestableImport(file: File) -> [StyleViolation] {
let pattern = "@testable[\n]+\\s*import" let pattern = "@testable[\n]+\\s*import"
return file.match(pattern: pattern).flatMap { range, kinds -> StyleViolation? in return file.match(pattern: pattern).flatMap { arg -> StyleViolation? in
let (range, kinds) = arg
guard kinds == [.attributeBuiltin, .keyword] else { guard kinds == [.attributeBuiltin, .keyword] else {
return nil return nil
} }
@ -149,18 +150,20 @@ public struct AttributesRule: ASTRule, OptInRule, ConfigurationProviderRule {
attributesTokens: [(String, NSRange)], attributesTokens: [(String, NSRange)],
line: Line, file: File) -> Set<String> { line: Line, file: File) -> Set<String> {
let attributesTokensWithParameters: [(String, Bool)] = attributesTokens.map { let attributesTokensWithParameters: [(String, Bool)] = attributesTokens.map {
let hasParameter = attributeContainsParameter(attributeRange: $1, let hasParameter = attributeContainsParameter(attributeRange: $0.1,
line: line, file: file) line: line, file: file)
return ($0, hasParameter) return ($0.0, hasParameter)
} }
let allAttributes = previousAttributes + attributesTokensWithParameters let allAttributes = previousAttributes + attributesTokensWithParameters
return Set(allAttributes.flatMap { (token, hasParameter) -> String? in return Set(allAttributes.flatMap { arg -> String? in
// an attribute should be on a new line if one of these is true: // an attribute should be on a new line if one of these is true:
// 1. it's a parameterized attribute // 1. it's a parameterized attribute
// a. the parameter is on the token (i.e. warn_unused_result) // a. the parameter is on the token (i.e. warn_unused_result)
// b. the parameter was parsed in the `hasParameter` variable (most attributes) // b. the parameter was parsed in the `hasParameter` variable (most attributes)
// 2. it's a whitelisted attribute, according to the current configuration // 2. it's a whitelisted attribute, according to the current configuration
let (token, hasParameter) = arg
let isParameterized = hasParameter || token.bridge().contains("(") let isParameterized = hasParameter || token.bridge().contains("(")
if isParameterized || configuration.alwaysOnNewLine.contains(token) { if isParameterized || configuration.alwaysOnNewLine.contains(token) {
return token return token

View File

@ -195,13 +195,15 @@ extension ColonRule {
fileprivate func typeColonViolationRanges(in file: File, matching pattern: String) -> [NSRange] { fileprivate func typeColonViolationRanges(in file: File, matching pattern: String) -> [NSRange] {
let nsstring = file.contents.bridge() let nsstring = file.contents.bridge()
let commentAndStringKindsSet = Set(SyntaxKind.commentAndStringKinds()) let commentAndStringKindsSet = Set(SyntaxKind.commentAndStringKinds())
return file.rangesAndTokens(matching: pattern).filter { _, syntaxTokens in return file.rangesAndTokens(matching: pattern).filter { arg in
let (_, syntaxTokens) = arg
let syntaxKinds = syntaxTokens.flatMap { SyntaxKind(rawValue: $0.type) } let syntaxKinds = syntaxTokens.flatMap { SyntaxKind(rawValue: $0.type) }
if !syntaxKinds.starts(with: [.identifier, .typeidentifier]) { if !syntaxKinds.starts(with: [.identifier, .typeidentifier]) {
return false return false
} }
return Set(syntaxKinds).intersection(commentAndStringKindsSet).isEmpty return Set(syntaxKinds).intersection(commentAndStringKindsSet).isEmpty
}.flatMap { range, syntaxTokens in }.flatMap { arg in
let (range, syntaxTokens) = arg
let identifierRange = nsstring let identifierRange = nsstring
.byteRangeToNSRange(start: syntaxTokens[0].offset, length: 0) .byteRangeToNSRange(start: syntaxTokens[0].offset, length: 0)
return identifierRange.map { NSUnionRange($0, range) } return identifierRange.map { NSUnionRange($0, range) }
@ -281,10 +283,11 @@ extension ColonRule {
return NSRange(location: offset, length: length) return NSRange(location: offset, length: length)
} }
let even = ranges.enumerated().flatMap { $0 % 2 == 0 ? $1 : nil } let even = ranges.enumerated().flatMap { $0.0 % 2 == 0 ? $0.1 : nil }
let odd = ranges.enumerated().flatMap { $0 % 2 != 0 ? $1 : nil } let odd = ranges.enumerated().flatMap { $0.0 % 2 != 0 ? $0.1 : nil }
return zip(even, odd).map { evenRange, oddRange -> NSRange in return zip(even, odd).map { evenOdd -> NSRange in
let (evenRange, oddRange) = evenOdd
let location = NSMaxRange(evenRange) let location = NSMaxRange(evenRange)
let length = oddRange.location - location let length = oddRange.location - location

View File

@ -38,7 +38,8 @@ public struct ConditionalReturnsOnNewlineRule: ConfigurationProviderRule, Rule,
public func validate(file: File) -> [StyleViolation] { public func validate(file: File) -> [StyleViolation] {
let pattern = "(guard|if)[^\n]*return" let pattern = "(guard|if)[^\n]*return"
return file.rangesAndTokens(matching: pattern).filter { _, tokens in return file.rangesAndTokens(matching: pattern).filter { arg in
let (_, tokens) = arg
guard let firstToken = tokens.first, let lastToken = tokens.last, guard let firstToken = tokens.first, let lastToken = tokens.last,
SyntaxKind(rawValue: firstToken.type) == .keyword && SyntaxKind(rawValue: firstToken.type) == .keyword &&
SyntaxKind(rawValue: lastToken.type) == .keyword else { SyntaxKind(rawValue: lastToken.type) == .keyword else {

View File

@ -61,7 +61,8 @@ public struct ControlStatementRule: ConfigurationProviderRule {
let pattern = statementKind == "guard" let pattern = statementKind == "guard"
? "\(statementKind)\\s*\\([^,{]*\\)\\s*else\\s*\\{" ? "\(statementKind)\\s*\\([^,{]*\\)\\s*else\\s*\\{"
: "\(statementKind)\\s*\\([^,{]*\\)\\s*\\{" : "\(statementKind)\\s*\\([^,{]*\\)\\s*\\{"
return file.match(pattern: pattern).flatMap { match, syntaxKinds in return file.match(pattern: pattern).flatMap { arg in
let (match, syntaxKinds) = arg
let matchString = file.contents.substring(from: match.location, length: match.length) let matchString = file.contents.substring(from: match.location, length: match.length)
if isFalsePositive(matchString, syntaxKind: syntaxKinds.first) { if isFalsePositive(matchString, syntaxKind: syntaxKinds.first) {
return nil return nil

View File

@ -67,7 +67,8 @@ public struct EmptyEnumArgumentsRule: ASTRule, ConfigurationProviderRule, Correc
return [] return []
} }
return file.match(pattern: "\\([,\\s_]*\\)", range: caseRange).flatMap { range, kinds in return file.match(pattern: "\\([,\\s_]*\\)", range: caseRange).flatMap { arg in
let (range, kinds) = arg
guard Set(kinds).isSubset(of: [.keyword]), guard Set(kinds).isSubset(of: [.keyword]),
case let byteRange = NSRange(location: offset, length: length), case let byteRange = NSRange(location: offset, length: length),
Set(file.syntaxMap.kinds(inByteRange: byteRange)) != [.keyword] else { Set(file.syntaxMap.kinds(inByteRange: byteRange)) != [.keyword] else {

View File

@ -102,8 +102,14 @@ public struct FunctionParameterCountRule: ASTRule, ConfigurationProviderRule {
} }
fileprivate func defaultFunctionParameterCount(file: File, byteOffset: Int, byteLength: Int) -> Int { fileprivate func defaultFunctionParameterCount(file: File, byteOffset: Int, byteLength: Int) -> Int {
return file.contents.bridge().substringWithByteRange(start: byteOffset, length: byteLength)? guard let characters = file.contents.bridge().substringWithByteRange(start: byteOffset, length: byteLength)?
.characters.filter { $0 == "=" }.count ?? 0 .characters else {
return 0
}
let equals: [Character] = characters.filter { char -> Bool in
return char == "="
}
return equals.count
} }
fileprivate func functionIsInitializer(file: File, byteOffset: Int, byteLength: Int) -> Bool { fileprivate func functionIsInitializer(file: File, byteOffset: Int, byteLength: Int) -> Bool {

View File

@ -77,7 +77,8 @@ public struct GenericTypeNameRule: ASTRule, ConfigurationProviderRule {
private func validateGenericTypeAliases(in file: File) -> [StyleViolation] { private func validateGenericTypeAliases(in file: File) -> [StyleViolation] {
let pattern = "typealias\\s+\\w+?\\s*" + genericTypePattern + "\\s*=" let pattern = "typealias\\s+\\w+?\\s*" + genericTypePattern + "\\s*="
return file.match(pattern: pattern).flatMap { (range, tokens) -> [(String, Int)] in return file.match(pattern: pattern).flatMap { arg -> [(String, Int)] in
let (range, tokens) = arg
guard tokens.first == .keyword, guard tokens.first == .keyword,
Set(tokens.dropFirst()) == [.identifier], Set(tokens.dropFirst()) == [.identifier],
let match = genericTypeRegex.firstMatch(in: file.contents, options: [], let match = genericTypeRegex.firstMatch(in: file.contents, options: [],
@ -139,7 +140,9 @@ public struct GenericTypeNameRule: ASTRule, ConfigurationProviderRule {
return [] return []
} }
let namesAndRanges: [(String, NSRange)] = beforeWhere.split(separator: ",").flatMap { string, range in let namesAndRanges: [(String, NSRange)] = beforeWhere.split(separator: ",")
.flatMap { arg -> (String, NSRange)? in
let (string, range) = arg
return string.split(separator: ":").first.map { return string.split(separator: ":").first.map {
let (trimmed, trimmedRange) = $0.0.trimmingWhitespaces() let (trimmed, trimmedRange) = $0.0.trimmingWhitespaces()
return (trimmed, NSRange(location: range.location + trimmedRange.location, return (trimmed, NSRange(location: range.location + trimmedRange.location,
@ -148,7 +151,8 @@ public struct GenericTypeNameRule: ASTRule, ConfigurationProviderRule {
} }
let contents = file.contents.bridge() let contents = file.contents.bridge()
return namesAndRanges.flatMap { (name, range) -> (String, Int)? in return namesAndRanges.flatMap { arg -> (String, Int)? in
let (name, range) = arg
guard let byteRange = contents.NSRangeToByteRange(start: range.location + offset, guard let byteRange = contents.NSRangeToByteRange(start: range.location + offset,
length: range.length), length: range.length),
file.syntaxMap.kinds(inByteRange: byteRange) == [.identifier] else { file.syntaxMap.kinds(inByteRange: byteRange) == [.identifier] else {

View File

@ -37,13 +37,14 @@ public struct IdentifierNameRule: ASTRule, ConfigurationProviderRule {
return [] return []
} }
return validateName(dictionary: dictionary, kind: kind).map { name, offset in return validateName(dictionary: dictionary, kind: kind).map { nameAndOffset in
let (name, offset) = nameAndOffset
guard !configuration.excluded.contains(name) else { guard !configuration.excluded.contains(name) else {
return [] return []
} }
let isFunction = SwiftDeclarationKind.functionKinds().contains(kind) let isFunction = SwiftDeclarationKind.functionKinds().contains(kind)
let description = type(of: self).description let description = Swift.type(of: self).description
let type = self.type(for: kind) let type = self.type(for: kind)
if !isFunction { if !isFunction {
@ -64,7 +65,7 @@ public struct IdentifierNameRule: ASTRule, ConfigurationProviderRule {
"\(configuration.minLengthThreshold) and " + "\(configuration.minLengthThreshold) and " +
"\(configuration.maxLengthThreshold) characters long: '\(name)'" "\(configuration.maxLengthThreshold) characters long: '\(name)'"
return [ return [
StyleViolation(ruleDescription: type(of: self).description, StyleViolation(ruleDescription: Swift.type(of: self).description,
severity: severity, severity: severity,
location: Location(file: file, byteOffset: offset), location: Location(file: file, byteOffset: offset),
reason: reason) reason: reason)

View File

@ -54,7 +54,8 @@ public struct ImplicitGetterRule: ConfigurationProviderRule {
public func validate(file: File) -> [StyleViolation] { public func validate(file: File) -> [StyleViolation] {
let pattern = "\\bget\\b" let pattern = "\\bget\\b"
let getTokens: [SyntaxToken] = file.rangesAndTokens(matching: pattern).flatMap { _, tokens in let getTokens: [SyntaxToken] = file.rangesAndTokens(matching: pattern).flatMap { arg in
let (_, tokens) = arg
guard tokens.count == 1, let token = tokens.first, guard tokens.count == 1, let token = tokens.first,
SyntaxKind(rawValue: token.type) == .keyword else { SyntaxKind(rawValue: token.type) == .keyword else {
return nil return nil

View File

@ -68,7 +68,8 @@ public struct ImplicitReturnRule: ConfigurationProviderRule, CorrectableRule, Op
let pattern = "(?:\\bin|\\{)\\s+(return\\s+)" let pattern = "(?:\\bin|\\{)\\s+(return\\s+)"
let contents = file.contents.bridge() let contents = file.contents.bridge()
return file.matchesAndSyntaxKinds(matching: pattern).flatMap { result, kinds in return file.matchesAndSyntaxKinds(matching: pattern).flatMap { arg in
let (result, kinds) = arg
let range = result.range let range = result.range
guard kinds == [.keyword, .keyword] || kinds == [.keyword], guard kinds == [.keyword, .keyword] || kinds == [.keyword],
let byteRange = contents.NSRangeToByteRange(start: range.location, let byteRange = contents.NSRangeToByteRange(start: range.location,

View File

@ -64,7 +64,8 @@ public struct LargeTupleRule: ASTRule, ConfigurationProviderRule {
let offsets = violationOffsetsForTypes(in: file, dictionary: dictionary, kind: kind) + let offsets = violationOffsetsForTypes(in: file, dictionary: dictionary, kind: kind) +
violationOffsetsForFunctions(in: file, dictionary: dictionary, kind: kind) violationOffsetsForFunctions(in: file, dictionary: dictionary, kind: kind)
return offsets.flatMap { location, size in return offsets.flatMap { arg in
let (location, size) = arg
for parameter in configuration.params where size > parameter.value { for parameter in configuration.params where size > parameter.value {
let reason = "Tuples should have at most \(configuration.warning) members." let reason = "Tuples should have at most \(configuration.warning) members."
return StyleViolation(ruleDescription: type(of: self).description, return StyleViolation(ruleDescription: type(of: self).description,

View File

@ -45,7 +45,8 @@ public struct LegacyConstantRule: CorrectableRule, ConfigurationProviderRule {
public func correct(file: File) -> [Correction] { public func correct(file: File) -> [Correction] {
var wordBoundPatterns: [String: String] = [:] var wordBoundPatterns: [String: String] = [:]
LegacyConstantRule.legacyPatterns.forEach { key, value in LegacyConstantRule.legacyPatterns.forEach { arg in
let (key, value) = arg
wordBoundPatterns["\\b" + key] = value wordBoundPatterns["\\b" + key] = value
} }

View File

@ -150,9 +150,11 @@ public struct MarkRule: CorrectableRule, ConfigurationProviderRule {
private func violationRanges(in file: File, matching pattern: String) -> [NSRange] { private func violationRanges(in file: File, matching pattern: String) -> [NSRange] {
let nsstring = file.contents.bridge() let nsstring = file.contents.bridge()
return file.rangesAndTokens(matching: pattern).filter { _, syntaxTokens in return file.rangesAndTokens(matching: pattern).filter { arg -> Bool in
let (_, syntaxTokens) = arg
return !syntaxTokens.isEmpty && SyntaxKind(rawValue: syntaxTokens[0].type) == .comment return !syntaxTokens.isEmpty && SyntaxKind(rawValue: syntaxTokens[0].type) == .comment
}.flatMap { range, syntaxTokens in }.flatMap { arg in
let (range, syntaxTokens) = arg
let identifierRange = nsstring let identifierRange = nsstring
.byteRangeToNSRange(start: syntaxTokens[0].offset, length: 0) .byteRangeToNSRange(start: syntaxTokens[0].offset, length: 0)
return identifierRange.map { NSUnionRange($0, range) } return identifierRange.map { NSUnionRange($0, range) }

View File

@ -57,14 +57,17 @@ public struct NestingRule: ASTRule, ConfigurationProviderRule {
reason: "\(targetName) should be nested at most \(threshold) level\(pluralSuffix) deep")) reason: "\(targetName) should be nested at most \(threshold) level\(pluralSuffix) deep"))
} }
} }
violations.append(contentsOf: dictionary.substructure.flatMap { subDict in violations.append(contentsOf: dictionary.substructure
.flatMap { subDict -> [(SwiftDeclarationKind, [String: SourceKitRepresentable])] in
if let kind = (subDict.kind).flatMap(SwiftDeclarationKind.init) { if let kind = (subDict.kind).flatMap(SwiftDeclarationKind.init) {
return (kind, subDict) return [(kind, subDict)]
} }
return nil return []
}.flatMap { kind, subDict in }.flatMap { kindAndSubdict -> [StyleViolation] in
let (kind, subDict) = kindAndSubdict
return validate(file: file, kind: kind, dictionary: subDict, level: level + 1) return validate(file: file, kind: kind, dictionary: subDict, level: level + 1)
}) }
)
return violations return violations
} }
} }

View File

@ -88,8 +88,9 @@ public struct NimbleOperatorRule: ConfigurationProviderRule, OptInRule, Correcta
let excludingKinds = SyntaxKind.commentKinds() let excludingKinds = SyntaxKind.commentKinds()
return file.match(pattern: pattern) return file.match(pattern: pattern)
.filter { _, kinds in .filter { arg -> Bool in
kinds.filter(excludingKinds.contains).isEmpty && kinds.first == .identifier let (_, kinds) = arg
return kinds.filter(excludingKinds.contains).isEmpty && kinds.first == .identifier
}.map { $0.0 } }.map { $0.0 }
} }

View File

@ -24,7 +24,8 @@ public struct NumberSeparatorRule: OptInRule, CorrectableRule, ConfigurationProv
) )
public func validate(file: File) -> [StyleViolation] { public func validate(file: File) -> [StyleViolation] {
return violatingRanges(in: file).map { range, _ in return violatingRanges(in: file).map { rangeAndThing in
let (range, _) = rangeAndThing
return StyleViolation(ruleDescription: type(of: self).description, return StyleViolation(ruleDescription: type(of: self).description,
severity: configuration.severityConfiguration.severity, severity: configuration.severityConfiguration.severity,
location: Location(file: file, characterOffset: range.location)) location: Location(file: file, characterOffset: range.location))
@ -86,7 +87,8 @@ public struct NumberSeparatorRule: OptInRule, CorrectableRule, ConfigurationProv
} }
public func correct(file: File) -> [Correction] { public func correct(file: File) -> [Correction] {
let violatingRanges = self.violatingRanges(in: file).filter { range, _ in let violatingRanges = self.violatingRanges(in: file).filter { arg -> Bool in
let (range, _) = arg
return !file.ruleEnabled(violatingRanges: [range], for: self).isEmpty return !file.ruleEnabled(violatingRanges: [range], for: self).isEmpty
} }

View File

@ -101,7 +101,7 @@ public struct OpeningBraceRule: CorrectableRule, ConfigurationProviderRule {
guard let indexRange = contents.nsrangeToIndexRange(violatingRange) else { guard let indexRange = contents.nsrangeToIndexRange(violatingRange) else {
return (contents, nil) return (contents, nil)
} }
let capturedString = contents[indexRange] let capturedString = String(contents[indexRange])
var adjustedRange = violatingRange var adjustedRange = violatingRange
var correctString = " {" var correctString = " {"

View File

@ -40,9 +40,11 @@ public struct OperatorFunctionWhitespaceRule: ConfigurationProviderRule {
let zeroOrManySpaces = "(\\s{0}|\\s{2,})" let zeroOrManySpaces = "(\\s{0}|\\s{2,})"
let pattern1 = "func\\s+[\(operators)]+\(zeroOrManySpaces)(<[A-Z]+>)?\\(" let pattern1 = "func\\s+[\(operators)]+\(zeroOrManySpaces)(<[A-Z]+>)?\\("
let pattern2 = "func\(zeroOrManySpaces)[\(operators)]+\\s+(<[A-Z]+>)?\\(" let pattern2 = "func\(zeroOrManySpaces)[\(operators)]+\\s+(<[A-Z]+>)?\\("
return file.match(pattern: "(\(pattern1)|\(pattern2))").filter { _, syntaxKinds in return file.match(pattern: "(\(pattern1)|\(pattern2))").filter { arg -> Bool in
let (_, syntaxKinds) = arg
return syntaxKinds.first == .keyword return syntaxKinds.first == .keyword
}.map { range, _ in }.map { arg in
let (range, _) = arg
return StyleViolation(ruleDescription: type(of: self).description, return StyleViolation(ruleDescription: type(of: self).description,
severity: configuration.severity, severity: configuration.severity,
location: Location(file: file, characterOffset: range.location)) location: Location(file: file, characterOffset: range.location))

View File

@ -74,8 +74,9 @@ public struct OperatorUsageWhitespaceRule: OptInRule, CorrectableRule, Configura
) )
public func validate(file: File) -> [StyleViolation] { public func validate(file: File) -> [StyleViolation] {
return violationRanges(file: file).map { range, _ in return violationRanges(file: file).map { rangeAndString in
StyleViolation(ruleDescription: type(of: self).description, let (range, _) = rangeAndString
return StyleViolation(ruleDescription: type(of: self).description,
severity: configuration.severity, severity: configuration.severity,
location: Location(file: file, characterOffset: range.location)) location: Location(file: file, characterOffset: range.location))
} }
@ -98,8 +99,9 @@ public struct OperatorUsageWhitespaceRule: OptInRule, CorrectableRule, Configura
let spaces = [(zeroSpaces, zeroSpaces), (oneSpace, manySpaces), let spaces = [(zeroSpaces, zeroSpaces), (oneSpace, manySpaces),
(manySpaces, oneSpace), (manySpaces, manySpaces)] (manySpaces, oneSpace), (manySpaces, manySpaces)]
let patterns = spaces.map { first, second in let patterns = spaces.map { arg -> String in
leadingVariableOrNumber + first + operators + second + trailingVariableOrNumber let (first, second) = arg
return leadingVariableOrNumber + first + operators + second + trailingVariableOrNumber
} }
let pattern = "(?:\(patterns.joined(separator: "|")))" let pattern = "(?:\(patterns.joined(separator: "|")))"
@ -156,7 +158,8 @@ public struct OperatorUsageWhitespaceRule: OptInRule, CorrectableRule, Configura
} }
public func correct(file: File) -> [Correction] { public func correct(file: File) -> [Correction] {
let violatingRanges = violationRanges(file: file).filter { range, _ in let violatingRanges = violationRanges(file: file).filter { arg -> Bool in
let (range, _) = arg
return !file.ruleEnabled(violatingRanges: [range], for: self).isEmpty return !file.ruleEnabled(violatingRanges: [range], for: self).isEmpty
} }

View File

@ -43,7 +43,8 @@ public struct SortedImportsRule: ConfigurationProviderRule, OptInRule {
} }
let modulePairs = zip(modulesAndOffsets, modulesAndOffsets.dropFirst()) let modulePairs = zip(modulesAndOffsets, modulesAndOffsets.dropFirst())
let violatingOffsets = modulePairs.flatMap { previous, current in let violatingOffsets = modulePairs.flatMap { arg -> Int? in
let (previous, current) = arg
return current < previous ? current.1 : nil return current < previous ? current.1 : nil
} }

View File

@ -107,7 +107,8 @@ private extension StatementPositionRule {
} }
func defaultViolationRanges(in file: File, matching pattern: String) -> [NSRange] { func defaultViolationRanges(in file: File, matching pattern: String) -> [NSRange] {
return file.match(pattern: pattern).filter { _, syntaxKinds in return file.match(pattern: pattern).filter { arg -> Bool in
let (_, syntaxKinds) = arg
return syntaxKinds.starts(with: [.keyword]) return syntaxKinds.starts(with: [.keyword])
}.flatMap { $0.0 } }.flatMap { $0.0 }
} }

View File

@ -86,7 +86,8 @@ public struct TodoRule: ConfigurationProviderRule {
} }
public func validate(file: File) -> [StyleViolation] { public func validate(file: File) -> [StyleViolation] {
return file.match(pattern: "\\b(?:TODO|FIXME)(?::|\\b)").flatMap { range, syntaxKinds in return file.match(pattern: "\\b(?:TODO|FIXME)(?::|\\b)").flatMap { rangeAndKinds in
let (range, syntaxKinds) = rangeAndKinds
if !syntaxKinds.filter({ !$0.isCommentLike }).isEmpty { if !syntaxKinds.filter({ !$0.isCommentLike }).isEmpty {
return nil return nil
} }

View File

@ -48,7 +48,8 @@ public struct TypeNameRule: ASTRule, ConfigurationProviderRule {
private func validateTypeAliasesAndAssociatedTypes(in file: File) -> [StyleViolation] { private func validateTypeAliasesAndAssociatedTypes(in file: File) -> [StyleViolation] {
let rangesAndTokens = file.rangesAndTokens(matching: "(typealias|associatedtype)\\s+.+?\\b") let rangesAndTokens = file.rangesAndTokens(matching: "(typealias|associatedtype)\\s+.+?\\b")
return rangesAndTokens.flatMap { _, tokens -> [StyleViolation] in return rangesAndTokens.flatMap { arg -> [StyleViolation] in
let (_, tokens) = arg
guard tokens.count == 2, guard tokens.count == 2,
let keywordToken = tokens.first, let keywordToken = tokens.first,
let nameToken = tokens.last, let nameToken = tokens.last,

View File

@ -80,7 +80,8 @@ public struct UnusedClosureParameterRule: ASTRule, ConfigurationProviderRule, Co
public func validate(file: File, kind: SwiftExpressionKind, public func validate(file: File, kind: SwiftExpressionKind,
dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] { dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
return violationRanges(in: file, dictionary: dictionary, kind: kind).map { range, name in return violationRanges(in: file, dictionary: dictionary, kind: kind).map { rangeName in
let (range, name) = rangeName
let reason = "Unused parameter \"\(name)\" in a closure should be replaced with _." let reason = "Unused parameter \"\(name)\" in a closure should be replaced with _."
return StyleViolation(ruleDescription: type(of: self).description, return StyleViolation(ruleDescription: type(of: self).description,
severity: configuration.severity, severity: configuration.severity,

View File

@ -115,7 +115,7 @@ public struct ValidIBInspectableRule: ASTRule, ConfigurationProviderRule {
"NSRect" "NSRect"
] ]
let intTypes = ["", "8", "16", "32", "64"].flatMap { size in let intTypes: [String] = ["", "8", "16", "32", "64"].flatMap { size in
["U", ""].flatMap { (sign: String) -> String in ["U", ""].flatMap { (sign: String) -> String in
"\(sign)Int\(size)" "\(sign)Int\(size)"
} }

View File

@ -37,7 +37,7 @@ struct AutoCorrectCommand: CommandProtocol {
if !options.quiet { if !options.quiet {
queuedPrintError("Done correcting \(files.count) files!") queuedPrintError("Done correcting \(files.count) files!")
} }
return .success() return .success(())
} }
} }
} }

View File

@ -33,7 +33,7 @@ struct LintCommand: CommandProtocol {
currentViolations = LintCommand.applyLeniency(options: options, violations: _currentViolations) currentViolations = LintCommand.applyLeniency(options: options, violations: _currentViolations)
visitorMutationQueue.sync { visitorMutationQueue.sync {
fileBenchmark.record(file: linter.file, from: start) fileBenchmark.record(file: linter.file, from: start)
currentRuleTimes.forEach { ruleBenchmark.record(id: $0, time: $1) } currentRuleTimes.forEach { ruleBenchmark.record(id: $0.0, time: $0.1) }
violations += currentViolations violations += currentViolations
} }
} else { } else {
@ -73,7 +73,7 @@ struct LintCommand: CommandProtocol {
} else if strictWithViolations { } else if strictWithViolations {
exit(3) exit(3)
} }
return .success() return .success(())
} }
private static func printStatus(violations: [StyleViolation], files: [File], serious: Int) { private static func printStatus(violations: [StyleViolation], files: [File], serious: Int) {

View File

@ -38,14 +38,14 @@ struct RulesCommand: CommandProtocol {
} }
print(ruleDescription: rule.description) print(ruleDescription: rule.description)
return .success() return .success(())
} }
let configuration = Configuration(commandLinePath: options.configurationFile) let configuration = Configuration(commandLinePath: options.configurationFile)
let rules = ruleList(for: options, configuration: configuration) let rules = ruleList(for: options, configuration: configuration)
print(TextTable(ruleList: rules, configuration: configuration).render()) print(TextTable(ruleList: rules, configuration: configuration).render())
return .success() return .success(())
} }
private func ruleList(for options: RulesOptions, configuration: Configuration) -> RuleList { private func ruleList(for options: RulesOptions, configuration: Configuration) -> RuleList {
@ -53,7 +53,8 @@ struct RulesCommand: CommandProtocol {
return masterRuleList return masterRuleList
} }
let filtered: [Rule.Type] = masterRuleList.list.flatMap { ruleID, ruleType in let filtered: [Rule.Type] = masterRuleList.list.flatMap { ruleIDAndType in
let (ruleID, ruleType) = ruleIDAndType
let configuredRule = configuration.rules.first { rule in let configuredRule = configuration.rules.first { rule in
return type(of: rule).description.identifier == ruleID return type(of: rule).description.identifier == ruleID
} }

View File

@ -16,6 +16,6 @@ struct VersionCommand: CommandProtocol {
func run(_ options: NoOptions<CommandantError<()>>) -> Result<(), CommandantError<()>> { func run(_ options: NoOptions<CommandantError<()>>) -> Result<(), CommandantError<()>> {
print(Version.current.value) print(Version.current.value)
return .success() return .success(())
} }
} }

View File

@ -38,7 +38,8 @@ struct Benchmark {
return accu return accu
} }
let entriesKeyValues: [(String, Double)] = entriesDict.sorted { $0.1 < $1.1 } let entriesKeyValues: [(String, Double)] = entriesDict.sorted { $0.1 < $1.1 }
let lines: [String] = entriesKeyValues.map { id, time -> String in let lines: [String] = entriesKeyValues.map { idAndTime -> String in
let (id, time) = idAndTime
return "\(numberFormatter.string(from: NSNumber(value: time))!): \(id)" return "\(numberFormatter.string(from: NSNumber(value: time))!): \(id)"
} }
let string: String = lines.joined(separator: "\n") + "\n" let string: String = lines.joined(separator: "\n") + "\n"

View File

@ -1492,7 +1492,7 @@
FRAMEWORK_VERSION = A; FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Source/SwiftLintFramework/Supporting Files/Info.plist"; INFOPLIST_FILE = "Source/SwiftLintFramework/Supporting Files/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "@loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "@loader_path/Frameworks";
OTHER_SWIFT_FLAGS = "$(inherited) -Xfrontend -warn-long-function-bodies=150"; OTHER_SWIFT_FLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFramework; PRODUCT_NAME = SwiftLintFramework;
SWIFT_VERSION = 3.0; SWIFT_VERSION = 3.0;
@ -1574,7 +1574,7 @@
FRAMEWORK_VERSION = A; FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Source/SwiftLintFramework/Supporting Files/Info.plist"; INFOPLIST_FILE = "Source/SwiftLintFramework/Supporting Files/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "@loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "@loader_path/Frameworks";
OTHER_SWIFT_FLAGS = "$(inherited) -Xfrontend -warn-long-function-bodies=150"; OTHER_SWIFT_FLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFramework; PRODUCT_NAME = SwiftLintFramework;
SWIFT_VERSION = 3.0; SWIFT_VERSION = 3.0;
@ -1620,7 +1620,7 @@
FRAMEWORK_VERSION = A; FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Source/SwiftLintFramework/Supporting Files/Info.plist"; INFOPLIST_FILE = "Source/SwiftLintFramework/Supporting Files/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "@loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "@loader_path/Frameworks";
OTHER_SWIFT_FLAGS = "$(inherited) -Xfrontend -warn-long-function-bodies=150"; OTHER_SWIFT_FLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFramework; PRODUCT_NAME = SwiftLintFramework;
SWIFT_VERSION = 3.0; SWIFT_VERSION = 3.0;

View File

@ -93,7 +93,7 @@ class CustomRulesTests: XCTestCase {
func getCustomRules(_ extraConfig: [String:String] = [:]) -> (RegexConfiguration, CustomRules) { func getCustomRules(_ extraConfig: [String:String] = [:]) -> (RegexConfiguration, CustomRules) {
var config = ["regex": "pattern", var config = ["regex": "pattern",
"match_kinds": "comment"] "match_kinds": "comment"]
extraConfig.forEach { config[$0] = $1 } extraConfig.forEach { config[$0.0] = $0.1 }
var regexConfig = RegexConfiguration(identifier: "custom") var regexConfig = RegexConfiguration(identifier: "custom")
do { do {

View File

@ -191,7 +191,8 @@ extension XCTestCase {
} }
// "disable" commands do not correct // "disable" commands do not correct
ruleDescription.corrections.forEach { before, _ in ruleDescription.corrections.forEach { arg in
let (before, _) = arg
for command in disableCommands { for command in disableCommands {
let beforeDisabled = command + before let beforeDisabled = command + before
let expectedCleaned = cleanedContentsAndMarkerOffsets(from: beforeDisabled).0 let expectedCleaned = cleanedContentsAndMarkerOffsets(from: beforeDisabled).0