Files
Danny Mösch a6c4fd98bc Move files from SwiftLintCore to SwiftLintFramework
Ideally, SwiftLintCore would some day only contain components
that are needed to define rules. Consequently, it would be the
only bundle required to import for (external) rule development.
2024-12-23 12:51:43 +01:00

94 lines
3.3 KiB
Swift

/// All possible rule list configuration errors.
public enum RuleListError: Error {
/// The rule list contains more than one configuration for the specified rule.
case duplicatedConfigurations(rule: any Rule.Type)
}
/// A list of available SwiftLint rules.
public struct RuleList {
/// The rules contained in this list.
public let list: [String: any Rule.Type]
private let aliases: [String: String]
// MARK: - Initializers
/// Creates a `RuleList` by specifying all its rules.
///
/// - parameter rules: The rules to be contained in this list.
public init(rules: any Rule.Type...) {
self.init(rules: rules)
}
/// Creates a `RuleList` by specifying all its rules.
///
/// - parameter rules: The rules to be contained in this list.
public init(rules: [any Rule.Type]) {
var tmpList = [String: any Rule.Type]()
var tmpAliases = [String: String]()
for rule in rules {
let identifier = rule.identifier
tmpList[identifier] = rule
for alias in rule.description.deprecatedAliases {
tmpAliases[alias] = identifier
}
tmpAliases[identifier] = identifier
}
list = tmpList
aliases = tmpAliases
}
// MARK: - Internal
package func allRulesWrapped(configurationDict: [String: Any] = [:]) throws -> [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) }
do {
let configuredRule = try ruleType.init(configuration: configuration)
let isConfigured = (configuration as? [String: Any])?.isEmpty == false
|| ([Any].array(of: configuration))?.isEmpty == false
rules[identifier] = ConfigurationRuleWrapper(
rule: configuredRule,
initializedWithNonEmptyConfiguration: isConfigured
)
continue
} catch let issue as Issue {
issue.print()
} catch {
Issue.invalidConfiguration(ruleID: identifier).print()
}
rules[identifier] = (ruleType.init(), false)
}
// Add remaining rules without configuring them
for (identifier, ruleType) in list where rules[identifier] == nil {
rules[identifier] = (ruleType.init(), false)
}
return Array(rules.values)
}
package func identifier(for alias: String) -> String? {
aliases[alias]
}
package func allValidIdentifiers() -> [String] {
list.flatMap { _, rule -> [String] in
rule.description.allIdentifiers
}
}
}
extension RuleList: Equatable {
public static func == (lhs: RuleList, rhs: RuleList) -> Bool {
lhs.list.map(\.0) == rhs.list.map(\.0)
// swiftlint:disable:next prefer_key_path
&& lhs.list.map { $0.1.description } == rhs.list.map { $0.1.description }
&& lhs.aliases == rhs.aliases
}
}