Skip to content

Commit

Permalink
Allow configuring xct_specific_matcher with matchers (realm#4905)
Browse files Browse the repository at this point in the history
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 realm#3858:

```yaml
xct_specific_matcher:
  matchers:
    - two-argument-asserts
```
  • Loading branch information
jpsim authored Apr 18, 2023
1 parent 8b72eb0 commit fbbccf9
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 5 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@
[kimdv](https://github.com/kimdv)

* 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)
[JP Simard](https://github.com/jpsim)
[#3726](https://github.com/realm/SwiftLint/issues/3726)

* Trigger `prefer_self_in_static_references` rule on more type references.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import SwiftOperators
import SwiftSyntax

struct XCTSpecificMatcherRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule {
var configuration = SeverityConfiguration(.warning)
var configuration = XCTSpecificMatcherRuleConfiguration()

init() {}

Expand All @@ -16,14 +16,28 @@ struct XCTSpecificMatcherRule: SwiftSyntaxRule, OptInRule, ConfigurationProvider
)

func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
Visitor(viewMode: .sourceAccurate)
Visitor(configuration: configuration)
}
}

private extension XCTSpecificMatcherRule {
final class Visitor: ViolationsSyntaxVisitor {
let configuration: XCTSpecificMatcherRuleConfiguration

init(configuration: XCTSpecificMatcherRuleConfiguration) {
self.configuration = configuration
super.init(viewMode: .sourceAccurate)
}

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(
position: node.positionAfterSkippingLeadingTrivia,
reason: "Prefer the specific matcher '\(suggestion)' instead"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,13 @@ internal struct XCTSpecificMatcherRuleExamples {
Example("XCTAssertEqual(foo?.bar, toto())"),
Example("XCTAssertEqual(foo?.bar, .toto(.zoo))"),
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 = [
Expand Down
Original file line number Diff line number Diff line change
@@ -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:)))
}
}
}

0 comments on commit fbbccf9

Please sign in to comment.