mirror of
https://github.com/realm/SwiftLint.git
synced 2026-05-07 20:12:49 +00:00
Make postprocessors non-throwing (#5539)
Failing immediately when a property is invalid is too strict. It feels sufficient to allow to report an issue but otherwise continue with a default value instead of stopping execution completely.
This commit is contained in:
+8
-1
@@ -4,11 +4,18 @@ import SwiftLintCore
|
||||
struct IndentationWidthConfiguration: SeverityBasedRuleConfiguration {
|
||||
typealias Parent = IndentationWidthRule
|
||||
|
||||
private static let defaultIndentationWidth = 4
|
||||
|
||||
@ConfigurationElement(key: "severity")
|
||||
private(set) var severityConfiguration = SeverityConfiguration<Parent>.warning
|
||||
@ConfigurationElement(
|
||||
key: "indentation_width",
|
||||
postprocessor: { if $0 < 1 { throw Issue.invalidConfiguration(ruleID: Parent.identifier) } }
|
||||
postprocessor: {
|
||||
if $0 < 1 {
|
||||
Issue.invalidConfiguration(ruleID: Parent.identifier).print()
|
||||
$0 = Self.defaultIndentationWidth
|
||||
}
|
||||
}
|
||||
)
|
||||
private(set) var indentationWidth = 4
|
||||
@ConfigurationElement(key: "include_comments")
|
||||
|
||||
@@ -416,7 +416,13 @@ public protocol InlinableOptionType: AcceptableByConfigurationElement {}
|
||||
@propertyWrapper
|
||||
public struct ConfigurationElement<T: AcceptableByConfigurationElement & Equatable>: Equatable {
|
||||
/// Wrapped option value.
|
||||
public var wrappedValue: T
|
||||
public var wrappedValue: T {
|
||||
didSet {
|
||||
if wrappedValue != oldValue {
|
||||
postprocessor(&wrappedValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The wrapper itself providing access to all its data. This field can only be accessed by the
|
||||
/// element's name prefixed with a `$`.
|
||||
@@ -431,7 +437,7 @@ public struct ConfigurationElement<T: AcceptableByConfigurationElement & Equatab
|
||||
/// Whether this configuration element will be inlined into its description.
|
||||
public let inline: Bool
|
||||
|
||||
private let postprocessor: (inout T) throws -> Void
|
||||
private let postprocessor: (inout T) -> Void
|
||||
|
||||
/// Default constructor.
|
||||
///
|
||||
@@ -441,11 +447,11 @@ public struct ConfigurationElement<T: AcceptableByConfigurationElement & Equatab
|
||||
/// - postprocessor: Function to be applied to the wrapped value after parsing to validate and modify it.
|
||||
public init(wrappedValue value: T,
|
||||
key: String,
|
||||
postprocessor: @escaping (inout T) throws -> Void = { _ in }) {
|
||||
postprocessor: @escaping (inout T) -> Void = { _ in }) {
|
||||
self.init(wrappedValue: value, key: key, inline: false, postprocessor: postprocessor)
|
||||
|
||||
// Validate and modify the set value immediately. An exception means invalid defaults.
|
||||
try! performAfterParseOperations() // swiftlint:disable:this force_try
|
||||
// Modify the set value immediately.
|
||||
postprocessor(&wrappedValue)
|
||||
}
|
||||
|
||||
/// Constructor for optional values.
|
||||
@@ -482,18 +488,13 @@ public struct ConfigurationElement<T: AcceptableByConfigurationElement & Equatab
|
||||
private init(wrappedValue: T,
|
||||
key: String,
|
||||
inline: Bool,
|
||||
postprocessor: @escaping (inout T) throws -> Void = { _ in }) {
|
||||
postprocessor: @escaping (inout T) -> Void = { _ in }) {
|
||||
self.wrappedValue = wrappedValue
|
||||
self.key = key
|
||||
self.inline = inline
|
||||
self.postprocessor = postprocessor
|
||||
}
|
||||
|
||||
/// Run operations to validate and modify the parsed value.
|
||||
public mutating func performAfterParseOperations() throws {
|
||||
try postprocessor(&wrappedValue)
|
||||
}
|
||||
|
||||
public static func == (lhs: ConfigurationElement, rhs: ConfigurationElement) -> Bool {
|
||||
lhs.wrappedValue == rhs.wrappedValue && lhs.key == rhs.key
|
||||
}
|
||||
|
||||
@@ -60,7 +60,6 @@ enum AutoApply: MemberMacro {
|
||||
"""
|
||||
do {
|
||||
try \(raw: option).apply(configuration, ruleID: Parent.identifier)
|
||||
try $\(raw: option).performAfterParseOperations()
|
||||
} catch let issue as Issue where issue == Issue.nothingApplied(ruleID: Parent.identifier) {
|
||||
// Acceptable. Continue.
|
||||
}
|
||||
@@ -77,9 +76,6 @@ enum AutoApply: MemberMacro {
|
||||
"""
|
||||
try \(raw: option).apply(configuration[$\(raw: option).key], ruleID: Parent.identifier)
|
||||
"""
|
||||
"""
|
||||
try $\(raw: option).performAfterParseOperations()
|
||||
"""
|
||||
}
|
||||
"""
|
||||
if !supportedKeys.isSuperset(of: configuration.keys) {
|
||||
|
||||
@@ -81,9 +81,7 @@ final class AutoApplyTests: XCTestCase {
|
||||
throw Issue.invalidConfiguration(ruleID: Parent.identifier)
|
||||
}
|
||||
try eA.apply(configuration[$eA.key], ruleID: Parent.identifier)
|
||||
try $eA.performAfterParseOperations()
|
||||
try eB.apply(configuration[$eB.key], ruleID: Parent.identifier)
|
||||
try $eB.performAfterParseOperations()
|
||||
if !supportedKeys.isSuperset(of: configuration.keys) {
|
||||
let unknownKeys = Set(configuration.keys).subtracting(supportedKeys)
|
||||
throw Issue.invalidConfigurationKeys(ruleID: Parent.identifier, keys: unknownKeys)
|
||||
@@ -127,7 +125,6 @@ final class AutoApplyTests: XCTestCase {
|
||||
}
|
||||
do {
|
||||
try eB.apply(configuration, ruleID: Parent.identifier)
|
||||
try $eB.performAfterParseOperations()
|
||||
} catch let issue as Issue where issue == Issue.nothingApplied(ruleID: Parent.identifier) {
|
||||
// Acceptable. Continue.
|
||||
}
|
||||
@@ -135,9 +132,7 @@ final class AutoApplyTests: XCTestCase {
|
||||
return
|
||||
}
|
||||
try eA.apply(configuration[$eA.key], ruleID: Parent.identifier)
|
||||
try $eA.performAfterParseOperations()
|
||||
try eC.apply(configuration[$eC.key], ruleID: Parent.identifier)
|
||||
try $eC.performAfterParseOperations()
|
||||
if !supportedKeys.isSuperset(of: configuration.keys) {
|
||||
let unknownKeys = Set(configuration.keys).subtracting(supportedKeys)
|
||||
throw Issue.invalidConfigurationKeys(ruleID: Parent.identifier, keys: unknownKeys)
|
||||
@@ -210,7 +205,6 @@ final class AutoApplyTests: XCTestCase {
|
||||
}
|
||||
do {
|
||||
try severityConfiguration.apply(configuration, ruleID: Parent.identifier)
|
||||
try $severityConfiguration.performAfterParseOperations()
|
||||
} catch let issue as Issue where issue == Issue.nothingApplied(ruleID: Parent.identifier) {
|
||||
// Acceptable. Continue.
|
||||
}
|
||||
@@ -218,9 +212,7 @@ final class AutoApplyTests: XCTestCase {
|
||||
return
|
||||
}
|
||||
try severityConfiguration.apply(configuration[$severityConfiguration.key], ruleID: Parent.identifier)
|
||||
try $severityConfiguration.performAfterParseOperations()
|
||||
try foo.apply(configuration[$foo.key], ruleID: Parent.identifier)
|
||||
try $foo.performAfterParseOperations()
|
||||
if !supportedKeys.isSuperset(of: configuration.keys) {
|
||||
let unknownKeys = Set(configuration.keys).subtracting(supportedKeys)
|
||||
throw Issue.invalidConfigurationKeys(ruleID: Parent.identifier, keys: unknownKeys)
|
||||
|
||||
@@ -3,12 +3,14 @@ import SwiftLintTestHelpers
|
||||
import XCTest
|
||||
|
||||
class IndentationWidthRuleTests: SwiftLintTestCase {
|
||||
func testInvalidIndentation() {
|
||||
func testInvalidIndentation() throws {
|
||||
var testee = IndentationWidthConfiguration()
|
||||
let defaultValue = testee.indentationWidth
|
||||
for indentation in [0, -1, -5] {
|
||||
checkError(Issue.invalidConfiguration(ruleID: IndentationWidthRule.description.identifier)) {
|
||||
try testee.apply(configuration: ["indentation_width": indentation])
|
||||
}
|
||||
try testee.apply(configuration: ["indentation_width": indentation])
|
||||
|
||||
// Value remains the default.
|
||||
XCTAssertEqual(testee.indentationWidth, defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user