mirror of
https://github.com/realm/SwiftLint.git
synced 2026-05-07 20:12:49 +00:00
fcf848608e
* Add Example wrapper in order to display test failures inline when running in Xcode. * Stop using Swift 5.1-only features so we can compile on Xcode 10.2. * Wrap strings in Example. * Add Changelog entry. * Wrap all examples in Example struct. * Better and more complete capturing of line numbers. * Fix broken test. * Better test traceability. * Address or disable linting warnings. * Add documentation comments. * Disable linter for a few cases. * Limit mutability and add copy-and-mutate utility functions. * Limit scope of mutability.
51 lines
2.2 KiB
Swift
51 lines
2.2 KiB
Swift
import SourceKittenFramework
|
|
|
|
public struct ReduceBooleanRule: Rule, ConfigurationProviderRule, AutomaticTestableRule {
|
|
public var configuration = SeverityConfiguration(.warning)
|
|
|
|
public init() {}
|
|
|
|
public static let description = RuleDescription(
|
|
identifier: "reduce_boolean",
|
|
name: "Reduce Boolean",
|
|
description: "Prefer using `.allSatisfy()` or `.contains()` over `reduce(true)` or `reduce(false)`",
|
|
kind: .performance,
|
|
minSwiftVersion: .fourDotTwo,
|
|
nonTriggeringExamples: [
|
|
Example("nums.reduce(0) { $0.0 + $0.1 }"),
|
|
Example("nums.reduce(0.0) { $0.0 + $0.1 }")
|
|
],
|
|
triggeringExamples: [
|
|
Example("let allNines = nums.↓reduce(true) { $0.0 && $0.1 == 9 }"),
|
|
Example("let anyNines = nums.↓reduce(false) { $0.0 || $0.1 == 9 }"),
|
|
Example("let allValid = validators.↓reduce(true) { $0 && $1(input) }"),
|
|
Example("let anyValid = validators.↓reduce(false) { $0 || $1(input) }"),
|
|
Example("let allNines = nums.↓reduce(true, { $0.0 && $0.1 == 9 })"),
|
|
Example("let anyNines = nums.↓reduce(false, { $0.0 || $0.1 == 9 })"),
|
|
Example("let allValid = validators.↓reduce(true, { $0 && $1(input) })"),
|
|
Example("let anyValid = validators.↓reduce(false, { $0 || $1(input) })")
|
|
]
|
|
)
|
|
|
|
public func validate(file: SwiftLintFile) -> [StyleViolation] {
|
|
let pattern = "\\breduce\\((true|false)"
|
|
return file
|
|
.match(pattern: pattern, with: [.identifier, .keyword])
|
|
.map { range in
|
|
let reason: String
|
|
if file.contents[Range(range, in: file.contents)!].contains("true") {
|
|
reason = "Use `allSatisfy` instead"
|
|
} else {
|
|
reason = "Use `contains` instead"
|
|
}
|
|
|
|
return StyleViolation(
|
|
ruleDescription: type(of: self).description,
|
|
severity: configuration.severity,
|
|
location: Location(file: file, characterOffset: range.location),
|
|
reason: reason
|
|
)
|
|
}
|
|
}
|
|
}
|