Allow configuring `xct_specific_matcher` with matchers (#4905)
So that either `one-argument-asserts` or `two-argument-asserts` or both can be enabled. The following configuration effectively reverts back to the rule behavior prior to https://github.com/realm/SwiftLint/pull/3858: ```yaml xct_specific_matcher: matchers: - two-argument-asserts ```
This commit is contained in:
parent
8b72eb0406
commit
fbbccf9db8
|
@ -19,8 +19,11 @@
|
||||||
[kimdv](https://github.com/kimdv)
|
[kimdv](https://github.com/kimdv)
|
||||||
|
|
||||||
* Extend `xct_specific_matcher` rule to check for boolean asserts on (un)equal
|
* Extend `xct_specific_matcher` rule to check for boolean asserts on (un)equal
|
||||||
comparisons.
|
comparisons. The rule can be configured with the matchers that should trigger
|
||||||
|
rule violations. By default, all matchers trigger, but that can be limited to
|
||||||
|
just `one-argument-asserts` or `two-argument-asserts`.
|
||||||
[SimplyDanny](https://github.com/SimplyDanny)
|
[SimplyDanny](https://github.com/SimplyDanny)
|
||||||
|
[JP Simard](https://github.com/jpsim)
|
||||||
[#3726](https://github.com/realm/SwiftLint/issues/3726)
|
[#3726](https://github.com/realm/SwiftLint/issues/3726)
|
||||||
|
|
||||||
* Trigger `prefer_self_in_static_references` rule on more type references.
|
* Trigger `prefer_self_in_static_references` rule on more type references.
|
||||||
|
|
|
@ -2,7 +2,7 @@ import SwiftOperators
|
||||||
import SwiftSyntax
|
import SwiftSyntax
|
||||||
|
|
||||||
struct XCTSpecificMatcherRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
|
struct XCTSpecificMatcherRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
|
||||||
var configuration = SeverityConfiguration(.warning)
|
var configuration = XCTSpecificMatcherRuleConfiguration()
|
||||||
|
|
||||||
init() {}
|
init() {}
|
||||||
|
|
||||||
|
@ -16,14 +16,28 @@ struct XCTSpecificMatcherRule: SwiftSyntaxRule, OptInRule, ConfigurationProvider
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||||
Visitor(viewMode: .sourceAccurate)
|
Visitor(configuration: configuration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension XCTSpecificMatcherRule {
|
private extension XCTSpecificMatcherRule {
|
||||||
final class Visitor: ViolationsSyntaxVisitor {
|
final class Visitor: ViolationsSyntaxVisitor {
|
||||||
|
let configuration: XCTSpecificMatcherRuleConfiguration
|
||||||
|
|
||||||
|
init(configuration: XCTSpecificMatcherRuleConfiguration) {
|
||||||
|
self.configuration = configuration
|
||||||
|
super.init(viewMode: .sourceAccurate)
|
||||||
|
}
|
||||||
|
|
||||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||||
if let suggestion = TwoArgsXCTAssert.violations(in: node) ?? OneArgXCTAssert.violations(in: node) {
|
if configuration.matchers.contains(.twoArgumentAsserts),
|
||||||
|
let suggestion = TwoArgsXCTAssert.violations(in: node) {
|
||||||
|
violations.append(ReasonedRuleViolation(
|
||||||
|
position: node.positionAfterSkippingLeadingTrivia,
|
||||||
|
reason: "Prefer the specific matcher '\(suggestion)' instead"
|
||||||
|
))
|
||||||
|
} else if configuration.matchers.contains(.oneArgumentAsserts),
|
||||||
|
let suggestion = OneArgXCTAssert.violations(in: node) {
|
||||||
violations.append(ReasonedRuleViolation(
|
violations.append(ReasonedRuleViolation(
|
||||||
position: node.positionAfterSkippingLeadingTrivia,
|
position: node.positionAfterSkippingLeadingTrivia,
|
||||||
reason: "Prefer the specific matcher '\(suggestion)' instead"
|
reason: "Prefer the specific matcher '\(suggestion)' instead"
|
||||||
|
|
|
@ -50,7 +50,13 @@ internal struct XCTSpecificMatcherRuleExamples {
|
||||||
Example("XCTAssertEqual(foo?.bar, toto())"),
|
Example("XCTAssertEqual(foo?.bar, toto())"),
|
||||||
Example("XCTAssertEqual(foo?.bar, .toto(.zoo))"),
|
Example("XCTAssertEqual(foo?.bar, .toto(.zoo))"),
|
||||||
Example("XCTAssertEqual(toto(), foo?.bar)"),
|
Example("XCTAssertEqual(toto(), foo?.bar)"),
|
||||||
Example("XCTAssertEqual(.toto(.zoo), foo?.bar)")
|
Example("XCTAssertEqual(.toto(.zoo), foo?.bar)"),
|
||||||
|
|
||||||
|
// Configurations Disabled
|
||||||
|
Example("XCTAssertEqual(foo, true)",
|
||||||
|
configuration: ["matchers": ["one-argument-asserts"]]),
|
||||||
|
Example("XCTAssert(foo == bar)",
|
||||||
|
configuration: ["matchers": ["two-argument-asserts"]])
|
||||||
]
|
]
|
||||||
|
|
||||||
static let triggeringExamples = [
|
static let triggeringExamples = [
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
struct XCTSpecificMatcherRuleConfiguration: SeverityBasedRuleConfiguration, Equatable {
|
||||||
|
private(set) var severityConfiguration = SeverityConfiguration(.warning)
|
||||||
|
private(set) var matchers = Set(Matcher.allCases)
|
||||||
|
|
||||||
|
enum Matcher: String, Hashable, CaseIterable {
|
||||||
|
case oneArgumentAsserts = "one-argument-asserts"
|
||||||
|
case twoArgumentAsserts = "two-argument-asserts"
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum ConfigurationKey: String {
|
||||||
|
case severity
|
||||||
|
case matchers
|
||||||
|
}
|
||||||
|
|
||||||
|
var consoleDescription: String {
|
||||||
|
return [
|
||||||
|
"severity: \(severityConfiguration.consoleDescription)",
|
||||||
|
"\(ConfigurationKey.matchers): \(matchers.map(\.rawValue).sorted().joined(separator: ", "))"
|
||||||
|
].joined(separator: ", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func apply(configuration: Any) throws {
|
||||||
|
guard let configuration = configuration as? [String: Any] else {
|
||||||
|
throw ConfigurationError.unknownConfiguration
|
||||||
|
}
|
||||||
|
|
||||||
|
if let severityString = configuration[ConfigurationKey.severity.rawValue] as? String {
|
||||||
|
try severityConfiguration.apply(configuration: severityString)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let matchers = configuration[ConfigurationKey.matchers.rawValue] as? [String] {
|
||||||
|
self.matchers = Set(matchers.compactMap(Matcher.init(rawValue:)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue