Adopt typed throws where possible (#5922)

This commit is contained in:
Danny Mösch
2025-09-27 19:11:46 +02:00
committed by GitHub
parent 0e2198d086
commit aa67f5ac13
27 changed files with 121 additions and 119 deletions
-2
View File
@@ -39,8 +39,6 @@ jobs:
strategy:
matrix:
include:
- macOS: '14'
xcode: '15.4'
- macOS: '15'
xcode: '16.4'
- macOS: '26'
@@ -47,15 +47,15 @@ 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)
}
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
}
@@ -63,7 +63,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:
@@ -118,9 +118,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 {
@@ -144,14 +144,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<Self, Version>,
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,
@@ -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)
}
@@ -25,9 +25,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.
@@ -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<AccessControlLevel>]? {
private func parameters(from dict: [String: Any]) throws(Issue) -> [RuleParameter<AccessControlLevel>]? {
var parameters: [RuleParameter<AccessControlLevel>] = []
for (key, value) in dict {
@@ -67,9 +67,9 @@ struct MissingDocsConfiguration: RuleConfiguration {
if let array = [String].array(of: value) {
let rules: [RuleParameter<AccessControlLevel>] = try array
.map { val -> RuleParameter<AccessControlLevel> in
.map { val throws(Issue) -> RuleParameter<AccessControlLevel> in
guard let acl = AccessControlLevel(description: val) else {
throw Issue.invalidConfiguration(ruleID: Parent.identifier)
throw .invalidConfiguration(ruleID: Parent.identifier)
}
return RuleParameter<AccessControlLevel>(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
@@ -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)
}
}
@@ -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
}
@@ -49,9 +49,9 @@ struct NameConfiguration<Parent: Rule>: 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] {
@@ -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
@@ -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)
@@ -8,13 +8,13 @@ struct TransitiveModuleConfiguration<Parent: Rule>: 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
@@ -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)
}
}
}
@@ -22,10 +22,10 @@ public struct ChildOptionSeverityConfiguration<Parent: Rule>: 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
}
@@ -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,13 +624,13 @@ extension Double: AcceptableByConfigurationElement {
.float(self)
}
public init(fromAny value: Any, context ruleID: String) throws {
public init(fromAny value: Any, context ruleID: String) throws(Issue) {
if let value = value as? Self {
self = value
} else if let value = value as? Int {
self = Double(value)
} else {
throw Issue.invalidConfiguration(ruleID: ruleID)
throw .invalidConfiguration(ruleID: ruleID)
}
}
}
@@ -638,11 +640,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)
}
}
@@ -660,12 +662,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")
}
}
+3 -2
View File
@@ -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
@@ -19,17 +19,17 @@ public struct SeverityConfiguration<Parent: Rule>: 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)
}
}
}
@@ -12,11 +12,11 @@ public protocol RuleConfiguration: Equatable, Sendable {
/// - 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.
}
}
@@ -70,10 +70,10 @@ public struct RegexConfiguration<Parent: Rule>: SeverityBasedRuleConfiguration,
}
// swiftlint:disable:next cyclomatic_complexity
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)
@@ -81,7 +81,7 @@ public struct RegexConfiguration<Parent: Rule>: 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)
}
}
@@ -89,7 +89,7 @@ public struct RegexConfiguration<Parent: Rule>: 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)
}
}
@@ -105,7 +105,7 @@ public struct RegexConfiguration<Parent: Rule>: 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
}
@@ -140,7 +140,7 @@ public struct RegexConfiguration<Parent: Rule>: SeverityBasedRuleConfiguration,
}
}
private func excludedMatchKinds(from configurationDict: [String: Any]) throws -> Set<SyntaxKind> {
private func excludedMatchKinds(from configurationDict: [String: Any]) throws(Issue) -> Set<SyntaxKind> {
let matchKinds = [String].array(of: configurationDict["match_kinds"])
let excludedMatchKinds = [String].array(of: configurationDict["excluded_match_kinds"])
@@ -152,18 +152,18 @@ public struct RegexConfiguration<Parent: Rule>: 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<SyntaxKind> {
let kinds = try names.map {
if let kind = SyntaxKind(shortName: $0) {
private func toSyntaxKinds(_ names: [String]) throws(Issue) -> Set<SyntaxKind> {
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)
}
@@ -27,7 +27,7 @@ public struct SeverityLevelsConfiguration<Parent: Rule>: 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
@@ -37,7 +37,7 @@ public struct SeverityLevelsConfiguration<Parent: Rule>: 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] {
@@ -46,13 +46,13 @@ public struct SeverityLevelsConfiguration<Parent: Rule>: 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 if warningValue != nil {
self.error = nil
}
} else {
throw Issue.nothingApplied(ruleID: Parent.identifier)
throw .nothingApplied(ruleID: Parent.identifier)
}
}
}
@@ -49,7 +49,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 {
@@ -61,7 +61,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.
}
"""
@@ -69,7 +69,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")
}
"""
@@ -115,11 +115,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)
}
}
}
@@ -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..<count).compactMap { fileNumber in
do {
@@ -31,7 +31,7 @@ private func readFilesFromScriptInputFiles() throws -> [SwiftLintFile] {
}
}
private func readFilesFromScriptInputFileLists() throws -> [SwiftLintFile] {
private func readFilesFromScriptInputFileLists() throws(SwiftLintError) -> [SwiftLintFile] {
let count = try fileCount(from: "SCRIPT_INPUT_FILE_LIST_COUNT")
return (0..<count).flatMap { fileNumber in
var filesToLint: [SwiftLintFile] = []
@@ -59,12 +59,12 @@ private func readFilesFromScriptInputFileLists() throws -> [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: ", "))'"
)
}
@@ -236,14 +236,14 @@ extension Configuration {
linters.asyncMap(visit)
}
fileprivate func getFiles(with visitor: LintableFilesVisitor) throws -> [SwiftLintFile] {
fileprivate func getFiles(with visitor: LintableFilesVisitor) 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
@@ -119,10 +119,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)
@@ -131,13 +132,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]]? {
@@ -20,9 +20,9 @@ struct CustomRulesConfiguration: RuleConfiguration, CacheDescriptionProvider {
var customRuleConfigurations = [RegexConfiguration<Parent>]()
var defaultExecutionMode: RegexConfiguration<Parent>.ExecutionMode?
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)
}
// Parse default execution mode if present
+2 -2
View File
@@ -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
@@ -233,7 +233,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 }
}
@@ -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)
}
}
}
+10 -10
View File
@@ -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 {