mirror of
https://github.com/realm/SwiftLint.git
synced 2026-05-07 20:12:49 +00:00
a6c4fd98bc
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.
94 lines
3.3 KiB
Swift
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
|
|
}
|
|
}
|