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
[submodule "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"]
path = Carthage/Checkouts/Yams
url = https://github.com/jpsim/Yams.git

View File

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

View File

@ -1,3 +1,3 @@
github "Carthage/Commandant" "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 "antitypical/Result" "3.2.2"
github "drmohundro/SWXMLHash" "3.1.0"
github "jpsim/SourceKitten" "0.17.6"
github "jpsim/Yams" "0.3.2"
github "antitypical/Result" "3.2.3"
github "drmohundro/SWXMLHash" "4cb1b72d406b4309aed6e6b2f11f46aa83dacbf7"
github "jpsim/SourceKitten" "6e60ee7d6e9885ad6e674d55a5f540b0e52def09"
github "jpsim/SwiftyTextTable" "15f72002eea8e3b446d104d18225b6a828218d32"
github "jpsim/Yams" "b53284ba4c8bdece9ec8aad2e0010602dac588e9"
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 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 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
let package = Package(
name: "SwiftLint",
targets: [
Target(name: "SwiftLintFramework"),
Target(name: "swiftlint",
dependencies: [
.Target(name: "SwiftLintFramework")
]),
products: [
.executable(name: "swiftlint", targets: ["swiftlint"]),
.library(name: "SwiftLintFramework", targets: ["SwiftLintFramework"])
],
dependencies: [
.Package(url: "https://github.com/jpsim/SourceKitten.git", majorVersion: 0, minor: 17),
.Package(url: "https://github.com/jpsim/Yams.git", majorVersion: 0, minor: 3),
.Package(url: "https://github.com/scottrhoyt/SwiftyTextTable.git", majorVersion: 0, minor: 5),
]
.package(url: "https://github.com/Carthage/Commandant.git", from: "0.12.0"),
.package(url: "https://github.com/jpsim/Yams.git", .branch("master")),
.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
}
func group<U: Hashable>(by transform: (Element) -> U) -> [U: [Element]] {
func group<U>(by transform: (Element) -> U) -> [U: [Element]] {
return reduce([:]) { dictionary, element in
var dictionary = dictionary
let key = transform(element)
@ -52,11 +52,33 @@ extension Array {
}
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] {
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] {

View File

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

View File

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

View File

@ -294,12 +294,14 @@ private func warnAboutDeprecations(configurationDictionary dict: [String: Any],
}
// 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) }
}
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)
}

View File

@ -36,12 +36,14 @@ extension Rule {
let (disabledViolationsAndRegions, enabledViolationsAndRegions) = violations.map { violation in
return (violation, regions.first(where: { $0.contains(violation.location) }))
}.partitioned { _, region in
return region?.isRuleEnabled(self) ?? true
}.partitioned { arg -> Bool in
let (_, region) = arg
return region?.isRuleEnabled(self) ?? true
}
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) ?? []
return identifiers.map { ($0, type(of: self).description.identifier) }
}

View File

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

View File

@ -18,6 +18,6 @@ public struct RuleParameter<T: Equatable>: 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
}

View File

