mirror of
https://github.com/realm/SwiftLint.git
synced 2026-05-07 20:12:49 +00:00
541 lines
14 KiB
Swift
541 lines
14 KiB
Swift
@testable import SwiftLintCore
|
|
import TestHelpers
|
|
import XCTest
|
|
|
|
// swiftlint:disable file_length
|
|
|
|
// swiftlint:disable:next type_body_length
|
|
final class RuleConfigurationDescriptionTests: SwiftLintTestCase {
|
|
@AutoConfigParser
|
|
private struct MockConfiguration: RuleConfiguration {
|
|
@ConfigurationElement(key: "flag")
|
|
var flag = true
|
|
@ConfigurationElement(key: "string")
|
|
var string = "value"
|
|
@ConfigurationElement(key: "symbol")
|
|
var symbol = try! Symbol(fromAny: "value", context: "rule") // swiftlint:disable:this force_try
|
|
@ConfigurationElement(key: "integer")
|
|
var integer = 2
|
|
@ConfigurationElement(key: "null")
|
|
var null: Int?
|
|
@ConfigurationElement(key: "my_double")
|
|
var myDouble = 2.1
|
|
@ConfigurationElement(key: "severity")
|
|
var severity = ViolationSeverity.warning
|
|
@ConfigurationElement(
|
|
key: "list",
|
|
postprocessor: { list in list = list.map { $0.uppercased() } }
|
|
)
|
|
var list = ["string1", "string2"]
|
|
@ConfigurationElement(key: "set", deprecationNotice: .suggestAlternative(ruleID: "my_rule", name: "other_opt"))
|
|
var set: Set<Int> = [1, 2, 3]
|
|
@ConfigurationElement(key: "set_of_doubles")
|
|
var setOfDoubles: Set<Double> = [1, 2, 3, 4.7]
|
|
@ConfigurationElement(inline: true)
|
|
var severityConfig = SeverityConfiguration<Parent>(.error)
|
|
@ConfigurationElement(key: "SEVERITY")
|
|
var renamedSeverityConfig = SeverityConfiguration<Parent>(.warning)
|
|
@ConfigurationElement(inline: true)
|
|
var inlinedSeverityLevels = SeverityLevelsConfiguration<Parent>(warning: 1, error: nil)
|
|
@ConfigurationElement(key: "levels")
|
|
var nestedSeverityLevels = SeverityLevelsConfiguration<Parent>(warning: 3, error: 2)
|
|
|
|
func isEqualTo(_: some RuleConfiguration) -> Bool { false }
|
|
}
|
|
|
|
// swiftlint:disable:next function_body_length
|
|
func testDescriptionFromConfiguration() throws {
|
|
var configuration = MockConfiguration()
|
|
try configuration.apply(configuration: Void()) // Configure to set keys.
|
|
let description = RuleConfigurationDescription.from(configuration: configuration)
|
|
|
|
XCTAssertEqual(description.oneLiner(), """
|
|
flag: true; \
|
|
string: "value"; \
|
|
symbol: value; \
|
|
integer: 2; \
|
|
my_double: 2.1; \
|
|
severity: warning; \
|
|
list: ["STRING1", "STRING2"]; \
|
|
set: [1, 2, 3]; \
|
|
set_of_doubles: [1.0, 2.0, 3.0, 4.7]; \
|
|
severity: error; \
|
|
SEVERITY: warning; \
|
|
warning: 1; \
|
|
levels: warning: 3, error: 2
|
|
""")
|
|
|
|
XCTAssertEqual(description.markdown(), """
|
|
<table>
|
|
<thead>
|
|
<tr><th>Key</th><th>Value</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
flag
|
|
</td>
|
|
<td>
|
|
true
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
string
|
|
</td>
|
|
<td>
|
|
"value"
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
symbol
|
|
</td>
|
|
<td>
|
|
value
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
integer
|
|
</td>
|
|
<td>
|
|
2
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
my_double
|
|
</td>
|
|
<td>
|
|
2.1
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
severity
|
|
</td>
|
|
<td>
|
|
warning
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
list
|
|
</td>
|
|
<td>
|
|
["STRING1", "STRING2"]
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
set
|
|
</td>
|
|
<td>
|
|
[1, 2, 3]
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
set_of_doubles
|
|
</td>
|
|
<td>
|
|
[1.0, 2.0, 3.0, 4.7]
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
severity
|
|
</td>
|
|
<td>
|
|
error
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
SEVERITY
|
|
</td>
|
|
<td>
|
|
warning
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
warning
|
|
</td>
|
|
<td>
|
|
1
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
levels
|
|
</td>
|
|
<td>
|
|
<table>
|
|
<thead>
|
|
<tr><th>Key</th><th>Value</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
warning
|
|
</td>
|
|
<td>
|
|
3
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
error
|
|
</td>
|
|
<td>
|
|
2
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
""")
|
|
|
|
XCTAssertEqual(description.yaml(), """
|
|
flag: true
|
|
string: "value"
|
|
symbol: value
|
|
integer: 2
|
|
my_double: 2.1
|
|
severity: warning
|
|
list: ["STRING1", "STRING2"]
|
|
set: [1, 2, 3]
|
|
set_of_doubles: [1.0, 2.0, 3.0, 4.7]
|
|
severity: error
|
|
SEVERITY: warning
|
|
warning: 1
|
|
levels:
|
|
warning: 3
|
|
error: 2
|
|
""")
|
|
}
|
|
|
|
func testPrefersParameterDescription() {
|
|
struct MockConfiguration: RuleConfiguration {
|
|
typealias Parent = MockRule // swiftlint:disable:this nesting
|
|
|
|
var parameterDescription: RuleConfigurationDescription? {
|
|
"visible" => .flag(true)
|
|
}
|
|
|
|
@ConfigurationElement(key: "invisible")
|
|
var invisible = true
|
|
|
|
mutating func apply(configuration _: Any) { /* conformance for test */ }
|
|
|
|
func isEqualTo(_: some RuleConfiguration) -> Bool { false }
|
|
}
|
|
|
|
let description = RuleConfigurationDescription.from(configuration: MockConfiguration())
|
|
XCTAssertEqual(description.oneLiner(), "visible: true")
|
|
XCTAssertEqual(description.markdown(), """
|
|
<table>
|
|
<thead>
|
|
<tr><th>Key</th><th>Value</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
visible
|
|
</td>
|
|
<td>
|
|
true
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
""")
|
|
XCTAssertEqual(description.yaml(), "visible: true")
|
|
}
|
|
|
|
func testEmptyDescription() {
|
|
let description = description { RuleConfigurationOption.noOptions }
|
|
|
|
XCTAssertTrue(description.oneLiner().isEmpty)
|
|
XCTAssertTrue(description.markdown().isEmpty)
|
|
XCTAssertTrue(description.yaml().isEmpty)
|
|
}
|
|
|
|
// swiftlint:disable:next function_body_length
|
|
func testBasicTypes() {
|
|
let description = description {
|
|
"flag" => .flag(true)
|
|
"string" => .string("value")
|
|
"symbol" => .symbol("value")
|
|
"integer" => .integer(-12)
|
|
"float" => .float(42.0)
|
|
"severity" => .severity(.error)
|
|
"list" => .list([.symbol("value"), .string("value"), .float(12.8)])
|
|
}
|
|
|
|
XCTAssertEqual(description.markdown(), """
|
|
<table>
|
|
<thead>
|
|
<tr><th>Key</th><th>Value</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
flag
|
|
</td>
|
|
<td>
|
|
true
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
string
|
|
</td>
|
|
<td>
|
|
"value"
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
symbol
|
|
</td>
|
|
<td>
|
|
value
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
integer
|
|
</td>
|
|
<td>
|
|
-12
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
float
|
|
</td>
|
|
<td>
|
|
42.0
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
severity
|
|
</td>
|
|
<td>
|
|
error
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
list
|
|
</td>
|
|
<td>
|
|
[value, "value", 12.8]
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
""")
|
|
|
|
XCTAssertEqual(description.oneLiner(), """
|
|
flag: true; string: "value"; symbol: value; integer: -12; float: 42.0; \
|
|
severity: error; list: [value, "value", 12.8]
|
|
""")
|
|
|
|
XCTAssertEqual(description.yaml(), """
|
|
flag: true
|
|
string: "value"
|
|
symbol: value
|
|
integer: -12
|
|
float: 42.0
|
|
severity: error
|
|
list: [value, "value", 12.8]
|
|
""")
|
|
}
|
|
|
|
// swiftlint:disable:next function_body_length
|
|
func testNestedDescription() {
|
|
let description = description {
|
|
"flag" => .flag(true)
|
|
"nested 1" => .nest {
|
|
"integer" => .integer(2)
|
|
"nested 2" => .nest {
|
|
"float" => .float(42.1)
|
|
}
|
|
"symbol" => .symbol("value")
|
|
}
|
|
"string" => .string("value")
|
|
}
|
|
|
|
XCTAssertEqual(description.markdown(), """
|
|
<table>
|
|
<thead>
|
|
<tr><th>Key</th><th>Value</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
flag
|
|
</td>
|
|
<td>
|
|
true
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
nested 1
|
|
</td>
|
|
<td>
|
|
<table>
|
|
<thead>
|
|
<tr><th>Key</th><th>Value</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
integer
|
|
</td>
|
|
<td>
|
|
2
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
nested 2
|
|
</td>
|
|
<td>
|
|
<table>
|
|
<thead>
|
|
<tr><th>Key</th><th>Value</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
float
|
|
</td>
|
|
<td>
|
|
42.1
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
symbol
|
|
</td>
|
|
<td>
|
|
value
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
string
|
|
</td>
|
|
<td>
|
|
"value"
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
""")
|
|
|
|
XCTAssertEqual(description.oneLiner(), """
|
|
flag: true; nested 1: integer: 2, nested 2: float: 42.1, symbol: value; string: "value"
|
|
""")
|
|
|
|
XCTAssertEqual(description.yaml(), """
|
|
flag: true
|
|
nested 1:
|
|
integer: 2
|
|
nested 2:
|
|
float: 42.1
|
|
symbol: value
|
|
string: "value"
|
|
""")
|
|
}
|
|
|
|
func testUpdate() throws {
|
|
var configuration = MockConfiguration()
|
|
|
|
try configuration.apply(configuration: [
|
|
"flag": false,
|
|
"string": "new value",
|
|
"symbol": "new symbol",
|
|
"integer": 5,
|
|
"null": 0,
|
|
"my_double": 5.1,
|
|
"severity": "error",
|
|
"list": ["string3", "string4"],
|
|
"set": [4, 5, 6],
|
|
"SEVERITY": "error",
|
|
"warning": 12,
|
|
"levels": ["warning": 6, "error": 7],
|
|
])
|
|
|
|
XCTAssertFalse(configuration.flag)
|
|
XCTAssertEqual(configuration.string, "new value")
|
|
XCTAssertEqual(configuration.symbol, try Symbol(fromAny: "new symbol", context: "rule"))
|
|
XCTAssertEqual(configuration.integer, 5)
|
|
XCTAssertEqual(configuration.null, 0)
|
|
XCTAssertEqual(configuration.myDouble, 5.1)
|
|
XCTAssertEqual(configuration.severity, .error)
|
|
XCTAssertEqual(configuration.list, ["STRING3", "STRING4"])
|
|
XCTAssertEqual(configuration.set, [4, 5, 6])
|
|
XCTAssertEqual(configuration.severityConfig, .error)
|
|
XCTAssertEqual(configuration.renamedSeverityConfig, .error)
|
|
XCTAssertEqual(configuration.inlinedSeverityLevels, SeverityLevelsConfiguration(warning: 12))
|
|
XCTAssertEqual(configuration.nestedSeverityLevels, SeverityLevelsConfiguration(warning: 6, error: 7))
|
|
}
|
|
|
|
func testDeprecationWarning() async throws {
|
|
let console = try await Issue.captureConsole {
|
|
var configuration = MockConfiguration()
|
|
try configuration.apply(configuration: ["set": [6, 7]])
|
|
}
|
|
XCTAssertEqual(
|
|
console,
|
|
"warning: Configuration option 'set' in 'my_rule' rule is deprecated. Use the option 'other_opt' instead."
|
|
)
|
|
}
|
|
|
|
func testNoDeprecationWarningIfNoDeprecatedPropertySet() async throws {
|
|
let console = try await Issue.captureConsole {
|
|
var configuration = MockConfiguration()
|
|
try configuration.apply(configuration: ["flag": false])
|
|
}
|
|
XCTAssertTrue(console.isEmpty)
|
|
}
|
|
|
|
func testInvalidKeys() async throws {
|
|
let console = try await Issue.captureConsole {
|
|
var configuration = MockConfiguration()
|
|
try configuration.apply(configuration: [
|
|
"severity": "error",
|
|
"warning": 3,
|
|
"unknown": 1,
|
|
"unsupported": true,
|
|
])
|
|
}
|
|
XCTAssertEqual(
|
|
console,
|
|
"warning: Configuration for 'MockRule' rule contains the invalid key(s) 'unknown', 'unsupported'."
|
|
)
|
|
}
|
|
|
|
private func description(@RuleConfigurationDescriptionBuilder _ content: () -> RuleConfigurationDescription)
|
|
-> RuleConfigurationDescription { content() }
|
|
}
|