From 55c63a72d7669b2b1b6b3bd5ecf83a36b0fdd0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= Date: Sat, 28 Dec 2024 18:24:35 +0100 Subject: [PATCH] Adopt typed throws where possible --- .../DeploymentTargetConfiguration.swift | 18 +++---- .../ExpiringTodoConfiguration.swift | 4 +- .../FileHeaderConfiguration.swift | 4 +- .../MissingDocsConfiguration.swift | 12 ++--- .../ModifierOrderConfiguration.swift | 4 +- .../MultilineParametersConfiguration.swift | 2 +- .../NameConfiguration.swift | 4 +- .../NumberSeparatorConfiguration.swift | 4 +- .../RequiredEnumCaseConfiguration.swift | 4 +- .../UnusedImportConfiguration.swift | 4 +- .../NSRegularExpression+SwiftLint.swift | 4 +- .../ChildOptionSeverityConfiguration.swift | 4 +- .../Models/RuleConfigurationDescription.swift | 48 ++++++++++--------- Source/SwiftLintCore/Models/RuleList.swift | 5 +- .../Models/SeverityConfiguration.swift | 6 +-- .../Protocols/RuleConfiguration.swift | 6 +-- .../RegexConfiguration.swift | 22 ++++----- .../SeverityLevelsConfiguration.swift | 8 ++-- .../RuleConfigurationMacros.swift | 10 ++-- .../Configuration+CommandLine.swift | 18 +++---- .../LintableFilesVisitor.swift | 9 ++-- .../Rules/CustomRules.swift | 4 +- Source/swiftlint/Commands/Rules.swift | 4 +- .../RuleConfigurationDescriptionTests.swift | 2 +- ...cceptableByConfigurationElementTests.swift | 8 ++-- Tests/MacroTests/AutoConfigParserTests.swift | 20 ++++---- 26 files changed, 121 insertions(+), 117 deletions(-) diff --git a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/DeploymentTargetConfiguration.swift b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/DeploymentTargetConfiguration.swift index 6c7cd87ee1..809b050f10 100644 --- a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/DeploymentTargetConfiguration.swift +++ b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/DeploymentTargetConfiguration.swift @@ -47,7 +47,7 @@ struct DeploymentTargetConfiguration: SeverityBasedRuleConfiguration { self.patch = patch } - init(platform: Platform, value: Any) throws { + init(platform: Platform, value: Any) throws(Issue) { let (major, minor, patch) = try Self.parseVersion(string: String(describing: value)) self.init(platform: platform, major: major, minor: minor, patch: patch) } @@ -56,10 +56,10 @@ struct DeploymentTargetConfiguration: SeverityBasedRuleConfiguration { platform.configurationKey } - private static func parseVersion(string: String) throws -> (Int, Int, Int) { - func parseNumber(_ string: String) throws -> Int { + private static func parseVersion(string: String) throws(Issue) -> (Int, Int, Int) { + func parseNumber(_ string: String) throws(Issue) -> Int { guard let number = Int(string) else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } return number } @@ -67,7 +67,7 @@ struct DeploymentTargetConfiguration: SeverityBasedRuleConfiguration { let parts = string.components(separatedBy: ".") switch parts.count { case 0: - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) case 1: return (try parseNumber(parts[0]), 0, 0) case 2: @@ -122,9 +122,9 @@ struct DeploymentTargetConfiguration: SeverityBasedRuleConfiguration { } // swiftlint:disable:next cyclomatic_complexity - mutating func apply(configuration: Any) throws { + mutating func apply(configuration: Any) throws(Issue) { guard let configuration = configuration as? [String: Any] else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } for (key, value) in configuration { if key == "severity", let value = value as? String { @@ -148,14 +148,14 @@ struct DeploymentTargetConfiguration: SeverityBasedRuleConfiguration { try apply(value: value, to: \.tvOSDeploymentTarget, from: configuration) case tvOSAppExtensionDeploymentTarget.platform.configurationKey: tvOSAppExtensionDeploymentTarget = try Version(platform: .tvOSApplicationExtension, value: value) - default: throw Issue.invalidConfiguration(ruleID: Parent.identifier) + default: throw .invalidConfiguration(ruleID: Parent.identifier) } } } private mutating func apply(value: Any, to target: WritableKeyPath, - from configuration: [String: Any]) throws { + from configuration: [String: Any]) throws(Issue) { let platform = self[keyPath: target].platform self[keyPath: target] = try Version(platform: platform, value: value) if let counterpart = platform.appExtensionCounterpart, diff --git a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/ExpiringTodoConfiguration.swift b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/ExpiringTodoConfiguration.swift index 29f1fb7da0..72bd3d184d 100644 --- a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/ExpiringTodoConfiguration.swift +++ b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/ExpiringTodoConfiguration.swift @@ -11,11 +11,11 @@ struct ExpiringTodoConfiguration: RuleConfiguration { fileprivate(set) var opening: String fileprivate(set) var closing: String - init(fromAny value: Any, context ruleID: String) throws { + init(fromAny value: Any, context ruleID: String) throws(Issue) { guard let dateDelimiters = value as? [String: String], let openingDelimiter = dateDelimiters["opening"], let closingDelimiter = dateDelimiters["closing"] else { - throw Issue.invalidConfiguration(ruleID: ruleID) + throw .invalidConfiguration(ruleID: ruleID) } self.init(opening: openingDelimiter, closing: closingDelimiter) } diff --git a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/FileHeaderConfiguration.swift b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/FileHeaderConfiguration.swift index e23e265ffd..8bdd523320 100644 --- a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/FileHeaderConfiguration.swift +++ b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/FileHeaderConfiguration.swift @@ -26,9 +26,9 @@ struct FileHeaderConfiguration: SeverityBasedRuleConfiguration { private static let defaultRegex = regex("\\bCopyright\\b", options: [.caseInsensitive]) - mutating func apply(configuration: Any) throws { + mutating func apply(configuration: Any) throws(Issue) { guard let configuration = configuration as? [String: String] else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } // Cache the created regexes if possible. diff --git a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/MissingDocsConfiguration.swift b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/MissingDocsConfiguration.swift index f1466c1503..2c0041c04e 100644 --- a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/MissingDocsConfiguration.swift +++ b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/MissingDocsConfiguration.swift @@ -31,9 +31,9 @@ struct MissingDocsConfiguration: RuleConfiguration { $evaluateEffectiveAccessControlLevel.key => .flag(evaluateEffectiveAccessControlLevel) } - mutating func apply(configuration: Any) throws { + mutating func apply(configuration: Any) throws(Issue) { guard let dict = configuration as? [String: Any] else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } if let shouldExcludeExtensions = dict[$excludesExtensions.key] as? Bool { @@ -57,7 +57,7 @@ struct MissingDocsConfiguration: RuleConfiguration { } } - private func parameters(from dict: [String: Any]) throws -> [RuleParameter]? { + private func parameters(from dict: [String: Any]) throws(Issue) -> [RuleParameter]? { var parameters: [RuleParameter] = [] for (key, value) in dict { @@ -67,9 +67,9 @@ struct MissingDocsConfiguration: RuleConfiguration { if let array = [String].array(of: value) { let rules: [RuleParameter] = try array - .map { val -> RuleParameter in + .map { val throws(Issue) -> RuleParameter in guard let acl = AccessControlLevel(description: val) else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } return RuleParameter(severity: severity, value: acl) } @@ -83,7 +83,7 @@ struct MissingDocsConfiguration: RuleConfiguration { } guard parameters.count == parameters.map(\.value).unique.count else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } return parameters.isNotEmpty ? parameters : nil diff --git a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/ModifierOrderConfiguration.swift b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/ModifierOrderConfiguration.swift index d2ce6210c9..cb7e6ef468 100644 --- a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/ModifierOrderConfiguration.swift +++ b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/ModifierOrderConfiguration.swift @@ -24,11 +24,11 @@ struct ModifierOrderConfiguration: SeverityBasedRuleConfiguration { } extension SwiftDeclarationAttributeKind.ModifierGroup: AcceptableByConfigurationElement { - public init(fromAny value: Any, context ruleID: String) throws { + public init(fromAny value: Any, context ruleID: String) throws(Issue) { if let value = value as? String, let newSelf = Self(rawValue: value), newSelf != .atPrefixed { self = newSelf } else { - throw Issue.invalidConfiguration(ruleID: ruleID) + throw .invalidConfiguration(ruleID: ruleID) } } diff --git a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/MultilineParametersConfiguration.swift b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/MultilineParametersConfiguration.swift index 22c3cd470c..ce31957ebe 100644 --- a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/MultilineParametersConfiguration.swift +++ b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/MultilineParametersConfiguration.swift @@ -11,7 +11,7 @@ struct MultilineParametersConfiguration: SeverityBasedRuleConfiguration { @ConfigurationElement(key: "max_number_of_single_line_parameters") private(set) var maxNumberOfSingleLineParameters: Int? - func validate() throws { + func validate() throws(Issue) { guard let maxNumberOfSingleLineParameters else { return } diff --git a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/NameConfiguration.swift b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/NameConfiguration.swift index 6c9ee3e4b4..03bf483a0c 100644 --- a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/NameConfiguration.swift +++ b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/NameConfiguration.swift @@ -49,9 +49,9 @@ struct NameConfiguration: RuleConfiguration, InlinableOptionType { self.validatesStartWithLowercase = validatesStartWithLowercase } - mutating func apply(configuration: Any) throws { + mutating func apply(configuration: Any) throws(Issue) { guard let configurationDict = configuration as? [String: Any] else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } if let minLengthConfiguration = configurationDict[$minLength.key] { diff --git a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/NumberSeparatorConfiguration.swift b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/NumberSeparatorConfiguration.swift index aad4aad6f9..fad3d435d1 100644 --- a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/NumberSeparatorConfiguration.swift +++ b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/NumberSeparatorConfiguration.swift @@ -12,11 +12,11 @@ struct NumberSeparatorConfiguration: SeverityBasedRuleConfiguration { .symbol("\(min) ..< \(max)") } - init(fromAny value: Any, context ruleID: String) throws { + init(fromAny value: Any, context ruleID: String) throws(Issue) { guard let values = value as? [String: Any], let min = values["min"] as? Double, let max = values["max"] as? Double else { - throw Issue.invalidConfiguration(ruleID: ruleID) + throw .invalidConfiguration(ruleID: ruleID) } self.min = min self.max = max diff --git a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/RequiredEnumCaseConfiguration.swift b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/RequiredEnumCaseConfiguration.swift index 2402ed84d3..ecad910d8b 100644 --- a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/RequiredEnumCaseConfiguration.swift +++ b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/RequiredEnumCaseConfiguration.swift @@ -30,9 +30,9 @@ struct RequiredEnumCaseConfiguration: RuleConfiguration { } } - mutating func apply(configuration: Any) throws { + mutating func apply(configuration: Any) throws(Issue) { guard let config = configuration as? [String: [String: String]] else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } register(protocols: config) diff --git a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/UnusedImportConfiguration.swift b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/UnusedImportConfiguration.swift index aed18138ff..ad46ba0f77 100644 --- a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/UnusedImportConfiguration.swift +++ b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/UnusedImportConfiguration.swift @@ -8,13 +8,13 @@ struct TransitiveModuleConfiguration: Equatable, AcceptableByConfi /// The set of modules that can be transitively imported by `importedModule`. let transitivelyImportedModules: [String] - init(fromAny configuration: Any, context _: String) throws { + init(fromAny configuration: Any, context _: String) throws(Issue) { guard let configurationDict = configuration as? [String: Any], Set(configurationDict.keys) == ["module", "allowed_transitive_imports"], let importedModule = configurationDict["module"] as? String, let transitivelyImportedModules = configurationDict["allowed_transitive_imports"] as? [String] else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } self.importedModule = importedModule self.transitivelyImportedModules = transitivelyImportedModules diff --git a/Source/SwiftLintCore/Extensions/NSRegularExpression+SwiftLint.swift b/Source/SwiftLintCore/Extensions/NSRegularExpression+SwiftLint.swift index 76cc1272e9..f9b2ee4725 100644 --- a/Source/SwiftLintCore/Extensions/NSRegularExpression+SwiftLint.swift +++ b/Source/SwiftLintCore/Extensions/NSRegularExpression+SwiftLint.swift @@ -33,11 +33,11 @@ public struct RegularExpression: Hashable, Comparable, ExpressibleByStringLitera /// - Returns: A `RegularExpression` instance. public static func from(pattern: String, options: NSRegularExpression.Options? = nil, - for ruleID: String) throws -> Self { + for ruleID: String) throws(Issue) -> Self { do { return try Self(pattern: pattern, options: options) } catch { - throw Issue.invalidRegexPattern(ruleID: ruleID, pattern: pattern) + throw .invalidRegexPattern(ruleID: ruleID, pattern: pattern) } } } diff --git a/Source/SwiftLintCore/Models/ChildOptionSeverityConfiguration.swift b/Source/SwiftLintCore/Models/ChildOptionSeverityConfiguration.swift index f0f28828e5..b21747e2b2 100644 --- a/Source/SwiftLintCore/Models/ChildOptionSeverityConfiguration.swift +++ b/Source/SwiftLintCore/Models/ChildOptionSeverityConfiguration.swift @@ -22,10 +22,10 @@ public struct ChildOptionSeverityConfiguration: RuleConfiguration, ViolationSeverity(rawValue: optionSeverity.rawValue) } - public mutating func apply(configuration: Any) throws { + public mutating func apply(configuration: Any) throws(Issue) { guard let configString = configuration as? String, let optionSeverity = ChildOptionSeverity(rawValue: configString.lowercased()) else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } self.optionSeverity = optionSeverity } diff --git a/Source/SwiftLintCore/Models/RuleConfigurationDescription.swift b/Source/SwiftLintCore/Models/RuleConfigurationDescription.swift index 1cc140fe31..f175a9e9a0 100644 --- a/Source/SwiftLintCore/Models/RuleConfigurationDescription.swift +++ b/Source/SwiftLintCore/Models/RuleConfigurationDescription.swift @@ -317,7 +317,7 @@ public protocol AcceptableByConfigurationElement { /// - Parameters: /// - value: Value from a configuration. /// - ruleID: The rule's identifier in which context the configuration parsing runs. - init(fromAny value: Any, context ruleID: String) throws + init(fromAny value: Any, context ruleID: String) throws(Issue) /// Make the object an option. /// @@ -337,7 +337,7 @@ public protocol AcceptableByConfigurationElement { /// - Parameters: /// - value: New underlying data for the object. /// - ruleID: The rule's identifier in which context the configuration parsing runs. - mutating func apply(_ value: Any, ruleID: String) throws + mutating func apply(_ value: Any, ruleID: String) throws(Issue) } /// Default implementations which are shortcuts applicable for most of the types conforming to the protocol. @@ -346,7 +346,7 @@ public extension AcceptableByConfigurationElement { RuleConfigurationDescription(options: [key => asOption()]) } - mutating func apply(_ value: Any, ruleID: String) throws { + mutating func apply(_ value: Any, ruleID: String) throws(Issue) { self = try Self(fromAny: value, context: ruleID) } } @@ -537,7 +537,7 @@ extension Optional: AcceptableByConfigurationElement where Wrapped: AcceptableBy self?.asOption() ?? .empty } - public init(fromAny value: Any, context ruleID: String) throws { + public init(fromAny value: Any, context ruleID: String) throws(Issue) { self = try Wrapped(fromAny: value, context: ruleID) } } @@ -549,9 +549,9 @@ struct Symbol: Equatable, AcceptableByConfigurationElement { .symbol(value) } - init(fromAny value: Any, context ruleID: String) throws { + init(fromAny value: Any, context ruleID: String) throws(Issue) { guard let value = value as? String else { - throw Issue.invalidConfiguration(ruleID: ruleID) + throw .invalidConfiguration(ruleID: ruleID) } self.value = value } @@ -562,9 +562,9 @@ extension Bool: AcceptableByConfigurationElement { .flag(self) } - public init(fromAny value: Any, context ruleID: String) throws { + public init(fromAny value: Any, context ruleID: String) throws(Issue) { guard let value = value as? Self else { - throw Issue.invalidConfiguration(ruleID: ruleID) + throw .invalidConfiguration(ruleID: ruleID) } self = value } @@ -575,9 +575,9 @@ extension String: AcceptableByConfigurationElement { .string(self) } - public init(fromAny value: Any, context ruleID: String) throws { + public init(fromAny value: Any, context ruleID: String) throws(Issue) { guard let value = value as? Self else { - throw Issue.invalidConfiguration(ruleID: ruleID) + throw .invalidConfiguration(ruleID: ruleID) } self = value } @@ -588,9 +588,11 @@ extension Array: AcceptableByConfigurationElement where Element: AcceptableByCon .list(map { $0.asOption() }) } - public init(fromAny value: Any, context ruleID: String) throws { + public init(fromAny value: Any, context ruleID: String) throws(Issue) { let values = value as? [Any] ?? [value] - self = try values.map { try Element(fromAny: $0, context: ruleID) } + self = try values.map { value throws(Issue) in + try Element(fromAny: value, context: ruleID) + } } } @@ -599,7 +601,7 @@ extension Set: AcceptableByConfigurationElement where Element: AcceptableByConfi sorted().asOption() } - public init(fromAny value: Any, context ruleID: String) throws { + public init(fromAny value: Any, context ruleID: String) throws(Issue) { self = Set(try [Element].init(fromAny: value, context: ruleID)) } } @@ -609,9 +611,9 @@ extension Int: AcceptableByConfigurationElement { .integer(self) } - public init(fromAny value: Any, context ruleID: String) throws { + public init(fromAny value: Any, context ruleID: String) throws(Issue) { guard let value = value as? Self else { - throw Issue.invalidConfiguration(ruleID: ruleID) + throw .invalidConfiguration(ruleID: ruleID) } self = value } @@ -622,9 +624,9 @@ extension Double: AcceptableByConfigurationElement { .float(self) } - public init(fromAny value: Any, context ruleID: String) throws { + public init(fromAny value: Any, context ruleID: String) throws(Issue) { guard let value = value as? Self else { - throw Issue.invalidConfiguration(ruleID: ruleID) + throw .invalidConfiguration(ruleID: ruleID) } self = value } @@ -635,11 +637,11 @@ extension RegularExpression: AcceptableByConfigurationElement { .string(pattern) } - public init(fromAny value: Any, context ruleID: String) throws { + public init(fromAny value: Any, context ruleID: String) throws(Issue) { guard let value = value as? String else { - throw Issue.invalidConfiguration(ruleID: ruleID) + throw .invalidConfiguration(ruleID: ruleID) } - self = try Self(pattern: value) + self = try .from(pattern: value, for: ruleID) } } @@ -657,12 +659,12 @@ public extension AcceptableByConfigurationElement where Self: RuleConfiguration return RuleConfigurationDescription(options: [key => asOption()]) } - mutating func apply(_ value: Any, ruleID _: String) throws { + mutating func apply(_ value: Any, ruleID _: String) throws(Issue) { try apply(configuration: value) } - init(fromAny _: Any, context _: String) throws { - throw Issue.genericError("Do not call this initializer") + init(fromAny _: Any, context _: String) throws(Issue) { + throw .genericError("Do not call this initializer") } } diff --git a/Source/SwiftLintCore/Models/RuleList.swift b/Source/SwiftLintCore/Models/RuleList.swift index 74978e997f..ca3f8cfb42 100644 --- a/Source/SwiftLintCore/Models/RuleList.swift +++ b/Source/SwiftLintCore/Models/RuleList.swift @@ -40,13 +40,14 @@ public struct RuleList { // MARK: - Internal - package func allRulesWrapped(configurationDict: [String: Any] = [:]) throws -> [ConfigurationRuleWrapper] { + package func allRulesWrapped(configurationDict: [String: Any] = [:]) + throws(RuleListError) -> [ConfigurationRuleWrapper] { var rules = [String: ConfigurationRuleWrapper]() // Add rules where configuration exists for (key, configuration) in configurationDict { guard let identifier = identifier(for: key), let ruleType = list[identifier] else { continue } - guard rules[identifier] == nil else { throw RuleListError.duplicatedConfigurations(rule: ruleType) } + guard rules[identifier] == nil else { throw .duplicatedConfigurations(rule: ruleType) } do { let configuredRule = try ruleType.init(configuration: configuration) let isConfigured = (configuration as? [String: Any])?.isEmpty == false diff --git a/Source/SwiftLintCore/Models/SeverityConfiguration.swift b/Source/SwiftLintCore/Models/SeverityConfiguration.swift index 705801e5b7..201402fe26 100644 --- a/Source/SwiftLintCore/Models/SeverityConfiguration.swift +++ b/Source/SwiftLintCore/Models/SeverityConfiguration.swift @@ -19,17 +19,17 @@ public struct SeverityConfiguration: SeverityBasedRuleConfiguratio self.severity = severity } - public mutating func apply(configuration: Any) throws { + public mutating func apply(configuration: Any) throws(Issue) { let configString = configuration as? String let configDict = configuration as? [String: Any] if let severityString: String = configString ?? configDict?[$severity.key] as? String { if let severity = ViolationSeverity(rawValue: severityString.lowercased()) { self.severity = severity } else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } } else { - throw Issue.nothingApplied(ruleID: Parent.identifier) + throw .nothingApplied(ruleID: Parent.identifier) } } } diff --git a/Source/SwiftLintCore/Protocols/RuleConfiguration.swift b/Source/SwiftLintCore/Protocols/RuleConfiguration.swift index c750417df4..3a64250e35 100644 --- a/Source/SwiftLintCore/Protocols/RuleConfiguration.swift +++ b/Source/SwiftLintCore/Protocols/RuleConfiguration.swift @@ -12,11 +12,11 @@ public protocol RuleConfiguration: Equatable { /// - parameter configuration: The untyped configuration value to apply. /// /// - throws: Throws if the configuration is not in the expected format. - mutating func apply(configuration: Any) throws + mutating func apply(configuration: Any) throws(Issue) /// Run a sanity check on the configuration, perform optional postprocessing steps and/or warn about potential /// issues. - mutating func validate() throws + mutating func validate() throws(Issue) } /// A configuration for a rule that allows to configure at least the severity. @@ -35,7 +35,7 @@ public extension SeverityBasedRuleConfiguration { public extension RuleConfiguration { var parameterDescription: RuleConfigurationDescription? { nil } - func validate() throws { + func validate() throws(Issue) { // Do nothing by default. } } diff --git a/Source/SwiftLintCore/RuleConfigurations/RegexConfiguration.swift b/Source/SwiftLintCore/RuleConfigurations/RegexConfiguration.swift index 6329261b45..77416fcd46 100644 --- a/Source/SwiftLintCore/RuleConfigurations/RegexConfiguration.swift +++ b/Source/SwiftLintCore/RuleConfigurations/RegexConfiguration.swift @@ -57,10 +57,10 @@ public struct RegexConfiguration: SeverityBasedRuleConfiguration, self.identifier = identifier } - public mutating func apply(configuration: Any) throws { + public mutating func apply(configuration: Any) throws(Issue) { guard let configurationDict = configuration as? [String: Any], let regexString = configurationDict[$regex.key] as? String else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } regex = try .from(pattern: regexString, for: Parent.identifier) @@ -68,7 +68,7 @@ public struct RegexConfiguration: SeverityBasedRuleConfiguration, if let includedString = configurationDict["included"] as? String { included = [try .from(pattern: includedString, for: Parent.identifier)] } else if let includedArray = configurationDict["included"] as? [String] { - included = try includedArray.map { pattern in + included = try includedArray.map { pattern throws(Issue) in try .from(pattern: pattern, for: Parent.identifier) } } @@ -76,7 +76,7 @@ public struct RegexConfiguration: SeverityBasedRuleConfiguration, if let excludedString = configurationDict["excluded"] as? String { excluded = [try .from(pattern: excludedString, for: Parent.identifier)] } else if let excludedArray = configurationDict["excluded"] as? [String] { - excluded = try excludedArray.map { pattern in + excluded = try excludedArray.map { pattern throws(Issue) in try .from(pattern: pattern, for: Parent.identifier) } } @@ -92,7 +92,7 @@ public struct RegexConfiguration: SeverityBasedRuleConfiguration, } if let captureGroup = configurationDict["capture_group"] as? Int { guard (0 ... regex.numberOfCaptureGroups).contains(captureGroup) else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } self.captureGroup = captureGroup } @@ -119,7 +119,7 @@ public struct RegexConfiguration: SeverityBasedRuleConfiguration, } } - private func excludedMatchKinds(from configurationDict: [String: Any]) throws -> Set { + private func excludedMatchKinds(from configurationDict: [String: Any]) throws(Issue) -> Set { let matchKinds = [String].array(of: configurationDict["match_kinds"]) let excludedMatchKinds = [String].array(of: configurationDict["excluded_match_kinds"]) @@ -131,18 +131,18 @@ public struct RegexConfiguration: SeverityBasedRuleConfiguration, case (nil, nil): return .init() case (.some, .some): - throw Issue.genericWarning( + throw .genericWarning( "The configuration keys 'match_kinds' and 'excluded_match_kinds' cannot appear at the same time." ) } } - private func toSyntaxKinds(_ names: [String]) throws -> Set { - let kinds = try names.map { - if let kind = SyntaxKind(shortName: $0) { + private func toSyntaxKinds(_ names: [String]) throws(Issue) -> Set { + let kinds = try names.map { name throws(Issue) in + if let kind = SyntaxKind(shortName: name) { return kind } - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } return Set(kinds) } diff --git a/Source/SwiftLintCore/RuleConfigurations/SeverityLevelsConfiguration.swift b/Source/SwiftLintCore/RuleConfigurations/SeverityLevelsConfiguration.swift index e23f082b05..937579e6e2 100644 --- a/Source/SwiftLintCore/RuleConfigurations/SeverityLevelsConfiguration.swift +++ b/Source/SwiftLintCore/RuleConfigurations/SeverityLevelsConfiguration.swift @@ -27,7 +27,7 @@ public struct SeverityLevelsConfiguration: RuleConfiguration, Inli return [RuleParameter(severity: .warning, value: warning)] } - public mutating func apply(configuration: Any) throws { + public mutating func apply(configuration: Any) throws(Issue) { if let configurationArray = [Int].array(of: configuration), configurationArray.isNotEmpty { warning = configurationArray[0] error = (configurationArray.count > 1) ? configurationArray[1] : nil @@ -36,7 +36,7 @@ public struct SeverityLevelsConfiguration: RuleConfiguration, Inli if let warning = warningValue as? Int { self.warning = warning } else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } } if let errorValue = configDict[$error.key] { @@ -45,13 +45,13 @@ public struct SeverityLevelsConfiguration: RuleConfiguration, Inli } else if let error = errorValue as? Int { self.error = error } else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } } else { self.error = nil } } else { - throw Issue.nothingApplied(ruleID: Parent.identifier) + throw .nothingApplied(ruleID: Parent.identifier) } } } diff --git a/Source/SwiftLintCoreMacros/RuleConfigurationMacros.swift b/Source/SwiftLintCoreMacros/RuleConfigurationMacros.swift index 51ba4427d7..413f461d16 100644 --- a/Source/SwiftLintCoreMacros/RuleConfigurationMacros.swift +++ b/Source/SwiftLintCoreMacros/RuleConfigurationMacros.swift @@ -48,7 +48,7 @@ enum AutoConfigParser: MemberMacro { } } return [ - DeclSyntax(try FunctionDeclSyntax("mutating func apply(configuration: Any) throws") { + DeclSyntax(try FunctionDeclSyntax("mutating func apply(configuration: Any) throws(Issue)") { for option in nonInlinedOptions { """ if $\(raw: option).key.isEmpty { @@ -60,7 +60,7 @@ enum AutoConfigParser: MemberMacro { """ do { try \(raw: option).apply(configuration, ruleID: Parent.identifier) - } catch let issue as Issue where issue == Issue.nothingApplied(ruleID: Parent.identifier) { + } catch let issue where issue == Issue.nothingApplied(ruleID: Parent.identifier) { // Acceptable. Continue. } """ @@ -68,7 +68,7 @@ enum AutoConfigParser: MemberMacro { """ guard let configuration = configuration as? [String: Any] else { \(raw: inlinedOptions.isEmpty - ? "throw Issue.invalidConfiguration(ruleID: Parent.identifier)" + ? "throw .invalidConfiguration(ruleID: Parent.identifier)" : "return") } """ @@ -114,11 +114,11 @@ enum AcceptableByConfigurationElement: ExtensionMacro { try ExtensionDeclSyntax(""" extension \(type): AcceptableByConfigurationElement { \(raw: accessLevel)func asOption() -> OptionType { .symbol(rawValue) } - \(raw: accessLevel)init(fromAny value: Any, context ruleID: String) throws { + \(raw: accessLevel)init(fromAny value: Any, context ruleID: String) throws(Issue) { if let value = value as? String, let newSelf = Self(rawValue: value) { self = newSelf } else { - throw Issue.invalidConfiguration(ruleID: ruleID) + throw .invalidConfiguration(ruleID: ruleID) } } } diff --git a/Source/SwiftLintFramework/Configuration+CommandLine.swift b/Source/SwiftLintFramework/Configuration+CommandLine.swift index 987542a5be..37970c4232 100644 --- a/Source/SwiftLintFramework/Configuration+CommandLine.swift +++ b/Source/SwiftLintFramework/Configuration+CommandLine.swift @@ -11,7 +11,7 @@ private actor CounterActor { } } -private func readFilesFromScriptInputFiles() throws -> [SwiftLintFile] { +private func readFilesFromScriptInputFiles() throws(SwiftLintError) -> [SwiftLintFile] { let count = try fileCount(from: "SCRIPT_INPUT_FILE_COUNT") return (0.. [SwiftLintFile] { } } -private func readFilesFromScriptInputFileLists() throws -> [SwiftLintFile] { +private func readFilesFromScriptInputFileLists() throws(SwiftLintError) -> [SwiftLintFile] { let count = try fileCount(from: "SCRIPT_INPUT_FILE_LIST_COUNT") return (0.. [SwiftLintFile] { } } -private func fileCount(from envVar: String) throws -> Int { +private func fileCount(from envVar: String) throws(SwiftLintError) -> Int { guard let countString = ProcessInfo.processInfo.environment[envVar] else { - throw SwiftLintError.usageError(description: "\(envVar) variable not set") + throw .usageError(description: "\(envVar) variable not set") } guard let count = Int(countString) else { - throw SwiftLintError.usageError(description: "\(envVar) did not specify a number") + throw .usageError(description: "\(envVar) did not specify a number") } return count } @@ -103,10 +103,10 @@ extension Configuration { return result.flatMap { $0 } } - private func groupFiles(_ files: [SwiftLintFile], visitor: LintableFilesVisitor) throws + private func groupFiles(_ files: [SwiftLintFile], visitor: LintableFilesVisitor) throws(SwiftLintError) -> [Configuration: [SwiftLintFile]] { if files.isEmpty && !visitor.allowZeroLintableFiles { - throw SwiftLintError.usageError( + throw .usageError( description: "No lintable files found at paths: '\(visitor.options.paths.joined(separator: ", "))'" ) } @@ -241,14 +241,14 @@ extension Configuration { linters.asyncMap(visit) } - fileprivate func getFiles(with visitor: LintableFilesVisitor) async throws -> [SwiftLintFile] { + fileprivate func getFiles(with visitor: LintableFilesVisitor) async throws(SwiftLintError) -> [SwiftLintFile] { let options = visitor.options if options.useSTDIN { let stdinData = FileHandle.standardInput.readDataToEndOfFile() if let stdinString = String(data: stdinData, encoding: .utf8) { return [SwiftLintFile(contents: stdinString)] } - throw SwiftLintError.usageError(description: "stdin isn't a UTF8-encoded string") + throw .usageError(description: "stdin isn't a UTF8-encoded string") } if options.useScriptInputFiles || options.useScriptInputFileLists { let files = try options.useScriptInputFiles diff --git a/Source/SwiftLintFramework/LintableFilesVisitor.swift b/Source/SwiftLintFramework/LintableFilesVisitor.swift index c6c630e335..5f42d49c9b 100644 --- a/Source/SwiftLintFramework/LintableFilesVisitor.swift +++ b/Source/SwiftLintFramework/LintableFilesVisitor.swift @@ -129,10 +129,11 @@ struct LintableFilesVisitor { } } - private static func loadCompilerInvocations(_ options: LintOrAnalyzeOptions) throws -> CompilerInvocations { + private static func loadCompilerInvocations(_ options: LintOrAnalyzeOptions) + throws(SwiftLintError) -> CompilerInvocations { if let path = options.compilerLogPath { guard let compilerInvocations = self.loadLogCompilerInvocations(path) else { - throw SwiftLintError.usageError(description: "Could not read compiler log at path: '\(path)'") + throw .usageError(description: "Could not read compiler log at path: '\(path)'") } return .buildLog(compilerInvocations: compilerInvocations) @@ -141,13 +142,13 @@ struct LintableFilesVisitor { do { return .compilationDatabase(compileCommands: try self.loadCompileCommands(path)) } catch { - throw SwiftLintError.usageError( + throw .usageError( description: "Could not read compilation database at path: '\(path)' \(error.localizedDescription)" ) } } - throw SwiftLintError.usageError(description: "Could not read compiler invocations") + throw .usageError(description: "Could not read compiler invocations") } private static func loadLogCompilerInvocations(_ path: String) -> [[String]]? { diff --git a/Source/SwiftLintFramework/Rules/CustomRules.swift b/Source/SwiftLintFramework/Rules/CustomRules.swift index ec6a4f9000..b3ec1ae525 100644 --- a/Source/SwiftLintFramework/Rules/CustomRules.swift +++ b/Source/SwiftLintFramework/Rules/CustomRules.swift @@ -14,9 +14,9 @@ struct CustomRulesConfiguration: RuleConfiguration, CacheDescriptionProvider { } var customRuleConfigurations = [RegexConfiguration]() - mutating func apply(configuration: Any) throws { + mutating func apply(configuration: Any) throws(Issue) { guard let configurationDict = configuration as? [String: Any] else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } for (key, value) in configurationDict { diff --git a/Source/swiftlint/Commands/Rules.swift b/Source/swiftlint/Commands/Rules.swift index ea79fc957a..8304caf211 100644 --- a/Source/swiftlint/Commands/Rules.swift +++ b/Source/swiftlint/Commands/Rules.swift @@ -22,11 +22,11 @@ extension SwiftLint { @Argument(help: "The rule identifier to display description for") var ruleID: String? - func run() throws { + func run() throws(SwiftLintError) { let configuration = Configuration(configurationFiles: [config].compactMap({ $0 })) if let ruleID { guard let rule = RuleRegistry.shared.rule(forID: ruleID) else { - throw SwiftLintError.usageError(description: "No rule with identifier: \(ruleID)") + throw .usageError(description: "No rule with identifier: \(ruleID)") } printDescription(for: rule, with: configuration) return diff --git a/Tests/FrameworkTests/RuleConfigurationDescriptionTests.swift b/Tests/FrameworkTests/RuleConfigurationDescriptionTests.swift index 8e15565c37..655a890e7b 100644 --- a/Tests/FrameworkTests/RuleConfigurationDescriptionTests.swift +++ b/Tests/FrameworkTests/RuleConfigurationDescriptionTests.swift @@ -221,7 +221,7 @@ final class RuleConfigurationDescriptionTests: SwiftLintTestCase { @ConfigurationElement(key: "invisible") var invisible = true - mutating func apply(configuration _: Any) throws { /* conformance for test */ } + mutating func apply(configuration _: Any) throws(Issue) { /* conformance for test */ } func isEqualTo(_: some RuleConfiguration) -> Bool { false } } diff --git a/Tests/MacroTests/AcceptableByConfigurationElementTests.swift b/Tests/MacroTests/AcceptableByConfigurationElementTests.swift index b63c5a6a2b..920d5a0dc0 100644 --- a/Tests/MacroTests/AcceptableByConfigurationElementTests.swift +++ b/Tests/MacroTests/AcceptableByConfigurationElementTests.swift @@ -59,11 +59,11 @@ final class AcceptableByConfigurationElementTests: XCTestCase { private func asOption() -> OptionType { .symbol(rawValue) } - private init(fromAny value: Any, context ruleID: String) throws { + private init(fromAny value: Any, context ruleID: String) throws(Issue) { if let value = value as? String, let newSelf = Self(rawValue: value) { self = newSelf } else { - throw Issue.invalidConfiguration(ruleID: ruleID) + throw .invalidConfiguration(ruleID: ruleID) } } } @@ -87,11 +87,11 @@ final class AcceptableByConfigurationElementTests: XCTestCase { public func asOption() -> OptionType { .symbol(rawValue) } - public init(fromAny value: Any, context ruleID: String) throws { + public init(fromAny value: Any, context ruleID: String) throws(Issue) { if let value = value as? String, let newSelf = Self(rawValue: value) { self = newSelf } else { - throw Issue.invalidConfiguration(ruleID: ruleID) + throw .invalidConfiguration(ruleID: ruleID) } } } diff --git a/Tests/MacroTests/AutoConfigParserTests.swift b/Tests/MacroTests/AutoConfigParserTests.swift index 86ce276120..852c6cb356 100644 --- a/Tests/MacroTests/AutoConfigParserTests.swift +++ b/Tests/MacroTests/AutoConfigParserTests.swift @@ -36,9 +36,9 @@ final class AutoConfigParserTests: XCTestCase { """ struct S { - mutating func apply(configuration: Any) throws { + mutating func apply(configuration: Any) throws(Issue) { guard let configuration = configuration as? [String: Any] else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } if !supportedKeys.isSuperset(of: configuration.keys) { let unknownKeys = Set(configuration.keys).subtracting(supportedKeys) @@ -71,7 +71,7 @@ final class AutoConfigParserTests: XCTestCase { @ConfigurationElement(key: "name") var eB = 2 - mutating func apply(configuration: Any) throws { + mutating func apply(configuration: Any) throws(Issue) { if $eA.key.isEmpty { $eA.key = "e_a" } @@ -79,7 +79,7 @@ final class AutoConfigParserTests: XCTestCase { $eB.key = "e_b" } guard let configuration = configuration as? [String: Any] else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } if let value = configuration[$eA.key] { try eA.apply(value, ruleID: Parent.identifier) @@ -122,7 +122,7 @@ final class AutoConfigParserTests: XCTestCase { @ConfigurationElement(inline: false) var eC = 3 - mutating func apply(configuration: Any) throws { + mutating func apply(configuration: Any) throws(Issue) { if $eA.key.isEmpty { $eA.key = "e_a" } @@ -131,7 +131,7 @@ final class AutoConfigParserTests: XCTestCase { } do { try eB.apply(configuration, ruleID: Parent.identifier) - } catch let issue as Issue where issue == Issue.nothingApplied(ruleID: Parent.identifier) { + } catch let issue where issue == Issue.nothingApplied(ruleID: Parent.identifier) { // Acceptable. Continue. } guard let configuration = configuration as? [String: Any] else { @@ -166,9 +166,9 @@ final class AutoConfigParserTests: XCTestCase { """ struct S: SeverityBasedRuleConfiguration { - mutating func apply(configuration: Any) throws { + mutating func apply(configuration: Any) throws(Issue) { guard let configuration = configuration as? [String: Any] else { - throw Issue.invalidConfiguration(ruleID: Parent.identifier) + throw .invalidConfiguration(ruleID: Parent.identifier) } if !supportedKeys.isSuperset(of: configuration.keys) { let unknownKeys = Set(configuration.keys).subtracting(supportedKeys) @@ -207,7 +207,7 @@ final class AutoConfigParserTests: XCTestCase { @ConfigurationElement var foo = 2 - mutating func apply(configuration: Any) throws { + mutating func apply(configuration: Any) throws(Issue) { if $severityConfiguration.key.isEmpty { $severityConfiguration.key = "severity_configuration" } @@ -216,7 +216,7 @@ final class AutoConfigParserTests: XCTestCase { } do { try severityConfiguration.apply(configuration, ruleID: Parent.identifier) - } catch let issue as Issue where issue == Issue.nothingApplied(ruleID: Parent.identifier) { + } catch let issue where issue == Issue.nothingApplied(ruleID: Parent.identifier) { // Acceptable. Continue. } guard let configuration = configuration as? [String: Any] else {