@ -64,7 +64,7 @@ public extension ConfigurationProviderRule {
public func == (lhs: [Rule], rhs: [Rule]) -> Bool {
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

View File

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

View File

@ -20,7 +20,8 @@ public struct EmojiReporter: Reporter {
return violations
.group(by: { $0.location.file ?? "Other" })
.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 {

View File

@ -61,7 +61,8 @@ public struct AttributesRule: ASTRule, OptInRule, ConfigurationProviderRule {
private func validateTestableImport(file: File) -> [StyleViolation] {
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 {
return nil
}
@ -149,18 +150,20 @@ public struct AttributesRule: ASTRule, OptInRule, ConfigurationProviderRule {
attributesTokens: [(String, NSRange)],
line: Line, file: File) -> Set<String> {
let attributesTokensWithParameters: [(String, Bool)] = attributesTokens.map {
let hasParameter = attributeContainsParameter(attributeRange: $1,
let hasParameter = attributeContainsParameter(attributeRange: $0.1,
line: line, file: file)
return ($0, hasParameter)
return ($0.0, hasParameter)
}
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:
// 1. it's a parameterized attribute
// a. the parameter is on the token (i.e. warn_unused_result)
// b. the parameter was parsed in the `hasParameter` variable (most attributes)
// 2. it's a whitelisted attribute, according to the current configuration
let (token, hasParameter) = arg
let isParameterized = hasParameter || token.bridge().contains("(")
if isParameterized || configuration.alwaysOnNewLine.contains(token) {
return token

View File

@ -195,14 +195,16 @@ extension ColonRule {
fileprivate func typeColonViolationRanges(in file: File, matching pattern: String) -> [NSRange] {
let nsstring = file.contents.bridge()
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) }
if !syntaxKinds.starts(with: [.identifier, .typeidentifier]) {
return false
}
return Set(syntaxKinds).intersection(commentAndStringKindsSet).isEmpty
}.flatMap { range, syntaxTokens in
let identifierRange = nsstring
}.flatMap { arg in
let (range, syntaxTokens) = arg
let identifierRange = nsstring
.byteRangeToNSRange(start: syntaxTokens[0].offset, length: 0)
return identifierRange.map { NSUnionRange($0, range) }
}
@ -281,10 +283,11 @@ extension ColonRule {
return NSRange(location: offset, length: length)
}
let even = ranges.enumerated().flatMap { $0 % 2 == 0 ? $1 : nil }
let odd = 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.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 length = oddRange.location - location

View File

@ -38,7 +38,8 @@ public struct ConditionalReturnsOnNewlineRule: ConfigurationProviderRule, Rule,
public func validate(file: File) -> [StyleViolation] {
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,
SyntaxKind(rawValue: firstToken.type) == .keyword &&
SyntaxKind(rawValue: lastToken.type) == .keyword else {

View File

@ -61,7 +61,8 @@ public struct ControlStatementRule: ConfigurationProviderRule {
let pattern = statementKind == "guard"
? "\(statementKind)\\s*\\([^,{]*\\)\\s*else\\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)
if isFalsePositive(matchString, syntaxKind: syntaxKinds.first) {
return nil

View File

@ -67,7 +67,8 @@ public struct EmptyEnumArgumentsRule: ASTRule, ConfigurationProviderRule, Correc
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]),
case let byteRange = NSRange(location: offset, length: length),
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 {
return file.contents.bridge().substringWithByteRange(start: byteOffset, length: byteLength)?
.characters.filter { $0 == "=" }.count ?? 0
guard let characters = file.contents.bridge().substringWithByteRange(start: byteOffset, length: byteLength)?
.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 {

View File

@ -77,7 +77,8 @@ public struct GenericTypeNameRule: ASTRule, ConfigurationProviderRule {
private func validateGenericTypeAliases(in file: File) -> [StyleViolation] {
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,
Set(tokens.dropFirst()) == [.identifier],
let match = genericTypeRegex.firstMatch(in: file.contents, options: [],
@ -139,16 +140,19 @@ public struct GenericTypeNameRule: ASTRule, ConfigurationProviderRule {
return []
}
let namesAndRanges: [(String, NSRange)] = beforeWhere.split(separator: ",").flatMap { string, range in
return string.split(separator: ":").first.map {
let (trimmed, trimmedRange) = $0.0.trimmingWhitespaces()
return (trimmed, NSRange(location: range.location + trimmedRange.location,
length: trimmedRange.length))
let namesAndRanges: [(String, NSRange)] = beforeWhere.split(separator: ",")
.flatMap { arg -> (String, NSRange)? in
let (string, range) = arg
return string.split(separator: ":").first.map {
let (trimmed, trimmedRange) = $0.0.trimmingWhitespaces()
return (trimmed, NSRange(location: range.location + trimmedRange.location,
length: trimmedRange.length))
}
}
}
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,
length: range.length),
file.syntaxMap.kinds(inByteRange: byteRange) == [.identifier] else {

View File

@ -37,13 +37,14 @@ public struct IdentifierNameRule: ASTRule, ConfigurationProviderRule {
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 {
return []
}
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)
if !isFunction {
@ -64,7 +65,7 @@ public struct IdentifierNameRule: ASTRule, ConfigurationProviderRule {
"\(configuration.minLengthThreshold) and " +
"\(configuration.maxLengthThreshold) characters long: '\(name)'"
return [
StyleViolation(ruleDescription: type(of: self).description,
StyleViolation(ruleDescription: Swift.type(of: self).description,
severity: severity,
location: Location(file: file, byteOffset: offset),
reason: reason)

View File

@ -54,7 +54,8 @@ public struct ImplicitGetterRule: ConfigurationProviderRule {
public func validate(file: File) -> [StyleViolation] {
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,
SyntaxKind(rawValue: token.type) == .keyword else {
return nil

View File

@ -68,7 +68,8 @@ public struct ImplicitReturnRule: ConfigurationProviderRule, CorrectableRule, Op
let pattern = "(?:\\bin|\\{)\\s+(return\\s+)"
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
guard kinds == [.keyword, .keyword] || kinds == [.keyword],
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) +
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 {
let reason = "Tuples should have at most \(configuration.warning) members."
return StyleViolation(ruleDescription: type(of: self).description,

View File

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

View File

@ -150,10 +150,12 @@ public struct MarkRule: CorrectableRule, ConfigurationProviderRule {
private func violationRanges(in file: File, matching pattern: String) -> [NSRange] {
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
}.flatMap { range, syntaxTokens in
let identifierRange = nsstring
}.flatMap { arg in
let (range, syntaxTokens) = arg
let identifierRange = nsstring
.byteRangeToNSRange(start: syntaxTokens[0].offset, length: 0)
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"))
}
}
violations.append(contentsOf: dictionary.substructure.flatMap { subDict in
if let kind = (subDict.kind).flatMap(SwiftDeclarationKind.init) {
return (kind, subDict)
violations.append(contentsOf: dictionary.substructure
.flatMap { subDict -> [(SwiftDeclarationKind, [String: SourceKitRepresentable])] in
if let kind = (subDict.kind).flatMap(SwiftDeclarationKind.init) {
return [(kind, subDict)]
}
return []
}.flatMap { kindAndSubdict -> [StyleViolation] in
let (kind, subDict) = kindAndSubdict
return validate(file: file, kind: kind, dictionary: subDict, level: level + 1)
}
return nil
}.flatMap { kind, subDict in
return validate(file: file, kind: kind, dictionary: subDict, level: level + 1)
})
)
return violations
}
}

View File

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

View File

@ -24,7 +24,8 @@ public struct NumberSeparatorRule: OptInRule, CorrectableRule, ConfigurationProv
)
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,
severity: configuration.severityConfiguration.severity,
location: Location(file: file, characterOffset: range.location))
@ -86,7 +87,8 @@ public struct NumberSeparatorRule: OptInRule, CorrectableRule, ConfigurationProv
}
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
}

View File

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

View File

@ -40,9 +40,11 @@ public struct OperatorFunctionWhitespaceRule: ConfigurationProviderRule {
let zeroOrManySpaces = "(\\s{0}|\\s{2,})"
let pattern1 = "func\\s+[\(operators)]+\(zeroOrManySpaces)(<[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
}.map { range, _ in
}.map { arg in
let (range, _) = arg
return StyleViolation(ruleDescription: type(of: self).description,
severity: configuration.severity,
location: Location(file: file, characterOffset: range.location))

View File

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

View File

@ -43,7 +43,8 @@ public struct SortedImportsRule: ConfigurationProviderRule, OptInRule {
}
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
}

View File

@ -107,7 +107,8 @@ private extension StatementPositionRule {
}
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])
}.flatMap { $0.0 }
}

View File

@ -86,7 +86,8 @@ public struct TodoRule: ConfigurationProviderRule {
}
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 {
return nil
}

View File

@ -48,7 +48,8 @@ public struct TypeNameRule: ASTRule, ConfigurationProviderRule {
private func validateTypeAliasesAndAssociatedTypes(in file: File) -> [StyleViolation] {
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,
let keywordToken = tokens.first,
let nameToken = tokens.last,

View File

@ -80,7 +80,8 @@ public struct UnusedClosureParameterRule: ASTRule, ConfigurationProviderRule, Co
public func validate(file: File, kind: SwiftExpressionKind,
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 _."
return StyleViolation(ruleDescription: type(of: self).description,
severity: configuration.severity,

View File

@ -115,7 +115,7 @@ public struct ValidIBInspectableRule: ASTRule, ConfigurationProviderRule {
"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
"\(sign)Int\(size)"
}

View File

@ -37,7 +37,7 @@ struct AutoCorrectCommand: CommandProtocol {
if !options.quiet {
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)
visitorMutationQueue.sync {
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
}
} else {
@ -73,7 +73,7 @@ struct LintCommand: CommandProtocol {
} else if strictWithViolations {
exit(3)
}
return .success()
return .success(())
}
private static func printStatus(violations: [StyleViolation], files: [File], serious: Int) {

View File

@ -38,14 +38,14 @@ struct RulesCommand: CommandProtocol {
}
print(ruleDescription: rule.description)
return .success()
return .success(())
}
let configuration = Configuration(commandLinePath: options.configurationFile)
let rules = ruleList(for: options, configuration: configuration)
print(TextTable(ruleList: rules, configuration: configuration).render())
return .success()
return .success(())
}
private func ruleList(for options: RulesOptions, configuration: Configuration) -> RuleList {
@ -53,7 +53,8 @@ struct RulesCommand: CommandProtocol {
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
return type(of: rule).description.identifier == ruleID
}

View File

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

View File

@ -38,7 +38,8 @@ struct Benchmark {
return accu
}
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)"
}
let string: String = lines.joined(separator: "\n") + "\n"

View File

@ -1492,7 +1492,7 @@
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Source/SwiftLintFramework/Supporting Files/Info.plist";
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_NAME = SwiftLintFramework;
SWIFT_VERSION = 3.0;
@ -1574,7 +1574,7 @@
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Source/SwiftLintFramework/Supporting Files/Info.plist";
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_NAME = SwiftLintFramework;
SWIFT_VERSION = 3.0;
@ -1620,7 +1620,7 @@
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Source/SwiftLintFramework/Supporting Files/Info.plist";
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_NAME = SwiftLintFramework;
SWIFT_VERSION = 3.0;

View File

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

View File

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