mirror of
https://github.com/realm/SwiftLint.git
synced 2026-05-07 20:12:49 +00:00
166 lines
7.3 KiB
Swift
166 lines
7.3 KiB
Swift
import Foundation
|
|
|
|
struct DeploymentTargetConfiguration: SeverityBasedRuleConfiguration {
|
|
typealias Parent = DeploymentTargetRule
|
|
|
|
enum Platform: String {
|
|
case iOS
|
|
case iOSApplicationExtension
|
|
case macOS
|
|
case macOSApplicationExtension
|
|
case watchOS
|
|
case watchOSApplicationExtension
|
|
case tvOS
|
|
case tvOSApplicationExtension
|
|
case OSX
|
|
|
|
var configurationKey: String {
|
|
rawValue + "_deployment_target"
|
|
}
|
|
|
|
var appExtensionCounterpart: WritableKeyPath<DeploymentTargetConfiguration, Version>? {
|
|
switch self {
|
|
case .iOS: \DeploymentTargetConfiguration.iOSAppExtensionDeploymentTarget
|
|
case .macOS: \DeploymentTargetConfiguration.macOSAppExtensionDeploymentTarget
|
|
case .watchOS: \DeploymentTargetConfiguration.watchOSAppExtensionDeploymentTarget
|
|
case .tvOS: \DeploymentTargetConfiguration.tvOSAppExtensionDeploymentTarget
|
|
default: nil
|
|
}
|
|
}
|
|
}
|
|
|
|
struct Version: Equatable, Comparable {
|
|
let platform: Platform
|
|
var major: Int
|
|
var minor: Int
|
|
var patch: Int
|
|
|
|
var stringValue: String {
|
|
if patch > 0 {
|
|
return "\(major).\(minor).\(patch)"
|
|
}
|
|
return "\(major).\(minor)"
|
|
}
|
|
|
|
init(platform: Platform, major: Int, minor: Int = 0, patch: Int = 0) {
|
|
self.platform = platform
|
|
self.major = major
|
|
self.minor = minor
|
|
self.patch = patch
|
|
}
|
|
|
|
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(Issue) -> (Int, Int, Int) {
|
|
func parseNumber(_ string: String) throws(Issue) -> Int {
|
|
guard let number = Int(string) else {
|
|
throw .invalidConfiguration(ruleID: Parent.identifier)
|
|
}
|
|
return number
|
|
}
|
|
|
|
let parts = string.components(separatedBy: ".")
|
|
switch parts.count {
|
|
case 0:
|
|
throw .invalidConfiguration(ruleID: Parent.identifier)
|
|
case 1:
|
|
return (try parseNumber(parts[0]), 0, 0)
|
|
case 2:
|
|
return (try parseNumber(parts[0]), try parseNumber(parts[1]), 0)
|
|
default:
|
|
return (try parseNumber(parts[0]), try parseNumber(parts[1]), try parseNumber(parts[2]))
|
|
}
|
|
}
|
|
|
|
static func == (lhs: Self, rhs: Self) -> Bool {
|
|
lhs.major == rhs.major && lhs.minor == rhs.minor && lhs.patch == rhs.patch
|
|
}
|
|
|
|
static func < (lhs: Self, rhs: Self) -> Bool {
|
|
if lhs.major != rhs.major {
|
|
return lhs.major < rhs.major
|
|
}
|
|
if lhs.minor != rhs.minor {
|
|
return lhs.minor < rhs.minor
|
|
}
|
|
return lhs.patch < rhs.patch
|
|
}
|
|
}
|
|
|
|
private(set) var iOSDeploymentTarget = Version(platform: .iOS, major: 7)
|
|
private(set) var iOSAppExtensionDeploymentTarget = Version(platform: .iOSApplicationExtension, major: 7)
|
|
private(set) var macOSDeploymentTarget = Version(platform: .macOS, major: 10, minor: 9)
|
|
private(set) var macOSAppExtensionDeploymentTarget = Version(platform: .macOSApplicationExtension,
|
|
major: 10, minor: 9)
|
|
private(set) var watchOSDeploymentTarget = Version(platform: .watchOS, major: 1)
|
|
private(set) var watchOSAppExtensionDeploymentTarget = Version(platform: .watchOSApplicationExtension, major: 1)
|
|
private(set) var tvOSDeploymentTarget = Version(platform: .tvOS, major: 9)
|
|
private(set) var tvOSAppExtensionDeploymentTarget = Version(platform: .tvOSApplicationExtension, major: 9)
|
|
|
|
private(set) var severityConfiguration = SeverityConfiguration<Parent>(.warning)
|
|
|
|
var parameterDescription: RuleConfigurationDescription? {
|
|
let targets = Dictionary(uniqueKeysWithValues: [
|
|
iOSDeploymentTarget,
|
|
iOSAppExtensionDeploymentTarget,
|
|
macOSDeploymentTarget,
|
|
macOSAppExtensionDeploymentTarget,
|
|
watchOSDeploymentTarget,
|
|
watchOSAppExtensionDeploymentTarget,
|
|
tvOSDeploymentTarget,
|
|
tvOSAppExtensionDeploymentTarget,
|
|
].map { ($0.platform.configurationKey, $0) })
|
|
severityConfiguration
|
|
for (platform, target) in targets.sorted(by: { $0.key < $1.key }) {
|
|
platform => .symbol(target.stringValue)
|
|
}
|
|
}
|
|
|
|
// swiftlint:disable:next cyclomatic_complexity
|
|
mutating func apply(configuration: Any) throws(Issue) {
|
|
guard let configuration = configuration as? [String: Any] else {
|
|
throw .invalidConfiguration(ruleID: Parent.identifier)
|
|
}
|
|
for (key, value) in configuration {
|
|
if key == "severity", let value = value as? String {
|
|
try severityConfiguration.apply(configuration: value)
|
|
continue
|
|
}
|
|
switch key {
|
|
case iOSDeploymentTarget.platform.configurationKey:
|
|
try apply(value: value, to: \.iOSDeploymentTarget, from: configuration)
|
|
case iOSAppExtensionDeploymentTarget.platform.configurationKey:
|
|
iOSAppExtensionDeploymentTarget = try Version(platform: .iOSApplicationExtension, value: value)
|
|
case macOSDeploymentTarget.platform.configurationKey:
|
|
try apply(value: value, to: \.macOSDeploymentTarget, from: configuration)
|
|
case macOSAppExtensionDeploymentTarget.platform.configurationKey:
|
|
macOSAppExtensionDeploymentTarget = try Version(platform: .macOSApplicationExtension, value: value)
|
|
case watchOSDeploymentTarget.platform.configurationKey:
|
|
try apply(value: value, to: \.watchOSDeploymentTarget, from: configuration)
|
|
case watchOSAppExtensionDeploymentTarget.platform.configurationKey:
|
|
watchOSAppExtensionDeploymentTarget = try Version(platform: .watchOSApplicationExtension, value: value)
|
|
case tvOSDeploymentTarget.platform.configurationKey:
|
|
try apply(value: value, to: \.tvOSDeploymentTarget, from: configuration)
|
|
case tvOSAppExtensionDeploymentTarget.platform.configurationKey:
|
|
tvOSAppExtensionDeploymentTarget = try Version(platform: .tvOSApplicationExtension, value: value)
|
|
default: throw .invalidConfiguration(ruleID: Parent.identifier)
|
|
}
|
|
}
|
|
}
|
|
|
|
private mutating func apply(value: Any,
|
|
to target: WritableKeyPath<Self, Version>,
|
|
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,
|
|
case let counterPlatform = self[keyPath: counterpart].platform,
|
|
configuration[counterPlatform.configurationKey] == nil {
|
|
self[keyPath: counterpart] = try Version(platform: counterPlatform, value: value)
|
|
}
|
|
}
|
|
}
|