Compare commits
22 Commits
main
...
mf-plugins
Author | SHA1 | Date |
---|---|---|
![]() |
1e72a7bc97 | |
![]() |
cfc01e7875 | |
![]() |
00cf87af6b | |
![]() |
0f816cee95 | |
![]() |
053dd7043b | |
![]() |
b054c1f5df | |
![]() |
5c46ba8b8e | |
![]() |
988ebbb795 | |
![]() |
e470e7abff | |
![]() |
2cb160c538 | |
![]() |
155cd67997 | |
![]() |
be75073b74 | |
![]() |
3a3918e30c | |
![]() |
545580eb1f | |
![]() |
fb4e93e36c | |
![]() |
804e8d69a0 | |
![]() |
a42a8e940d | |
![]() |
0d1e1cb094 | |
![]() |
01b70ee2c9 | |
![]() |
1b984b6cf9 | |
![]() |
93d4696e4d | |
![]() |
7782098654 |
|
@ -19,3 +19,6 @@
|
||||||
[submodule "Carthage/Checkouts/Yams"]
|
[submodule "Carthage/Checkouts/Yams"]
|
||||||
path = Carthage/Checkouts/Yams
|
path = Carthage/Checkouts/Yams
|
||||||
url = https://github.com/jpsim/Yams.git
|
url = https://github.com/jpsim/Yams.git
|
||||||
|
[submodule "Carthage/Checkouts/BlueSocket"]
|
||||||
|
path = Carthage/Checkouts/BlueSocket
|
||||||
|
url = https://github.com/IBM-Swift/BlueSocket.git
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
github "Carthage/Commandant" ~> 0.15.0
|
github "Carthage/Commandant" ~> 0.15.0
|
||||||
|
github "IBM-Swift/BlueSocket" ~> 1.0.0
|
||||||
github "jpsim/Yams" ~> 1.0.1
|
github "jpsim/Yams" ~> 1.0.1
|
||||||
github "jspahrsummers/xcconfigs" ~> 0.12.0
|
github "jspahrsummers/xcconfigs" ~> 0.12.0
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
github "Carthage/Commandant" "0.15.0"
|
github "Carthage/Commandant" "0.15.0"
|
||||||
github "antitypical/Result" "4.0.0"
|
github "antitypical/Result" "4.0.0"
|
||||||
github "drmohundro/SWXMLHash" "4.7.6"
|
github "drmohundro/SWXMLHash" "4.7.6"
|
||||||
|
github "IBM-Swift/BlueSocket" "1.0.43"
|
||||||
github "jpsim/SourceKitten" "0.22.0"
|
github "jpsim/SourceKitten" "0.22.0"
|
||||||
github "jpsim/Yams" "1.0.1"
|
github "jpsim/Yams" "1.0.1"
|
||||||
github "jspahrsummers/xcconfigs" "0.12"
|
github "jspahrsummers/xcconfigs" "0.12"
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 9c1b578c618f0bfac017aaaaead19de57bb37831
|
2
Makefile
2
Makefile
|
@ -119,7 +119,7 @@ archive:
|
||||||
release: package archive portable_zip
|
release: package archive portable_zip
|
||||||
|
|
||||||
docker_test:
|
docker_test:
|
||||||
docker run -v `pwd`:`pwd` -w `pwd` --name swiftlint --rm norionomura/swift:42 swift test --parallel
|
docker run -v `pwd`:`pwd` -w `pwd` --name swiftlint --rm norionomura/swift:421 swift test --parallel
|
||||||
|
|
||||||
docker_htop:
|
docker_htop:
|
||||||
docker run -it --rm --pid=container:swiftlint terencewestphal/htop || reset
|
docker run -it --rm --pid=container:swiftlint terencewestphal/htop || reset
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
{
|
{
|
||||||
"object": {
|
"object": {
|
||||||
"pins": [
|
"pins": [
|
||||||
|
{
|
||||||
|
"package": "Socket",
|
||||||
|
"repositoryURL": "https://github.com/IBM-Swift/BlueSocket.git",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "9c1b578c618f0bfac017aaaaead19de57bb37831",
|
||||||
|
"version": "1.0.43"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"package": "Commandant",
|
"package": "Commandant",
|
||||||
"repositoryURL": "https://github.com/Carthage/Commandant.git",
|
"repositoryURL": "https://github.com/Carthage/Commandant.git",
|
||||||
|
|
|
@ -15,6 +15,7 @@ let package = Package(
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.package(url: "https://github.com/Carthage/Commandant.git", from: "0.15.0"),
|
.package(url: "https://github.com/Carthage/Commandant.git", from: "0.15.0"),
|
||||||
|
.package(url: "https://github.com/IBM-Swift/BlueSocket.git", from: "1.0.0"),
|
||||||
.package(url: "https://github.com/jpsim/SourceKitten.git", from: "0.22.0"),
|
.package(url: "https://github.com/jpsim/SourceKitten.git", from: "0.22.0"),
|
||||||
.package(url: "https://github.com/jpsim/Yams.git", from: "1.0.1"),
|
.package(url: "https://github.com/jpsim/Yams.git", from: "1.0.1"),
|
||||||
.package(url: "https://github.com/scottrhoyt/SwiftyTextTable.git", from: "0.8.2"),
|
.package(url: "https://github.com/scottrhoyt/SwiftyTextTable.git", from: "0.8.2"),
|
||||||
|
@ -31,6 +32,7 @@ let package = Package(
|
||||||
.target(
|
.target(
|
||||||
name: "SwiftLintFramework",
|
name: "SwiftLintFramework",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
"Socket",
|
||||||
"SourceKittenFramework",
|
"SourceKittenFramework",
|
||||||
"Yams",
|
"Yams",
|
||||||
] + (addCryptoSwift ? ["CryptoSwift"] : [])
|
] + (addCryptoSwift ? ["CryptoSwift"] : [])
|
||||||
|
|
|
@ -115,7 +115,9 @@ extension Configuration {
|
||||||
rules: mergingRules(with: configuration),
|
rules: mergingRules(with: configuration),
|
||||||
cachePath: cachePath, // Always use the parent cache path
|
cachePath: cachePath, // Always use the parent cache path
|
||||||
rootPath: configuration.rootPath,
|
rootPath: configuration.rootPath,
|
||||||
indentation: configuration.indentation
|
indentation: configuration.indentation,
|
||||||
|
plugins: plugins,
|
||||||
|
remoteRules: remoteRules
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,11 @@ extension Configuration {
|
||||||
case whitelistRules = "whitelist_rules"
|
case whitelistRules = "whitelist_rules"
|
||||||
case indentation = "indentation"
|
case indentation = "indentation"
|
||||||
case analyzerRules = "analyzer_rules"
|
case analyzerRules = "analyzer_rules"
|
||||||
|
case plugins = "plugins"
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func validKeys(ruleList: RuleList) -> [String] {
|
private static func validKeys(ruleList: RuleList, remoteRules: [RemoteRule]) -> [String] {
|
||||||
return [
|
let globalKeys = [
|
||||||
Key.cachePath,
|
Key.cachePath,
|
||||||
.disabledRules,
|
.disabledRules,
|
||||||
.enabledRules,
|
.enabledRules,
|
||||||
|
@ -29,8 +30,12 @@ extension Configuration {
|
||||||
.warningThreshold,
|
.warningThreshold,
|
||||||
.whitelistRules,
|
.whitelistRules,
|
||||||
.indentation,
|
.indentation,
|
||||||
.analyzerRules
|
.analyzerRules,
|
||||||
].map({ $0.rawValue }) + ruleList.allValidIdentifiers()
|
.plugins
|
||||||
|
].map { $0.rawValue }
|
||||||
|
|
||||||
|
return globalKeys + ruleList.allValidIdentifiers() +
|
||||||
|
remoteRules.flatMap { $0.ruleDescription.allIdentifiers }
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func getIndentationLogIfInvalid(from dict: [String: Any]) -> IndentationStyle {
|
private static func getIndentationLogIfInvalid(from dict: [String: Any]) -> IndentationStyle {
|
||||||
|
@ -46,23 +51,23 @@ extension Configuration {
|
||||||
return .default
|
return .default
|
||||||
}
|
}
|
||||||
|
|
||||||
public init?(dict: [String: Any], ruleList: RuleList = masterRuleList, enableAllRules: Bool = false,
|
public init?(dict: [String: Any],
|
||||||
cachePath: String? = nil) {
|
ruleList: RuleList = masterRuleList,
|
||||||
func defaultStringArray(_ object: Any?) -> [String] {
|
enableAllRules: Bool = false,
|
||||||
return [String].array(of: object) ?? []
|
cachePath: String? = nil,
|
||||||
}
|
remoteRulesResolver: RemoteRuleResolverProtocol = RemoteRuleResolver()) {
|
||||||
|
|
||||||
// Use either new 'opt_in_rules' or deprecated 'enabled_rules' for now.
|
// Use either new 'opt_in_rules' or deprecated 'enabled_rules' for now.
|
||||||
let optInRules = defaultStringArray(
|
let optInRules = defaultStringArray(
|
||||||
dict[Key.optInRules.rawValue] ?? dict[Key.enabledRules.rawValue]
|
dict[Key.optInRules.rawValue] ?? dict[Key.enabledRules.rawValue]
|
||||||
)
|
)
|
||||||
|
|
||||||
// Log an error when supplying invalid keys in the configuration dictionary
|
let plugins = defaultStringArray(dict[Key.plugins.rawValue])
|
||||||
let invalidKeys = Set(dict.keys).subtracting(Configuration.validKeys(ruleList: ruleList))
|
let remoteRules = plugins.compactMap {
|
||||||
if !invalidKeys.isEmpty {
|
try? remoteRulesResolver.remoteRule(forExecutable: $0, configuration: dict)
|
||||||
queuedPrintError("Configuration contains invalid keys:\n\(invalidKeys)")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Configuration.validateConfigurationKeys(dict: dict, ruleList: ruleList, remoteRules: remoteRules)
|
||||||
|
|
||||||
let disabledRules = defaultStringArray(dict[Key.disabledRules.rawValue])
|
let disabledRules = defaultStringArray(dict[Key.disabledRules.rawValue])
|
||||||
let whitelistRules = defaultStringArray(dict[Key.whitelistRules.rawValue])
|
let whitelistRules = defaultStringArray(dict[Key.whitelistRules.rawValue])
|
||||||
let analyzerRules = defaultStringArray(dict[Key.analyzerRules.rawValue])
|
let analyzerRules = defaultStringArray(dict[Key.analyzerRules.rawValue])
|
||||||
|
@ -77,9 +82,7 @@ extension Configuration {
|
||||||
do {
|
do {
|
||||||
configuredRules = try ruleList.configuredRules(with: dict)
|
configuredRules = try ruleList.configuredRules(with: dict)
|
||||||
} catch RuleListError.duplicatedConfigurations(let ruleType) {
|
} catch RuleListError.duplicatedConfigurations(let ruleType) {
|
||||||
let aliases = ruleType.description.deprecatedAliases.map { "'\($0)'" }.joined(separator: ", ")
|
Configuration.warnAboutDuplicateConfigurations(for: ruleType)
|
||||||
let identifier = ruleType.description.identifier
|
|
||||||
queuedPrintError("Multiple configurations found for '\(identifier)'. Check for any aliases: \(aliases).")
|
|
||||||
return nil
|
return nil
|
||||||
} catch {
|
} catch {
|
||||||
return nil
|
return nil
|
||||||
|
@ -99,7 +102,9 @@ extension Configuration {
|
||||||
configuredRules: configuredRules,
|
configuredRules: configuredRules,
|
||||||
swiftlintVersion: swiftlintVersion,
|
swiftlintVersion: swiftlintVersion,
|
||||||
cachePath: cachePath ?? dict[Key.cachePath.rawValue] as? String,
|
cachePath: cachePath ?? dict[Key.cachePath.rawValue] as? String,
|
||||||
indentation: indentation)
|
indentation: indentation,
|
||||||
|
plugins: plugins,
|
||||||
|
remoteRules: remoteRules)
|
||||||
}
|
}
|
||||||
|
|
||||||
private init?(disabledRules: [String],
|
private init?(disabledRules: [String],
|
||||||
|
@ -115,7 +120,9 @@ extension Configuration {
|
||||||
configuredRules: [Rule]?,
|
configuredRules: [Rule]?,
|
||||||
swiftlintVersion: String?,
|
swiftlintVersion: String?,
|
||||||
cachePath: String?,
|
cachePath: String?,
|
||||||
indentation: IndentationStyle) {
|
indentation: IndentationStyle,
|
||||||
|
plugins: [String],
|
||||||
|
remoteRules: [RemoteRule]) {
|
||||||
let rulesMode: RulesMode
|
let rulesMode: RulesMode
|
||||||
if enableAllRules {
|
if enableAllRules {
|
||||||
rulesMode = .allEnabled
|
rulesMode = .allEnabled
|
||||||
|
@ -140,7 +147,9 @@ extension Configuration {
|
||||||
configuredRules: configuredRules,
|
configuredRules: configuredRules,
|
||||||
swiftlintVersion: swiftlintVersion,
|
swiftlintVersion: swiftlintVersion,
|
||||||
cachePath: cachePath,
|
cachePath: cachePath,
|
||||||
indentation: indentation)
|
indentation: indentation,
|
||||||
|
plugins: plugins,
|
||||||
|
remoteRules: remoteRules)
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func warnAboutDeprecations(configurationDictionary dict: [String: Any],
|
private static func warnAboutDeprecations(configurationDictionary dict: [String: Any],
|
||||||
|
@ -177,4 +186,23 @@ extension Configuration {
|
||||||
"completely removed in a future release.")
|
"completely removed in a future release.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static func warnAboutDuplicateConfigurations(for ruleType: Rule.Type) {
|
||||||
|
let aliases = ruleType.description.deprecatedAliases.map { "'\($0)'" }.joined(separator: ", ")
|
||||||
|
let identifier = ruleType.description.identifier
|
||||||
|
queuedPrintError("Multiple configurations found for '\(identifier)'. Check for any aliases: \(aliases).")
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func validateConfigurationKeys(dict: [String: Any], ruleList: RuleList, remoteRules: [RemoteRule]) {
|
||||||
|
// Log an error when supplying invalid keys in the configuration dictionary
|
||||||
|
let invalidKeys = Set(dict.keys).subtracting(validKeys(ruleList: ruleList,
|
||||||
|
remoteRules: remoteRules))
|
||||||
|
if !invalidKeys.isEmpty {
|
||||||
|
queuedPrintError("Configuration contains invalid keys:\n\(invalidKeys)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func defaultStringArray(_ object: Any?) -> [String] {
|
||||||
|
return [String].array(of: object) ?? []
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,15 @@ public func queuedPrintError(_ string: String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
A thread-safe, newline-terminated version of fputs(..., stderr).
|
||||||
|
|
||||||
|
- parameter error: Error to print.
|
||||||
|
*/
|
||||||
|
public func queuedPrintError(_ error: Error) {
|
||||||
|
queuedPrintError(error.localizedDescription)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A thread-safe, newline-terminated version of fatalError that doesn't leak
|
A thread-safe, newline-terminated version of fatalError that doesn't leak
|
||||||
the source path from the compiled binary.
|
the source path from the compiled binary.
|
||||||
|
|
|
@ -18,6 +18,7 @@ public struct Configuration: Hashable {
|
||||||
public let excluded: [String] // excluded
|
public let excluded: [String] // excluded
|
||||||
public let reporter: String // reporter (xcode, json, csv, checkstyle)
|
public let reporter: String // reporter (xcode, json, csv, checkstyle)
|
||||||
public let warningThreshold: Int? // warning threshold
|
public let warningThreshold: Int? // warning threshold
|
||||||
|
public let plugins: [String]
|
||||||
public private(set) var rootPath: String? // the root path to search for nested configurations
|
public private(set) var rootPath: String? // the root path to search for nested configurations
|
||||||
public private(set) var configurationPath: String? // if successfully loaded from a path
|
public private(set) var configurationPath: String? // if successfully loaded from a path
|
||||||
public let cachePath: String?
|
public let cachePath: String?
|
||||||
|
@ -33,6 +34,7 @@ public struct Configuration: Hashable {
|
||||||
hasher.combine(included)
|
hasher.combine(included)
|
||||||
hasher.combine(excluded)
|
hasher.combine(excluded)
|
||||||
hasher.combine(reporter)
|
hasher.combine(reporter)
|
||||||
|
hasher.combine(plugins)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,9 +42,11 @@ public struct Configuration: Hashable {
|
||||||
|
|
||||||
// MARK: Rules Properties
|
// MARK: Rules Properties
|
||||||
|
|
||||||
// All rules enabled in this configuration, derived from disabled, opt-in and whitelist rules
|
/// All rules enabled in this configuration, derived from disabled, opt-in and whitelist rules
|
||||||
public let rules: [Rule]
|
public let rules: [Rule]
|
||||||
|
|
||||||
|
internal let remoteRules: [RemoteRule]
|
||||||
|
|
||||||
internal let rulesMode: RulesMode
|
internal let rulesMode: RulesMode
|
||||||
|
|
||||||
// MARK: Initializers
|
// MARK: Initializers
|
||||||
|
@ -56,7 +60,10 @@ public struct Configuration: Hashable {
|
||||||
configuredRules: [Rule]? = nil,
|
configuredRules: [Rule]? = nil,
|
||||||
swiftlintVersion: String? = nil,
|
swiftlintVersion: String? = nil,
|
||||||
cachePath: String? = nil,
|
cachePath: String? = nil,
|
||||||
indentation: IndentationStyle = .default) {
|
indentation: IndentationStyle = .default,
|
||||||
|
plugins: [String] = [],
|
||||||
|
remoteRulesResolver: RemoteRuleResolverProtocol = RemoteRuleResolver(),
|
||||||
|
remoteRules: [RemoteRule]? = nil) {
|
||||||
if let pinnedVersion = swiftlintVersion, pinnedVersion != Version.current.value {
|
if let pinnedVersion = swiftlintVersion, pinnedVersion != Version.current.value {
|
||||||
queuedPrintError("Currently running SwiftLint \(Version.current.value) but " +
|
queuedPrintError("Currently running SwiftLint \(Version.current.value) but " +
|
||||||
"configuration specified version \(pinnedVersion).")
|
"configuration specified version \(pinnedVersion).")
|
||||||
|
@ -67,10 +74,15 @@ public struct Configuration: Hashable {
|
||||||
?? (try? ruleList.configuredRules(with: [:]))
|
?? (try? ruleList.configuredRules(with: [:]))
|
||||||
?? []
|
?? []
|
||||||
|
|
||||||
|
let remoteRules = remoteRules ?? plugins.compactMap {
|
||||||
|
try? remoteRulesResolver.remoteRule(forExecutable: $0, configuration: nil)
|
||||||
|
}
|
||||||
|
|
||||||
let handleAliasWithRuleList: (String) -> String = { ruleList.identifier(for: $0) ?? $0 }
|
let handleAliasWithRuleList: (String) -> String = { ruleList.identifier(for: $0) ?? $0 }
|
||||||
|
|
||||||
guard let rules = enabledRules(from: configuredRules,
|
guard let enabledRules = enabledRules(from: configuredRules,
|
||||||
with: rulesMode,
|
with: rulesMode,
|
||||||
|
remoteRules: remoteRules,
|
||||||
aliasResolver: handleAliasWithRuleList) else {
|
aliasResolver: handleAliasWithRuleList) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -80,9 +92,11 @@ public struct Configuration: Hashable {
|
||||||
excluded: excluded,
|
excluded: excluded,
|
||||||
warningThreshold: warningThreshold,
|
warningThreshold: warningThreshold,
|
||||||
reporter: reporter,
|
reporter: reporter,
|
||||||
rules: rules,
|
rules: enabledRules.0,
|
||||||
cachePath: cachePath,
|
cachePath: cachePath,
|
||||||
indentation: indentation)
|
indentation: indentation,
|
||||||
|
plugins: plugins,
|
||||||
|
remoteRules: enabledRules.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal init(rulesMode: RulesMode,
|
internal init(rulesMode: RulesMode,
|
||||||
|
@ -93,7 +107,9 @@ public struct Configuration: Hashable {
|
||||||
rules: [Rule],
|
rules: [Rule],
|
||||||
cachePath: String?,
|
cachePath: String?,
|
||||||
rootPath: String? = nil,
|
rootPath: String? = nil,
|
||||||
indentation: IndentationStyle) {
|
indentation: IndentationStyle,
|
||||||
|
plugins: [String],
|
||||||
|
remoteRules: [RemoteRule]) {
|
||||||
self.rulesMode = rulesMode
|
self.rulesMode = rulesMode
|
||||||
self.included = included
|
self.included = included
|
||||||
self.excluded = excluded
|
self.excluded = excluded
|
||||||
|
@ -102,6 +118,8 @@ public struct Configuration: Hashable {
|
||||||
self.rules = rules
|
self.rules = rules
|
||||||
self.rootPath = rootPath
|
self.rootPath = rootPath
|
||||||
self.indentation = indentation
|
self.indentation = indentation
|
||||||
|
self.plugins = plugins
|
||||||
|
self.remoteRules = remoteRules
|
||||||
|
|
||||||
// set the config threshold to the threshold provided in the config file
|
// set the config threshold to the threshold provided in the config file
|
||||||
self.warningThreshold = warningThreshold
|
self.warningThreshold = warningThreshold
|
||||||
|
@ -117,6 +135,8 @@ public struct Configuration: Hashable {
|
||||||
cachePath = configuration.cachePath
|
cachePath = configuration.cachePath
|
||||||
rootPath = configuration.rootPath
|
rootPath = configuration.rootPath
|
||||||
indentation = configuration.indentation
|
indentation = configuration.indentation
|
||||||
|
plugins = configuration.plugins
|
||||||
|
remoteRules = configuration.remoteRules
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(path: String = Configuration.fileName, rootPath: String? = nil,
|
public init(path: String = Configuration.fileName, rootPath: String? = nil,
|
||||||
|
@ -176,7 +196,8 @@ public struct Configuration: Hashable {
|
||||||
(lhs.included == rhs.included) &&
|
(lhs.included == rhs.included) &&
|
||||||
(lhs.excluded == rhs.excluded) &&
|
(lhs.excluded == rhs.excluded) &&
|
||||||
(lhs.rules == rhs.rules) &&
|
(lhs.rules == rhs.rules) &&
|
||||||
(lhs.indentation == rhs.indentation)
|
(lhs.indentation == rhs.indentation) &&
|
||||||
|
(lhs.plugins == rhs.plugins)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,12 +234,13 @@ private func containsDuplicateIdentifiers(_ identifiers: [String]) -> Bool {
|
||||||
|
|
||||||
private func enabledRules(from configuredRules: [Rule],
|
private func enabledRules(from configuredRules: [Rule],
|
||||||
with mode: Configuration.RulesMode,
|
with mode: Configuration.RulesMode,
|
||||||
aliasResolver: (String) -> String) -> [Rule]? {
|
remoteRules: [RemoteRule],
|
||||||
let validRuleIdentifiers = configuredRules.map { type(of: $0).description.identifier }
|
aliasResolver: (String) -> String) -> ([Rule], [RemoteRule])? {
|
||||||
|
let validRuleIdentifiers = configuredRules.map { type(of: $0).description.identifier } + remoteRules.identifiers
|
||||||
|
|
||||||
switch mode {
|
switch mode {
|
||||||
case .allEnabled:
|
case .allEnabled:
|
||||||
return configuredRules
|
return (configuredRules, remoteRules)
|
||||||
case .whitelisted(let whitelistedRuleIdentifiers):
|
case .whitelisted(let whitelistedRuleIdentifiers):
|
||||||
let validWhitelistedRuleIdentifiers = validateRuleIdentifiers(
|
let validWhitelistedRuleIdentifiers = validateRuleIdentifiers(
|
||||||
ruleIdentifiers: whitelistedRuleIdentifiers.map(aliasResolver),
|
ruleIdentifiers: whitelistedRuleIdentifiers.map(aliasResolver),
|
||||||
|
@ -227,9 +249,15 @@ private func enabledRules(from configuredRules: [Rule],
|
||||||
if containsDuplicateIdentifiers(validWhitelistedRuleIdentifiers) {
|
if containsDuplicateIdentifiers(validWhitelistedRuleIdentifiers) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return configuredRules.filter { rule in
|
|
||||||
|
let whitelistedRules = configuredRules.filter { rule in
|
||||||
return validWhitelistedRuleIdentifiers.contains(type(of: rule).description.identifier)
|
return validWhitelistedRuleIdentifiers.contains(type(of: rule).description.identifier)
|
||||||
}
|
}
|
||||||
|
let whitelistedRemoteRules = remoteRules.filter { rule in
|
||||||
|
return validWhitelistedRuleIdentifiers.contains(rule.ruleDescription.identifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (whitelistedRules, whitelistedRemoteRules)
|
||||||
case let .default(disabledRuleIdentifiers, optInRuleIdentifiers):
|
case let .default(disabledRuleIdentifiers, optInRuleIdentifiers):
|
||||||
let validDisabledRuleIdentifiers = validateRuleIdentifiers(
|
let validDisabledRuleIdentifiers = validateRuleIdentifiers(
|
||||||
ruleIdentifiers: disabledRuleIdentifiers.map(aliasResolver),
|
ruleIdentifiers: disabledRuleIdentifiers.map(aliasResolver),
|
||||||
|
@ -242,11 +270,19 @@ private func enabledRules(from configuredRules: [Rule],
|
||||||
|| containsDuplicateIdentifiers(validOptInRuleIdentifiers) {
|
|| containsDuplicateIdentifiers(validOptInRuleIdentifiers) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return configuredRules.filter { rule in
|
|
||||||
|
let enabledRules = configuredRules.filter { rule in
|
||||||
let id = type(of: rule).description.identifier
|
let id = type(of: rule).description.identifier
|
||||||
if validDisabledRuleIdentifiers.contains(id) { return false }
|
if validDisabledRuleIdentifiers.contains(id) { return false }
|
||||||
return validOptInRuleIdentifiers.contains(id) || !(rule is OptInRule)
|
return validOptInRuleIdentifiers.contains(id) || !(rule is OptInRule)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let enabledRemoteRules = remoteRules.filter { rule in
|
||||||
|
let id = rule.ruleDescription.identifier
|
||||||
|
return !validDisabledRuleIdentifiers.contains(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (enabledRules, enabledRemoteRules)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
// extracted from https://forums.swift.org/t/pitch-declaring-local-variables-as-lazy/9287/3
|
||||||
|
internal class Lazy<Result> {
|
||||||
|
private var computation: () -> Result
|
||||||
|
private(set) lazy var value: Result = computation()
|
||||||
|
|
||||||
|
init(_ computation: @escaping @autoclosure () -> Result) {
|
||||||
|
self.computation = computation
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,8 +7,75 @@ private struct LintResult {
|
||||||
let deprecatedToValidIDPairs: [(String, String)]
|
let deprecatedToValidIDPairs: [(String, String)]
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension Rule {
|
private enum LintableBox {
|
||||||
static func superfluousDisableCommandViolations(regions: [Region],
|
case rule(Rule)
|
||||||
|
case remoteRule(RemoteRule)
|
||||||
|
|
||||||
|
private var ruleDescription: RuleDescription {
|
||||||
|
switch self {
|
||||||
|
case .rule(let rule):
|
||||||
|
return type(of: rule).description
|
||||||
|
case .remoteRule(let remoteRule):
|
||||||
|
return remoteRule.ruleDescription
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func lint(file: File, regions: [Region], benchmark: Bool,
|
||||||
|
superfluousDisableCommandRule: SuperfluousDisableCommandRule?,
|
||||||
|
compilerArguments: [String]) -> LintResult? {
|
||||||
|
let lintResultBeforeDisableCommand: LintResult?
|
||||||
|
switch self {
|
||||||
|
case .rule(let rule):
|
||||||
|
lintResultBeforeDisableCommand = rule.lint(file: file, regions: regions, benchmark: benchmark,
|
||||||
|
compilerArguments: compilerArguments)
|
||||||
|
case .remoteRule(let remoteRule):
|
||||||
|
lintResultBeforeDisableCommand = remoteRule.lint(file: file, regions: regions, benchmark: benchmark,
|
||||||
|
compilerArguments: compilerArguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let lintResult = lintResultBeforeDisableCommand else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let violations = lintResult.violations
|
||||||
|
let (disabledViolationsAndRegions, enabledViolationsAndRegions) = violations.map { violation in
|
||||||
|
return (violation, regions.first { $0.contains(violation.location) })
|
||||||
|
}.partitioned { _, region in
|
||||||
|
return region?.isRuleEnabled(ruleDescription) ?? true
|
||||||
|
}
|
||||||
|
|
||||||
|
let ruleIDs = ruleDescription.allIdentifiers +
|
||||||
|
(superfluousDisableCommandRule.map({ type(of: $0) })?.description.allIdentifiers ?? [])
|
||||||
|
let ruleIdentifiers = Set(ruleIDs.map { RuleIdentifier($0) })
|
||||||
|
|
||||||
|
let superfluousDisableCommandViolations = ruleDescription.superfluousDisableCommandViolations(
|
||||||
|
regions: regions.count > 1 ? file.regions(restrictingRuleIdentifiers: ruleIdentifiers) : regions,
|
||||||
|
superfluousDisableCommandRule: superfluousDisableCommandRule,
|
||||||
|
allViolations: violations
|
||||||
|
)
|
||||||
|
|
||||||
|
let enabledViolations: [StyleViolation]
|
||||||
|
if file.contents.hasPrefix("#!") { // if a violation happens on the same line as a shebang, ignore it
|
||||||
|
enabledViolations = enabledViolationsAndRegions.compactMap { violation, _ in
|
||||||
|
if violation.location.line == 1 { return nil }
|
||||||
|
return violation
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
enabledViolations = enabledViolationsAndRegions.map { $0.0 }
|
||||||
|
}
|
||||||
|
let deprecatedToValidIDPairs = disabledViolationsAndRegions.flatMap { _, region -> [(String, String)] in
|
||||||
|
let identifiers = region?.deprecatedAliasesDisabling(ruleDescription: ruleDescription) ?? []
|
||||||
|
return identifiers.map { ($0, ruleDescription.identifier) }
|
||||||
|
}
|
||||||
|
|
||||||
|
return LintResult(violations: enabledViolations + superfluousDisableCommandViolations,
|
||||||
|
ruleTime: lintResult.ruleTime,
|
||||||
|
deprecatedToValidIDPairs: deprecatedToValidIDPairs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension RuleDescription {
|
||||||
|
func superfluousDisableCommandViolations(regions: [Region],
|
||||||
superfluousDisableCommandRule: SuperfluousDisableCommandRule?,
|
superfluousDisableCommandRule: SuperfluousDisableCommandRule?,
|
||||||
allViolations: [StyleViolation]) -> [StyleViolation] {
|
allViolations: [StyleViolation]) -> [StyleViolation] {
|
||||||
guard !regions.isEmpty, let superfluousDisableCommandRule = superfluousDisableCommandRule else {
|
guard !regions.isEmpty, let superfluousDisableCommandRule = superfluousDisableCommandRule else {
|
||||||
|
@ -16,7 +83,7 @@ private extension Rule {
|
||||||
}
|
}
|
||||||
|
|
||||||
let regionsDisablingCurrentRule = regions.filter { region in
|
let regionsDisablingCurrentRule = regions.filter { region in
|
||||||
return region.isRuleDisabled(self.init())
|
return region.isRuleDisabled(self)
|
||||||
}
|
}
|
||||||
let regionsDisablingSuperflousDisableRule = regions.filter { region in
|
let regionsDisablingSuperflousDisableRule = regions.filter { region in
|
||||||
return region.isRuleDisabled(superfluousDisableCommandRule)
|
return region.isRuleDisabled(superfluousDisableCommandRule)
|
||||||
|
@ -43,9 +110,10 @@ private extension Rule {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension Rule {
|
||||||
func lint(file: File, regions: [Region], benchmark: Bool,
|
func lint(file: File, regions: [Region], benchmark: Bool,
|
||||||
superfluousDisableCommandRule: SuperfluousDisableCommandRule?,
|
|
||||||
compilerArguments: [String]) -> LintResult? {
|
compilerArguments: [String]) -> LintResult? {
|
||||||
if !(self is SourceKitFreeRule) && file.sourcekitdFailed {
|
if !(self is SourceKitFreeRule) && file.sourcekitdFailed {
|
||||||
return nil
|
return nil
|
||||||
|
@ -64,38 +132,29 @@ private extension Rule {
|
||||||
ruleTime = nil
|
ruleTime = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
let (disabledViolationsAndRegions, enabledViolationsAndRegions) = violations.map { violation in
|
return LintResult(violations: violations, ruleTime: ruleTime,
|
||||||
return (violation, regions.first { $0.contains(violation.location) })
|
deprecatedToValidIDPairs: [])
|
||||||
}.partitioned { _, region in
|
}
|
||||||
return region?.isRuleEnabled(self) ?? true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let ruleIDs = Self.description.allIdentifiers +
|
private extension RemoteRule {
|
||||||
(superfluousDisableCommandRule.map({ type(of: $0) })?.description.allIdentifiers ?? [])
|
func lint(file: File, regions: [Region], benchmark: Bool,
|
||||||
let ruleIdentifiers = Set(ruleIDs.map { RuleIdentifier($0) })
|
compilerArguments: [String]) -> LintResult? {
|
||||||
|
let ruleID = ruleDescription.identifier
|
||||||
|
|
||||||
let superfluousDisableCommandViolations = Self.superfluousDisableCommandViolations(
|
let violations: [StyleViolation]
|
||||||
regions: regions.count > 1 ? file.regions(restrictingRuleIdentifiers: ruleIdentifiers) : regions,
|
let ruleTime: (String, Double)?
|
||||||
superfluousDisableCommandRule: superfluousDisableCommandRule,
|
if benchmark {
|
||||||
allViolations: violations
|
let start = Date()
|
||||||
)
|
violations = validate(file: file)
|
||||||
|
ruleTime = (ruleID, -start.timeIntervalSinceNow)
|
||||||
let enabledViolations: [StyleViolation]
|
|
||||||
if file.contents.hasPrefix("#!") { // if a violation happens on the same line as a shebang, ignore it
|
|
||||||
enabledViolations = enabledViolationsAndRegions.compactMap { violation, _ in
|
|
||||||
if violation.location.line == 1 { return nil }
|
|
||||||
return violation
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
enabledViolations = enabledViolationsAndRegions.map { $0.0 }
|
violations = validate(file: file)
|
||||||
}
|
ruleTime = nil
|
||||||
let deprecatedToValidIDPairs = disabledViolationsAndRegions.flatMap { _, region -> [(String, String)] in
|
|
||||||
let identifiers = region?.deprecatedAliasesDisabling(rule: self) ?? []
|
|
||||||
return identifiers.map { ($0, ruleID) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return LintResult(violations: enabledViolations + superfluousDisableCommandViolations, ruleTime: ruleTime,
|
return LintResult(violations: violations, ruleTime: ruleTime,
|
||||||
deprecatedToValidIDPairs: deprecatedToValidIDPairs)
|
deprecatedToValidIDPairs: [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +164,7 @@ public struct Linter {
|
||||||
private let cache: LinterCache?
|
private let cache: LinterCache?
|
||||||
private let configuration: Configuration
|
private let configuration: Configuration
|
||||||
private let compilerArguments: [String]
|
private let compilerArguments: [String]
|
||||||
|
private let remoteRules: [RemoteRule]
|
||||||
|
|
||||||
public var styleViolations: [StyleViolation] {
|
public var styleViolations: [StyleViolation] {
|
||||||
return getStyleViolations().0
|
return getStyleViolations().0
|
||||||
|
@ -126,7 +186,9 @@ public struct Linter {
|
||||||
let superfluousDisableCommandRule = rules.first(where: {
|
let superfluousDisableCommandRule = rules.first(where: {
|
||||||
$0 is SuperfluousDisableCommandRule
|
$0 is SuperfluousDisableCommandRule
|
||||||
}) as? SuperfluousDisableCommandRule
|
}) as? SuperfluousDisableCommandRule
|
||||||
let validationResults = rules.parallelCompactMap {
|
|
||||||
|
let lintables = remoteRules.map(LintableBox.remoteRule) + rules.map(LintableBox.rule)
|
||||||
|
let validationResults = lintables.parallelCompactMap {
|
||||||
$0.lint(file: self.file, regions: regions, benchmark: benchmark,
|
$0.lint(file: self.file, regions: regions, benchmark: benchmark,
|
||||||
superfluousDisableCommandRule: superfluousDisableCommandRule,
|
superfluousDisableCommandRule: superfluousDisableCommandRule,
|
||||||
compilerArguments: self.compilerArguments)
|
compilerArguments: self.compilerArguments)
|
||||||
|
@ -184,6 +246,7 @@ public struct Linter {
|
||||||
return rule is AnalyzerRule
|
return rule is AnalyzerRule
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.remoteRules = configuration.remoteRules
|
||||||
}
|
}
|
||||||
|
|
||||||
public func correct() -> [Correction] {
|
public func correct() -> [Correction] {
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
public enum PluginRequiredInput: String, Codable {
|
||||||
|
case syntaxMap = "syntax_map"
|
||||||
|
case structure = "structure"
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct PluginDescription: Equatable, Codable {
|
||||||
|
public let ruleDescription: RuleDescription
|
||||||
|
public let requiredInformation: Set<PluginRequiredInput>
|
||||||
|
|
||||||
|
public init(ruleDescription: RuleDescription,
|
||||||
|
requiredInformation: Set<PluginRequiredInput> = []) {
|
||||||
|
self.ruleDescription = ruleDescription
|
||||||
|
self.requiredInformation = requiredInformation
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.ruleDescription = try container.decode(RuleDescription.self, forKey: .ruleDescription)
|
||||||
|
self.requiredInformation = try container.decodeIfPresent(Set<PluginRequiredInput>.self,
|
||||||
|
forKey: .requiredInformation) ?? []
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,22 +13,34 @@ public struct Region: Equatable {
|
||||||
return start <= location && end >= location
|
return start <= location && end >= location
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isRuleEnabled(_ ruleDescription: RuleDescription) -> Bool {
|
||||||
|
return !isRuleDisabled(ruleDescription)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func isRuleDisabled(_ ruleDescription: RuleDescription) -> Bool {
|
||||||
|
guard !disabledRuleIdentifiers.contains(.all) else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
let identifiersToCheck = ruleDescription.allIdentifiers
|
||||||
|
let regionIdentifiers = Set(disabledRuleIdentifiers.map { $0.stringRepresentation })
|
||||||
|
return !regionIdentifiers.isDisjoint(with: identifiersToCheck)
|
||||||
|
}
|
||||||
|
|
||||||
public func isRuleEnabled(_ rule: Rule) -> Bool {
|
public func isRuleEnabled(_ rule: Rule) -> Bool {
|
||||||
return !isRuleDisabled(rule)
|
return !isRuleDisabled(rule)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func isRuleDisabled(_ rule: Rule) -> Bool {
|
public func isRuleDisabled(_ rule: Rule) -> Bool {
|
||||||
guard !disabledRuleIdentifiers.contains(.all) else {
|
return isRuleDisabled(type(of: rule).description)
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let identifiersToCheck = type(of: rule).description.allIdentifiers
|
public func deprecatedAliasesDisabling(ruleDescription: RuleDescription) -> Set<String> {
|
||||||
let regionIdentifiers = Set(disabledRuleIdentifiers.map { $0.stringRepresentation })
|
let identifiers = ruleDescription.deprecatedAliases
|
||||||
return !regionIdentifiers.isDisjoint(with: identifiersToCheck)
|
return Set(disabledRuleIdentifiers.map { $0.stringRepresentation }).intersection(identifiers)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func deprecatedAliasesDisabling(rule: Rule) -> Set<String> {
|
public func deprecatedAliasesDisabling(rule: Rule) -> Set<String> {
|
||||||
let identifiers = type(of: rule).description.deprecatedAliases
|
return deprecatedAliasesDisabling(ruleDescription: type(of: rule).description)
|
||||||
return Set(disabledRuleIdentifiers.map { $0.stringRepresentation }).intersection(identifiers)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
import Dispatch
|
||||||
|
import Foundation
|
||||||
|
import Socket
|
||||||
|
|
||||||
|
protocol RemoteLintServerDelegate: AnyObject {
|
||||||
|
func server(_ server: RemoteLintServer, didReceivePayload payload: RemoteRulePayload) -> [StyleViolation]
|
||||||
|
func serverStartedListening(_ server: RemoteLintServer)
|
||||||
|
}
|
||||||
|
|
||||||
|
final class RemoteLintServer {
|
||||||
|
private let socketPath: String
|
||||||
|
private var listenSocket: Socket?
|
||||||
|
private var continueRunning = true
|
||||||
|
private var connectedSockets = [Int32: Socket]()
|
||||||
|
private let socketLockQueue = DispatchQueue(label: "io.realm.swiftlint.remoteLintServer")
|
||||||
|
|
||||||
|
weak var delegate: RemoteLintServerDelegate?
|
||||||
|
|
||||||
|
init(socketPath: String) {
|
||||||
|
self.socketPath = socketPath
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
for socket in connectedSockets.values {
|
||||||
|
socket.close()
|
||||||
|
}
|
||||||
|
listenSocket?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() {
|
||||||
|
let queue = DispatchQueue.global(qos: .userInteractive)
|
||||||
|
queue.async { [unowned self] in
|
||||||
|
do {
|
||||||
|
let socket = try Socket.create(family: .unix, type: .stream, proto: .unix)
|
||||||
|
socket.readBufferSize = 65_507
|
||||||
|
self.listenSocket = socket
|
||||||
|
|
||||||
|
try socket.listen(on: self.socketPath)
|
||||||
|
|
||||||
|
self.delegate?.serverStartedListening(self)
|
||||||
|
|
||||||
|
repeat {
|
||||||
|
let newSocket = try socket.acceptClientConnection()
|
||||||
|
self.addNewConnection(socket: newSocket)
|
||||||
|
} while self.continueRunning
|
||||||
|
} catch {
|
||||||
|
queuedPrintError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addNewConnection(socket: Socket) {
|
||||||
|
socketLockQueue.sync { [unowned self, socket] in
|
||||||
|
self.connectedSockets[socket.socketfd] = socket
|
||||||
|
}
|
||||||
|
|
||||||
|
let queue = DispatchQueue.global(qos: .default)
|
||||||
|
queue.async { [unowned self, socket] in
|
||||||
|
var shouldKeepRunning = true
|
||||||
|
var readData = Data()
|
||||||
|
|
||||||
|
do {
|
||||||
|
repeat {
|
||||||
|
let bytesRead = try socket.read(into: &readData)
|
||||||
|
|
||||||
|
if bytesRead > 0 {
|
||||||
|
guard let json = (try? JSONSerialization.jsonObject(with: readData)) as? [String: Any],
|
||||||
|
let payload = RemoteRulePayload(json: json) else {
|
||||||
|
readData.count = 0
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
let violations = self.delegate?.server(self, didReceivePayload: payload) ?? []
|
||||||
|
let data = try JSONSerialization.data(withJSONObject: violations.map { $0.toPluginJSON() })
|
||||||
|
try socket.write(from: data)
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytesRead == 0 {
|
||||||
|
shouldKeepRunning = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
readData.count = 0
|
||||||
|
} while shouldKeepRunning
|
||||||
|
|
||||||
|
socket.close()
|
||||||
|
|
||||||
|
self.socketLockQueue.sync { [unowned self, socket] in
|
||||||
|
self.connectedSockets[socket.socketfd] = nil
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
queuedPrintError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func shutdown() {
|
||||||
|
continueRunning = false
|
||||||
|
|
||||||
|
for socket in connectedSockets.values {
|
||||||
|
socket.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
listenSocket?.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension StyleViolation {
|
||||||
|
func toPluginJSON() -> [String: Any] {
|
||||||
|
return [
|
||||||
|
"severity": severity.rawValue,
|
||||||
|
"location": [
|
||||||
|
"line": location.line ?? 1,
|
||||||
|
"character": location.character ?? 1
|
||||||
|
],
|
||||||
|
"reason": reason
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
import Foundation
|
||||||
|
import Socket
|
||||||
|
import SourceKittenFramework
|
||||||
|
|
||||||
|
public final class RemoteRule {
|
||||||
|
public let description: PluginDescription
|
||||||
|
public let configuration: Any?
|
||||||
|
|
||||||
|
public var ruleDescription: RuleDescription {
|
||||||
|
return description.ruleDescription
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(description: PluginDescription, configuration: Any?) {
|
||||||
|
self.description = description
|
||||||
|
self.configuration = configuration
|
||||||
|
}
|
||||||
|
|
||||||
|
public func validate(file: File) -> [StyleViolation] {
|
||||||
|
let payload = RemoteRulePayload(structure: Lazy(file.structure.dictionary),
|
||||||
|
syntaxMap: Lazy(file.syntaxMap.tokens),
|
||||||
|
path: file.path,
|
||||||
|
contents: Lazy(file.contents),
|
||||||
|
configuration: configuration)
|
||||||
|
return validate(payload: payload, file: file)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func validate(payload: RemoteRulePayload, file: File) -> [StyleViolation] {
|
||||||
|
do {
|
||||||
|
let socket = try Socket.create(family: .unix, type: .stream, proto: .unix)
|
||||||
|
try socket.connect(to: "/tmp/\(ruleDescription.identifier).socket")
|
||||||
|
|
||||||
|
let data = try payload.asJSONData(input: description.requiredInformation)
|
||||||
|
try socket.write(from: data)
|
||||||
|
|
||||||
|
var readData = Data()
|
||||||
|
_ = try socket.read(into: &readData)
|
||||||
|
|
||||||
|
guard let json = try JSONSerialization.jsonObject(with: readData) as? [[String: Any]] else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.compactMap { dictionary -> StyleViolation? in
|
||||||
|
let severity = (dictionary["severity"] as? String).flatMap(ViolationSeverity.init) ?? .warning
|
||||||
|
guard let location = Location(file: file, json: dictionary) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return StyleViolation(ruleDescription: ruleDescription,
|
||||||
|
severity: severity,
|
||||||
|
location: location,
|
||||||
|
reason: dictionary["reason"] as? String)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
queuedPrintError(error)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal extension Array where Element == RemoteRule {
|
||||||
|
var identifiers: [String] {
|
||||||
|
return map { $0.ruleDescription.identifier }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension Location {
|
||||||
|
init?(file: File, json: [String: Any]) {
|
||||||
|
if let byteOffset = json["byte_offset"] as? Int {
|
||||||
|
self = Location(file: file, byteOffset: byteOffset)
|
||||||
|
} else if let characterOffset = json["character_offset"] as? Int {
|
||||||
|
self = Location(file: file, characterOffset: characterOffset)
|
||||||
|
} else if let location = json["location"] as? [String: Int],
|
||||||
|
let line = location["line"] {
|
||||||
|
self = Location(file: file.path, line: line, character: location["character"] ?? 1)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
import Foundation
|
||||||
|
import SourceKittenFramework
|
||||||
|
|
||||||
|
internal struct RemoteRulePayload {
|
||||||
|
let structure: Lazy<[String: SourceKitRepresentable]>
|
||||||
|
let syntaxMap: Lazy<[SyntaxToken]>
|
||||||
|
let path: String?
|
||||||
|
let contents: Lazy<String?>
|
||||||
|
let configuration: Any?
|
||||||
|
|
||||||
|
func asJSONData(input: Set<PluginRequiredInput>) throws -> Data {
|
||||||
|
return try JSONSerialization.data(withJSONObject: asJSONDictionary(input: input))
|
||||||
|
}
|
||||||
|
|
||||||
|
func asJSONDictionary(input: Set<PluginRequiredInput>) -> [String: Any] {
|
||||||
|
var json = [String: Any]()
|
||||||
|
if input.contains(.structure) {
|
||||||
|
json["structure"] = structure.value
|
||||||
|
}
|
||||||
|
if input.contains(.syntaxMap) {
|
||||||
|
json["syntax_map"] = syntaxMap.value.map { $0.dictionaryValue }
|
||||||
|
}
|
||||||
|
|
||||||
|
json["path"] = path
|
||||||
|
json["configuration"] = configuration
|
||||||
|
if path == nil {
|
||||||
|
json["contents"] = contents.value
|
||||||
|
}
|
||||||
|
|
||||||
|
return json
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension RemoteRulePayload {
|
||||||
|
init?(json: [String: Any]) {
|
||||||
|
let rawStructure = json["structure"]
|
||||||
|
let structure = rawStructure.map(convertingIntsToInt64) as? [String: SourceKitRepresentable] ?? [:]
|
||||||
|
let syntaxMap = (json["syntax_map"] as? [[String: Any]])?.compactMap(SyntaxToken.init(json:)) ?? []
|
||||||
|
let path = json["path"] as? String
|
||||||
|
let contents = json["contents"] as? String
|
||||||
|
let configuration = json["configuration"]
|
||||||
|
|
||||||
|
if path == nil && contents == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
self.init(structure: Lazy(structure), syntaxMap: Lazy(syntaxMap),
|
||||||
|
path: path, contents: Lazy(contents), configuration: configuration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func convertingIntsToInt64(value: Any) -> Any {
|
||||||
|
switch value {
|
||||||
|
case let value as Int:
|
||||||
|
return Int64(value)
|
||||||
|
case let values as [Any]:
|
||||||
|
return values.map(convertingIntsToInt64)
|
||||||
|
case let values as [String: Any]:
|
||||||
|
return values.mapValues(convertingIntsToInt64)
|
||||||
|
case let value as String:
|
||||||
|
return value
|
||||||
|
case let value as Int64:
|
||||||
|
return value
|
||||||
|
case let value as Bool:
|
||||||
|
return value
|
||||||
|
default:
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension SyntaxToken {
|
||||||
|
init?(json: [String: Any]) {
|
||||||
|
guard let type = json["type"] as? String,
|
||||||
|
let offset = json["offset"] as? Int,
|
||||||
|
let length = json["length"] as? Int else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
self.init(type: type, offset: offset, length: length)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public protocol RemoteRuleResolverProtocol {
|
||||||
|
func remoteRule(forExecutable executable: String,
|
||||||
|
configuration: [String: Any]?) throws -> RemoteRule
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class RemoteRuleResolver: RemoteRuleResolverProtocol {
|
||||||
|
public init() {}
|
||||||
|
|
||||||
|
public func remoteRule(forExecutable executable: String,
|
||||||
|
configuration: [String: Any]?) throws -> RemoteRule {
|
||||||
|
let task = Process()
|
||||||
|
task.launchPath = executable
|
||||||
|
task.arguments = ["plugin_description"]
|
||||||
|
|
||||||
|
let pipe = Pipe()
|
||||||
|
task.standardOutput = pipe
|
||||||
|
|
||||||
|
task.launch()
|
||||||
|
|
||||||
|
let file = pipe.fileHandleForReading
|
||||||
|
defer { file.closeFile() }
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||||
|
let description = try decoder.decode(PluginDescription.self, from: file.readDataToEndOfFile())
|
||||||
|
return RemoteRule(description: description,
|
||||||
|
configuration: configuration?[description.ruleDescription.identifier])
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
public struct RuleDescription: Equatable {
|
public struct RuleDescription: Equatable, Codable {
|
||||||
public let identifier: String
|
public let identifier: String
|
||||||
public let name: String
|
public let name: String
|
||||||
public let description: String
|
public let description: String
|
||||||
|
@ -39,4 +39,31 @@ public struct RuleDescription: Equatable {
|
||||||
public static func == (lhs: RuleDescription, rhs: RuleDescription) -> Bool {
|
public static func == (lhs: RuleDescription, rhs: RuleDescription) -> Bool {
|
||||||
return lhs.identifier == rhs.identifier
|
return lhs.identifier == rhs.identifier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Codable
|
||||||
|
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.identifier = try container.decode(String.self, forKey: .identifier)
|
||||||
|
self.name = try container.decode(String.self, forKey: .name)
|
||||||
|
self.description = try container.decode(String.self, forKey: .description)
|
||||||
|
self.kind = try container.decode(RuleKind.self, forKey: .kind)
|
||||||
|
self.nonTriggeringExamples = container.optionalDecode([String].self, forKey: .nonTriggeringExamples) ?? []
|
||||||
|
self.triggeringExamples = container.optionalDecode([String].self, forKey: .triggeringExamples) ?? []
|
||||||
|
self.corrections = container.optionalDecode([String: String].self, forKey: .corrections) ?? [:]
|
||||||
|
self.deprecatedAliases = container.optionalDecode(Set<String>.self, forKey: .deprecatedAliases) ?? []
|
||||||
|
self.minSwiftVersion = container.optionalDecode(SwiftVersion.self, forKey: .minSwiftVersion) ?? .three
|
||||||
|
self.requiresFileOnDisk = container.optionalDecode(Bool.self, forKey: .requiresFileOnDisk) ?? false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension KeyedDecodingContainerProtocol {
|
||||||
|
func optionalDecode<T>(_ type: T.Type, forKey key: KeyedDecodingContainer<Key>.Key) -> T? where T: Decodable {
|
||||||
|
do {
|
||||||
|
return try decodeIfPresent(type, forKey: key)
|
||||||
|
} catch {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
public enum RuleKind: String {
|
public enum RuleKind: String, Codable {
|
||||||
case lint
|
case lint
|
||||||
case idiomatic
|
case idiomatic
|
||||||
case style
|
case style
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import SourceKittenFramework
|
import SourceKittenFramework
|
||||||
|
|
||||||
public struct SwiftVersion: RawRepresentable {
|
public struct SwiftVersion: RawRepresentable, Codable {
|
||||||
public typealias RawValue = String
|
public typealias RawValue = String
|
||||||
|
|
||||||
public let rawValue: String
|
public let rawValue: String
|
||||||
|
|
|
@ -18,8 +18,8 @@ public struct SuperfluousDisableCommandRule: ConfigurationProviderRule {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
public func reason(for rule: Rule.Type) -> String {
|
public func reason(for ruleDescription: RuleDescription) -> String {
|
||||||
return "SwiftLint rule '\(rule.description.identifier)' did not trigger a violation " +
|
return "SwiftLint rule '\(ruleDescription.identifier)' did not trigger a violation " +
|
||||||
"in the disabled region. Please remove the disable command."
|
"in the disabled region. Please remove the disable command."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,16 +124,6 @@ public struct LineLengthRule: ConfigurationProviderRule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// extracted from https://forums.swift.org/t/pitch-declaring-local-variables-as-lazy/9287/3
|
|
||||||
private class Lazy<Result> {
|
|
||||||
private var computation: () -> Result
|
|
||||||
fileprivate private(set) lazy var value: Result = computation()
|
|
||||||
|
|
||||||
init(_ computation: @escaping @autoclosure () -> Result) {
|
|
||||||
self.computation = computation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private extension String {
|
private extension String {
|
||||||
var strippingURLs: String {
|
var strippingURLs: String {
|
||||||
let range = NSRange(location: 0, length: bridge().length)
|
let range = NSRange(location: 0, length: bridge().length)
|
||||||
|
|
|
@ -163,6 +163,16 @@ extension Configuration {
|
||||||
return LintableFilesVisitor.create(options, cache: cache, block: visitorBlock).flatMap(visitLintableFiles)
|
return LintableFilesVisitor.create(options, cache: cache, block: visitorBlock).flatMap(visitLintableFiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func startPlugins() -> [Process] {
|
||||||
|
return plugins.map { executable in
|
||||||
|
let task = Process()
|
||||||
|
task.launchPath = executable
|
||||||
|
task.arguments = ["lint"]
|
||||||
|
task.launch()
|
||||||
|
return task
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: AutoCorrect Command
|
// MARK: AutoCorrect Command
|
||||||
|
|
||||||
init(options: AutoCorrectOptions) {
|
init(options: AutoCorrectOptions) {
|
||||||
|
|
|
@ -27,6 +27,8 @@ struct LintOrAnalyzeCommand {
|
||||||
let reporter = reporterFrom(optionsReporter: options.reporter, configuration: configuration)
|
let reporter = reporterFrom(optionsReporter: options.reporter, configuration: configuration)
|
||||||
let cache = options.ignoreCache ? nil : LinterCache(configuration: configuration)
|
let cache = options.ignoreCache ? nil : LinterCache(configuration: configuration)
|
||||||
let visitorMutationQueue = DispatchQueue(label: "io.realm.swiftlint.lintVisitorMutation")
|
let visitorMutationQueue = DispatchQueue(label: "io.realm.swiftlint.lintVisitorMutation")
|
||||||
|
let pluginsProcesses = configuration.startPlugins()
|
||||||
|
|
||||||
return configuration.visitLintableFiles(options: options, cache: cache) { linter in
|
return configuration.visitLintableFiles(options: options, cache: cache) { linter in
|
||||||
let currentViolations: [StyleViolation]
|
let currentViolations: [StyleViolation]
|
||||||
if options.benchmark {
|
if options.benchmark {
|
||||||
|
@ -47,8 +49,7 @@ struct LintOrAnalyzeCommand {
|
||||||
linter.file.invalidateCache()
|
linter.file.invalidateCache()
|
||||||
reporter.report(violations: currentViolations, realtimeCondition: true)
|
reporter.report(violations: currentViolations, realtimeCondition: true)
|
||||||
}.flatMap { files in
|
}.flatMap { files in
|
||||||
if isWarningThresholdBroken(configuration: configuration, violations: violations)
|
if isWarningThresholdBroken(configuration: configuration, violations: violations) && !options.lenient {
|
||||||
&& !options.lenient {
|
|
||||||
violations.append(createThresholdViolation(threshold: configuration.warningThreshold!))
|
violations.append(createThresholdViolation(threshold: configuration.warningThreshold!))
|
||||||
reporter.report(violations: [violations.last!], realtimeCondition: true)
|
reporter.report(violations: [violations.last!], realtimeCondition: true)
|
||||||
}
|
}
|
||||||
|
@ -63,6 +64,7 @@ struct LintOrAnalyzeCommand {
|
||||||
ruleBenchmark.save()
|
ruleBenchmark.save()
|
||||||
}
|
}
|
||||||
try? cache?.save()
|
try? cache?.save()
|
||||||
|
pluginsProcesses.forEach { $0.terminate() }
|
||||||
return successOrExit(numberOfSeriousViolations: numberOfSeriousViolations,
|
return successOrExit(numberOfSeriousViolations: numberOfSeriousViolations,
|
||||||
strictWithViolations: options.strict && !violations.isEmpty)
|
strictWithViolations: options.strict && !violations.isEmpty)
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,6 +224,8 @@
|
||||||
D4130D991E16CC1300242361 /* TypeNameRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4130D981E16CC1300242361 /* TypeNameRuleExamples.swift */; };
|
D4130D991E16CC1300242361 /* TypeNameRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4130D981E16CC1300242361 /* TypeNameRuleExamples.swift */; };
|
||||||
D414D6AC21D0B77F00960935 /* DiscouragedObjectLiteralRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D414D6AB21D0B77F00960935 /* DiscouragedObjectLiteralRuleTests.swift */; };
|
D414D6AC21D0B77F00960935 /* DiscouragedObjectLiteralRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D414D6AB21D0B77F00960935 /* DiscouragedObjectLiteralRuleTests.swift */; };
|
||||||
D414D6AE21D22FF500960935 /* LastWhereRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D414D6AD21D22FF500960935 /* LastWhereRule.swift */; };
|
D414D6AE21D22FF500960935 /* LastWhereRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D414D6AD21D22FF500960935 /* LastWhereRule.swift */; };
|
||||||
|
D414D6B021D34FA500960935 /* RemoteRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D414D6AF21D34FA500960935 /* RemoteRule.swift */; };
|
||||||
|
D414D6B221D3509B00960935 /* RemoteRuleResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = D414D6B121D3509B00960935 /* RemoteRuleResolver.swift */; };
|
||||||
D41B57781ED8CEE0007B0470 /* ExtensionAccessModifierRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41B57771ED8CEE0007B0470 /* ExtensionAccessModifierRule.swift */; };
|
D41B57781ED8CEE0007B0470 /* ExtensionAccessModifierRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41B57771ED8CEE0007B0470 /* ExtensionAccessModifierRule.swift */; };
|
||||||
D41E7E0B1DF9DABB0065259A /* RedundantStringEnumValueRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41E7E0A1DF9DABB0065259A /* RedundantStringEnumValueRule.swift */; };
|
D41E7E0B1DF9DABB0065259A /* RedundantStringEnumValueRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41E7E0A1DF9DABB0065259A /* RedundantStringEnumValueRule.swift */; };
|
||||||
D4246D6D1F30D8620097E658 /* PrivateOverFilePrivateRuleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4246D6C1F30D8620097E658 /* PrivateOverFilePrivateRuleConfiguration.swift */; };
|
D4246D6D1F30D8620097E658 /* PrivateOverFilePrivateRuleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4246D6C1F30D8620097E658 /* PrivateOverFilePrivateRuleConfiguration.swift */; };
|
||||||
|
@ -236,6 +238,7 @@
|
||||||
D43B04661E071ED3004016AF /* ColonRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43B04651E071ED3004016AF /* ColonRuleTests.swift */; };
|
D43B04661E071ED3004016AF /* ColonRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43B04651E071ED3004016AF /* ColonRuleTests.swift */; };
|
||||||
D43B04691E072291004016AF /* ColonConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43B04671E07228D004016AF /* ColonConfiguration.swift */; };
|
D43B04691E072291004016AF /* ColonConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43B04671E07228D004016AF /* ColonConfiguration.swift */; };
|
||||||
D43B046B1E075905004016AF /* ClosureEndIndentationRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43B046A1E075905004016AF /* ClosureEndIndentationRule.swift */; };
|
D43B046B1E075905004016AF /* ClosureEndIndentationRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43B046A1E075905004016AF /* ClosureEndIndentationRule.swift */; };
|
||||||
|
D43CD01721D4AFD200944FAC /* Socket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D43CD01621D4AFD200944FAC /* Socket.framework */; };
|
||||||
D43DB1081DC573DA00281215 /* ImplicitGetterRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43DB1071DC573DA00281215 /* ImplicitGetterRule.swift */; };
|
D43DB1081DC573DA00281215 /* ImplicitGetterRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43DB1071DC573DA00281215 /* ImplicitGetterRule.swift */; };
|
||||||
D44037972132730000FDA77B /* ProhibitedInterfaceBuilderRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44037962132730000FDA77B /* ProhibitedInterfaceBuilderRule.swift */; };
|
D44037972132730000FDA77B /* ProhibitedInterfaceBuilderRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44037962132730000FDA77B /* ProhibitedInterfaceBuilderRule.swift */; };
|
||||||
D44254201DB87CA200492EA4 /* ValidIBInspectableRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D442541E1DB87C3D00492EA4 /* ValidIBInspectableRule.swift */; };
|
D44254201DB87CA200492EA4 /* ValidIBInspectableRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D442541E1DB87C3D00492EA4 /* ValidIBInspectableRule.swift */; };
|
||||||
|
@ -256,6 +259,10 @@
|
||||||
D47079AB1DFDCF7A00027086 /* SwiftExpressionKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47079AA1DFDCF7A00027086 /* SwiftExpressionKind.swift */; };
|
D47079AB1DFDCF7A00027086 /* SwiftExpressionKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47079AA1DFDCF7A00027086 /* SwiftExpressionKind.swift */; };
|
||||||
D47079AD1DFE2FA700027086 /* EmptyParametersRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47079AC1DFE2FA700027086 /* EmptyParametersRule.swift */; };
|
D47079AD1DFE2FA700027086 /* EmptyParametersRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47079AC1DFE2FA700027086 /* EmptyParametersRule.swift */; };
|
||||||
D47079AF1DFE520000027086 /* VoidReturnRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47079AE1DFE520000027086 /* VoidReturnRule.swift */; };
|
D47079AF1DFE520000027086 /* VoidReturnRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47079AE1DFE520000027086 /* VoidReturnRule.swift */; };
|
||||||
|
D47820C621D8B3ED00F24836 /* ConfigurationTests+Plugins.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47820C521D8B3ED00F24836 /* ConfigurationTests+Plugins.swift */; };
|
||||||
|
D47820C821D8CBC000F24836 /* PluginDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47820C721D8CBC000F24836 /* PluginDescription.swift */; };
|
||||||
|
D47820CA21D8CD2C00F24836 /* Lazy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47820C921D8CD2C00F24836 /* Lazy.swift */; };
|
||||||
|
D47820CD21D9FA7100F24836 /* RemoteRuleResolverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47820CB21D9FA5B00F24836 /* RemoteRuleResolverTests.swift */; };
|
||||||
D47A510E1DB29EEB00A4CC21 /* SwitchCaseOnNewlineRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47A510D1DB29EEB00A4CC21 /* SwitchCaseOnNewlineRule.swift */; };
|
D47A510E1DB29EEB00A4CC21 /* SwitchCaseOnNewlineRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47A510D1DB29EEB00A4CC21 /* SwitchCaseOnNewlineRule.swift */; };
|
||||||
D47A51101DB2DD4800A4CC21 /* AttributesRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47A510F1DB2DD4800A4CC21 /* AttributesRule.swift */; };
|
D47A51101DB2DD4800A4CC21 /* AttributesRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47A510F1DB2DD4800A4CC21 /* AttributesRule.swift */; };
|
||||||
D47EF4801F69E3100012C4CA /* ColonRule+FunctionCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47EF47F1F69E3100012C4CA /* ColonRule+FunctionCall.swift */; };
|
D47EF4801F69E3100012C4CA /* ColonRule+FunctionCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47EF47F1F69E3100012C4CA /* ColonRule+FunctionCall.swift */; };
|
||||||
|
@ -267,6 +274,9 @@
|
||||||
D48B51231F4F5E4B0068AB98 /* DocumentationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D48B51221F4F5E4B0068AB98 /* DocumentationTests.swift */; };
|
D48B51231F4F5E4B0068AB98 /* DocumentationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D48B51221F4F5E4B0068AB98 /* DocumentationTests.swift */; };
|
||||||
D495B1A221165DAA00E2CD7B /* FileNameRuleFixtures in Resources */ = {isa = PBXBuildFile; fileRef = D495B1A021165DAA00E2CD7B /* FileNameRuleFixtures */; };
|
D495B1A221165DAA00E2CD7B /* FileNameRuleFixtures in Resources */ = {isa = PBXBuildFile; fileRef = D495B1A021165DAA00E2CD7B /* FileNameRuleFixtures */; };
|
||||||
D495B1A321165DAA00E2CD7B /* FileHeaderRuleFixtures in Resources */ = {isa = PBXBuildFile; fileRef = D495B1A121165DAA00E2CD7B /* FileHeaderRuleFixtures */; };
|
D495B1A321165DAA00E2CD7B /* FileHeaderRuleFixtures in Resources */ = {isa = PBXBuildFile; fileRef = D495B1A121165DAA00E2CD7B /* FileHeaderRuleFixtures */; };
|
||||||
|
D496009221DF32D700520803 /* RemoteLintServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D496009121DF32D700520803 /* RemoteLintServer.swift */; };
|
||||||
|
D496009421DF376B00520803 /* RemoteRulePayload.swift in Sources */ = {isa = PBXBuildFile; fileRef = D496009321DF376B00520803 /* RemoteRulePayload.swift */; };
|
||||||
|
D496009621DF39DF00520803 /* RemoteRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D496009521DF39DF00520803 /* RemoteRuleTests.swift */; };
|
||||||
D49896F12026B36C00814A83 /* RedundantSetAccessControlRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49896F02026B36C00814A83 /* RedundantSetAccessControlRule.swift */; };
|
D49896F12026B36C00814A83 /* RedundantSetAccessControlRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49896F02026B36C00814A83 /* RedundantSetAccessControlRule.swift */; };
|
||||||
D4998DE71DF191380006E05D /* AttributesRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4998DE61DF191380006E05D /* AttributesRuleTests.swift */; };
|
D4998DE71DF191380006E05D /* AttributesRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4998DE61DF191380006E05D /* AttributesRuleTests.swift */; };
|
||||||
D4998DE91DF194F20006E05D /* FileHeaderRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4998DE81DF194F20006E05D /* FileHeaderRuleTests.swift */; };
|
D4998DE91DF194F20006E05D /* FileHeaderRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4998DE81DF194F20006E05D /* FileHeaderRuleTests.swift */; };
|
||||||
|
@ -288,6 +298,7 @@
|
||||||
D4C889711E385B7B00BAE88D /* RedundantDiscardableLetRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C889701E385B7B00BAE88D /* RedundantDiscardableLetRule.swift */; };
|
D4C889711E385B7B00BAE88D /* RedundantDiscardableLetRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C889701E385B7B00BAE88D /* RedundantDiscardableLetRule.swift */; };
|
||||||
D4CA758F1E2DEEA500A40E8A /* NumberSeparatorRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CA758E1E2DEEA500A40E8A /* NumberSeparatorRuleTests.swift */; };
|
D4CA758F1E2DEEA500A40E8A /* NumberSeparatorRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CA758E1E2DEEA500A40E8A /* NumberSeparatorRuleTests.swift */; };
|
||||||
D4CFC5D2209EC95A00668488 /* FunctionDefaultParameterAtEndRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CFC5D1209EC95A00668488 /* FunctionDefaultParameterAtEndRule.swift */; };
|
D4CFC5D2209EC95A00668488 /* FunctionDefaultParameterAtEndRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CFC5D1209EC95A00668488 /* FunctionDefaultParameterAtEndRule.swift */; };
|
||||||
|
D4D11B1D21D8AE2300FB9D93 /* RuleDescriptionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D11B1C21D8AE2300FB9D93 /* RuleDescriptionTests.swift */; };
|
||||||
D4D1B9BB1EAC2C910028BE6A /* AccessControlLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D1B9B91EAC2C870028BE6A /* AccessControlLevel.swift */; };
|
D4D1B9BB1EAC2C910028BE6A /* AccessControlLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D1B9B91EAC2C870028BE6A /* AccessControlLevel.swift */; };
|
||||||
D4D383852145F550000235BD /* StaticOperatorRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D383842145F550000235BD /* StaticOperatorRule.swift */; };
|
D4D383852145F550000235BD /* StaticOperatorRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D383842145F550000235BD /* StaticOperatorRule.swift */; };
|
||||||
D4D5A5FF1E1F3A1C00D15E0C /* ShorthandOperatorRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D5A5FE1E1F3A1C00D15E0C /* ShorthandOperatorRule.swift */; };
|
D4D5A5FF1E1F3A1C00D15E0C /* ShorthandOperatorRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D5A5FE1E1F3A1C00D15E0C /* ShorthandOperatorRule.swift */; };
|
||||||
|
@ -678,6 +689,8 @@
|
||||||
D4130D981E16CC1300242361 /* TypeNameRuleExamples.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypeNameRuleExamples.swift; sourceTree = "<group>"; };
|
D4130D981E16CC1300242361 /* TypeNameRuleExamples.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypeNameRuleExamples.swift; sourceTree = "<group>"; };
|
||||||
D414D6AB21D0B77F00960935 /* DiscouragedObjectLiteralRuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscouragedObjectLiteralRuleTests.swift; sourceTree = "<group>"; };
|
D414D6AB21D0B77F00960935 /* DiscouragedObjectLiteralRuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscouragedObjectLiteralRuleTests.swift; sourceTree = "<group>"; };
|
||||||
D414D6AD21D22FF500960935 /* LastWhereRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LastWhereRule.swift; sourceTree = "<group>"; };
|
D414D6AD21D22FF500960935 /* LastWhereRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LastWhereRule.swift; sourceTree = "<group>"; };
|
||||||
|
D414D6AF21D34FA500960935 /* RemoteRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteRule.swift; sourceTree = "<group>"; };
|
||||||
|
D414D6B121D3509B00960935 /* RemoteRuleResolver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteRuleResolver.swift; sourceTree = "<group>"; };
|
||||||
D41B57771ED8CEE0007B0470 /* ExtensionAccessModifierRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionAccessModifierRule.swift; sourceTree = "<group>"; };
|
D41B57771ED8CEE0007B0470 /* ExtensionAccessModifierRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionAccessModifierRule.swift; sourceTree = "<group>"; };
|
||||||
D41E7E0A1DF9DABB0065259A /* RedundantStringEnumValueRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedundantStringEnumValueRule.swift; sourceTree = "<group>"; };
|
D41E7E0A1DF9DABB0065259A /* RedundantStringEnumValueRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedundantStringEnumValueRule.swift; sourceTree = "<group>"; };
|
||||||
D4246D6C1F30D8620097E658 /* PrivateOverFilePrivateRuleConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrivateOverFilePrivateRuleConfiguration.swift; sourceTree = "<group>"; };
|
D4246D6C1F30D8620097E658 /* PrivateOverFilePrivateRuleConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrivateOverFilePrivateRuleConfiguration.swift; sourceTree = "<group>"; };
|
||||||
|
@ -690,6 +703,7 @@
|
||||||
D43B04651E071ED3004016AF /* ColonRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColonRuleTests.swift; sourceTree = "<group>"; };
|
D43B04651E071ED3004016AF /* ColonRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColonRuleTests.swift; sourceTree = "<group>"; };
|
||||||
D43B04671E07228D004016AF /* ColonConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColonConfiguration.swift; sourceTree = "<group>"; };
|
D43B04671E07228D004016AF /* ColonConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColonConfiguration.swift; sourceTree = "<group>"; };
|
||||||
D43B046A1E075905004016AF /* ClosureEndIndentationRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClosureEndIndentationRule.swift; sourceTree = "<group>"; };
|
D43B046A1E075905004016AF /* ClosureEndIndentationRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClosureEndIndentationRule.swift; sourceTree = "<group>"; };
|
||||||
|
D43CD01621D4AFD200944FAC /* Socket.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Socket.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D43DB1071DC573DA00281215 /* ImplicitGetterRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImplicitGetterRule.swift; sourceTree = "<group>"; };
|
D43DB1071DC573DA00281215 /* ImplicitGetterRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImplicitGetterRule.swift; sourceTree = "<group>"; };
|
||||||
D44037962132730000FDA77B /* ProhibitedInterfaceBuilderRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProhibitedInterfaceBuilderRule.swift; sourceTree = "<group>"; };
|
D44037962132730000FDA77B /* ProhibitedInterfaceBuilderRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProhibitedInterfaceBuilderRule.swift; sourceTree = "<group>"; };
|
||||||
D442541E1DB87C3D00492EA4 /* ValidIBInspectableRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidIBInspectableRule.swift; sourceTree = "<group>"; };
|
D442541E1DB87C3D00492EA4 /* ValidIBInspectableRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidIBInspectableRule.swift; sourceTree = "<group>"; };
|
||||||
|
@ -710,6 +724,10 @@
|
||||||
D47079AA1DFDCF7A00027086 /* SwiftExpressionKind.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftExpressionKind.swift; sourceTree = "<group>"; };
|
D47079AA1DFDCF7A00027086 /* SwiftExpressionKind.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftExpressionKind.swift; sourceTree = "<group>"; };
|
||||||
D47079AC1DFE2FA700027086 /* EmptyParametersRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyParametersRule.swift; sourceTree = "<group>"; };
|
D47079AC1DFE2FA700027086 /* EmptyParametersRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyParametersRule.swift; sourceTree = "<group>"; };
|
||||||
D47079AE1DFE520000027086 /* VoidReturnRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VoidReturnRule.swift; sourceTree = "<group>"; };
|
D47079AE1DFE520000027086 /* VoidReturnRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VoidReturnRule.swift; sourceTree = "<group>"; };
|
||||||
|
D47820C521D8B3ED00F24836 /* ConfigurationTests+Plugins.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConfigurationTests+Plugins.swift"; sourceTree = "<group>"; };
|
||||||
|
D47820C721D8CBC000F24836 /* PluginDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginDescription.swift; sourceTree = "<group>"; };
|
||||||
|
D47820C921D8CD2C00F24836 /* Lazy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Lazy.swift; sourceTree = "<group>"; };
|
||||||
|
D47820CB21D9FA5B00F24836 /* RemoteRuleResolverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteRuleResolverTests.swift; sourceTree = "<group>"; };
|
||||||
D47A510D1DB29EEB00A4CC21 /* SwitchCaseOnNewlineRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwitchCaseOnNewlineRule.swift; sourceTree = "<group>"; };
|
D47A510D1DB29EEB00A4CC21 /* SwitchCaseOnNewlineRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwitchCaseOnNewlineRule.swift; sourceTree = "<group>"; };
|
||||||
D47A510F1DB2DD4800A4CC21 /* AttributesRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributesRule.swift; sourceTree = "<group>"; };
|
D47A510F1DB2DD4800A4CC21 /* AttributesRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributesRule.swift; sourceTree = "<group>"; };
|
||||||
D47EF47F1F69E3100012C4CA /* ColonRule+FunctionCall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ColonRule+FunctionCall.swift"; sourceTree = "<group>"; };
|
D47EF47F1F69E3100012C4CA /* ColonRule+FunctionCall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ColonRule+FunctionCall.swift"; sourceTree = "<group>"; };
|
||||||
|
@ -721,6 +739,9 @@
|
||||||
D48B51221F4F5E4B0068AB98 /* DocumentationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DocumentationTests.swift; sourceTree = "<group>"; };
|
D48B51221F4F5E4B0068AB98 /* DocumentationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DocumentationTests.swift; sourceTree = "<group>"; };
|
||||||
D495B1A021165DAA00E2CD7B /* FileNameRuleFixtures */ = {isa = PBXFileReference; lastKnownFileType = folder; path = FileNameRuleFixtures; sourceTree = "<group>"; };
|
D495B1A021165DAA00E2CD7B /* FileNameRuleFixtures */ = {isa = PBXFileReference; lastKnownFileType = folder; path = FileNameRuleFixtures; sourceTree = "<group>"; };
|
||||||
D495B1A121165DAA00E2CD7B /* FileHeaderRuleFixtures */ = {isa = PBXFileReference; lastKnownFileType = folder; path = FileHeaderRuleFixtures; sourceTree = "<group>"; };
|
D495B1A121165DAA00E2CD7B /* FileHeaderRuleFixtures */ = {isa = PBXFileReference; lastKnownFileType = folder; path = FileHeaderRuleFixtures; sourceTree = "<group>"; };
|
||||||
|
D496009121DF32D700520803 /* RemoteLintServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteLintServer.swift; sourceTree = "<group>"; };
|
||||||
|
D496009321DF376B00520803 /* RemoteRulePayload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteRulePayload.swift; sourceTree = "<group>"; };
|
||||||
|
D496009521DF39DF00520803 /* RemoteRuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteRuleTests.swift; sourceTree = "<group>"; };
|
||||||
D49896F02026B36C00814A83 /* RedundantSetAccessControlRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedundantSetAccessControlRule.swift; sourceTree = "<group>"; };
|
D49896F02026B36C00814A83 /* RedundantSetAccessControlRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedundantSetAccessControlRule.swift; sourceTree = "<group>"; };
|
||||||
D4998DE61DF191380006E05D /* AttributesRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributesRuleTests.swift; sourceTree = "<group>"; };
|
D4998DE61DF191380006E05D /* AttributesRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributesRuleTests.swift; sourceTree = "<group>"; };
|
||||||
D4998DE81DF194F20006E05D /* FileHeaderRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileHeaderRuleTests.swift; sourceTree = "<group>"; };
|
D4998DE81DF194F20006E05D /* FileHeaderRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileHeaderRuleTests.swift; sourceTree = "<group>"; };
|
||||||
|
@ -742,6 +763,7 @@
|
||||||
D4C889701E385B7B00BAE88D /* RedundantDiscardableLetRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedundantDiscardableLetRule.swift; sourceTree = "<group>"; };
|
D4C889701E385B7B00BAE88D /* RedundantDiscardableLetRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedundantDiscardableLetRule.swift; sourceTree = "<group>"; };
|
||||||
D4CA758E1E2DEEA500A40E8A /* NumberSeparatorRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberSeparatorRuleTests.swift; sourceTree = "<group>"; };
|
D4CA758E1E2DEEA500A40E8A /* NumberSeparatorRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberSeparatorRuleTests.swift; sourceTree = "<group>"; };
|
||||||
D4CFC5D1209EC95A00668488 /* FunctionDefaultParameterAtEndRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FunctionDefaultParameterAtEndRule.swift; sourceTree = "<group>"; };
|
D4CFC5D1209EC95A00668488 /* FunctionDefaultParameterAtEndRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FunctionDefaultParameterAtEndRule.swift; sourceTree = "<group>"; };
|
||||||
|
D4D11B1C21D8AE2300FB9D93 /* RuleDescriptionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleDescriptionTests.swift; sourceTree = "<group>"; };
|
||||||
D4D1B9B91EAC2C870028BE6A /* AccessControlLevel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessControlLevel.swift; sourceTree = "<group>"; };
|
D4D1B9B91EAC2C870028BE6A /* AccessControlLevel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessControlLevel.swift; sourceTree = "<group>"; };
|
||||||
D4D383842145F550000235BD /* StaticOperatorRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticOperatorRule.swift; sourceTree = "<group>"; };
|
D4D383842145F550000235BD /* StaticOperatorRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticOperatorRule.swift; sourceTree = "<group>"; };
|
||||||
D4D5A5FE1E1F3A1C00D15E0C /* ShorthandOperatorRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShorthandOperatorRule.swift; sourceTree = "<group>"; };
|
D4D5A5FE1E1F3A1C00D15E0C /* ShorthandOperatorRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShorthandOperatorRule.swift; sourceTree = "<group>"; };
|
||||||
|
@ -855,6 +877,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
D43CD01721D4AFD200944FAC /* Socket.framework in Frameworks */,
|
||||||
E876BFBE1B07828500114ED5 /* SourceKittenFramework.framework in Frameworks */,
|
E876BFBE1B07828500114ED5 /* SourceKittenFramework.framework in Frameworks */,
|
||||||
E8C0DFCD1AD349DB007EE3D4 /* SWXMLHash.framework in Frameworks */,
|
E8C0DFCD1AD349DB007EE3D4 /* SWXMLHash.framework in Frameworks */,
|
||||||
3BBF2F9D1C640A0F006CD775 /* SwiftyTextTable.framework in Frameworks */,
|
3BBF2F9D1C640A0F006CD775 /* SwiftyTextTable.framework in Frameworks */,
|
||||||
|
@ -1190,6 +1213,7 @@
|
||||||
D0D1211A19E87861005E4BAA /* swiftlint */,
|
D0D1211A19E87861005E4BAA /* swiftlint */,
|
||||||
D0D1216E19E87B05005E4BAA /* SwiftLintFramework */,
|
D0D1216E19E87B05005E4BAA /* SwiftLintFramework */,
|
||||||
D0D1217B19E87B05005E4BAA /* SwiftLintFrameworkTests */,
|
D0D1217B19E87B05005E4BAA /* SwiftLintFrameworkTests */,
|
||||||
|
D43CD01521D4AFD200944FAC /* Frameworks */,
|
||||||
);
|
);
|
||||||
indentWidth = 4;
|
indentWidth = 4;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1329,6 +1353,7 @@
|
||||||
C2B3C15F2106F78100088928 /* ConfigurationAliasesTests.swift */,
|
C2B3C15F2106F78100088928 /* ConfigurationAliasesTests.swift */,
|
||||||
E809EDA21B8A73FB00399043 /* ConfigurationTests.swift */,
|
E809EDA21B8A73FB00399043 /* ConfigurationTests.swift */,
|
||||||
F480DC7E1F26090000099465 /* ConfigurationTests+Nested.swift */,
|
F480DC7E1F26090000099465 /* ConfigurationTests+Nested.swift */,
|
||||||
|
D47820C521D8B3ED00F24836 /* ConfigurationTests+Plugins.swift */,
|
||||||
F480DC821F2609D700099465 /* ConfigurationTests+ProjectMock.swift */,
|
F480DC821F2609D700099465 /* ConfigurationTests+ProjectMock.swift */,
|
||||||
3BB47D861C51DE6E00AE6A10 /* CustomRulesTests.swift */,
|
3BB47D861C51DE6E00AE6A10 /* CustomRulesTests.swift */,
|
||||||
67932E2C1E54AF4B00CB0629 /* CyclomaticComplexityConfigurationTests.swift */,
|
67932E2C1E54AF4B00CB0629 /* CyclomaticComplexityConfigurationTests.swift */,
|
||||||
|
@ -1363,11 +1388,14 @@
|
||||||
D4F5851820E99B5A0085C6D8 /* PrivateOutletRuleTests.swift */,
|
D4F5851820E99B5A0085C6D8 /* PrivateOutletRuleTests.swift */,
|
||||||
D4246D6E1F30DB260097E658 /* PrivateOverFilePrivateRuleTests.swift */,
|
D4246D6E1F30DB260097E658 /* PrivateOverFilePrivateRuleTests.swift */,
|
||||||
E81ADD711ED5ED9D000CD451 /* RegionTests.swift */,
|
E81ADD711ED5ED9D000CD451 /* RegionTests.swift */,
|
||||||
|
D47820CB21D9FA5B00F24836 /* RemoteRuleResolverTests.swift */,
|
||||||
|
D496009521DF39DF00520803 /* RemoteRuleTests.swift */,
|
||||||
E86396C61BADAFE6002C9E88 /* ReporterTests.swift */,
|
E86396C61BADAFE6002C9E88 /* ReporterTests.swift */,
|
||||||
B89F3BCB1FD5EDA900931E59 /* RequiredEnumCaseRuleTestCase.swift */,
|
B89F3BCB1FD5EDA900931E59 /* RequiredEnumCaseRuleTestCase.swift */,
|
||||||
3B12C9BE1C3209AC000B423F /* Resources */,
|
3B12C9BE1C3209AC000B423F /* Resources */,
|
||||||
3BCC04D31C502BAB006073C3 /* RuleConfigurationTests.swift */,
|
3BCC04D31C502BAB006073C3 /* RuleConfigurationTests.swift */,
|
||||||
D45255C71F0932F8003C9B56 /* RuleDescription+Examples.swift */,
|
D45255C71F0932F8003C9B56 /* RuleDescription+Examples.swift */,
|
||||||
|
D4D11B1C21D8AE2300FB9D93 /* RuleDescriptionTests.swift */,
|
||||||
E8BB8F9B1B17DE3B00199606 /* RulesTests.swift */,
|
E8BB8F9B1B17DE3B00199606 /* RulesTests.swift */,
|
||||||
3B12C9C61C3361CB000B423F /* RuleTests.swift */,
|
3B12C9C61C3361CB000B423F /* RuleTests.swift */,
|
||||||
6C7045431C6ADA450003F15A /* SourceKitCrashTests.swift */,
|
6C7045431C6ADA450003F15A /* SourceKitCrashTests.swift */,
|
||||||
|
@ -1399,6 +1427,14 @@
|
||||||
path = "Supporting Files";
|
path = "Supporting Files";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D43CD01521D4AFD200944FAC /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D43CD01621D4AFD200944FAC /* Socket.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
E802ECFE1C56A54600A35AE1 /* Helpers */ = {
|
E802ECFE1C56A54600A35AE1 /* Helpers */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -1475,10 +1511,12 @@
|
||||||
3BCC04CC1C4F5694006073C3 /* ConfigurationError.swift */,
|
3BCC04CC1C4F5694006073C3 /* ConfigurationError.swift */,
|
||||||
E8B67C3D1C095E6300FDED8E /* Correction.swift */,
|
E8B67C3D1C095E6300FDED8E /* Correction.swift */,
|
||||||
E812249B1B04FADC001783D2 /* Linter.swift */,
|
E812249B1B04FADC001783D2 /* Linter.swift */,
|
||||||
|
D47820C921D8CD2C00F24836 /* Lazy.swift */,
|
||||||
D4FD58B11E12A0200019503C /* LinterCache.swift */,
|
D4FD58B11E12A0200019503C /* LinterCache.swift */,
|
||||||
E88DEA6E1B09843F00A66CB0 /* Location.swift */,
|
E88DEA6E1B09843F00A66CB0 /* Location.swift */,
|
||||||
3B12C9C41C322032000B423F /* MasterRuleList.swift */,
|
3B12C9C41C322032000B423F /* MasterRuleList.swift */,
|
||||||
E80E018E1B92C1350078EB70 /* Region.swift */,
|
E80E018E1B92C1350078EB70 /* Region.swift */,
|
||||||
|
D47820C721D8CBC000F24836 /* PluginDescription.swift */,
|
||||||
83D71E261B131EB5000395DE /* RuleDescription.swift */,
|
83D71E261B131EB5000395DE /* RuleDescription.swift */,
|
||||||
CC26ED05204DE86E0013BBBC /* RuleIdentifier.swift */,
|
CC26ED05204DE86E0013BBBC /* RuleIdentifier.swift */,
|
||||||
E8BDE3FE1EDF91B6002EC12F /* RuleList.swift */,
|
E8BDE3FE1EDF91B6002EC12F /* RuleList.swift */,
|
||||||
|
@ -1490,6 +1528,10 @@
|
||||||
D4C27BFD1E12D53F00DF713E /* Version.swift */,
|
D4C27BFD1E12D53F00DF713E /* Version.swift */,
|
||||||
E88DEA701B09847500A66CB0 /* ViolationSeverity.swift */,
|
E88DEA701B09847500A66CB0 /* ViolationSeverity.swift */,
|
||||||
3BD9CD3C1C37175B009A5D25 /* YamlParser.swift */,
|
3BD9CD3C1C37175B009A5D25 /* YamlParser.swift */,
|
||||||
|
D414D6AF21D34FA500960935 /* RemoteRule.swift */,
|
||||||
|
D414D6B121D3509B00960935 /* RemoteRuleResolver.swift */,
|
||||||
|
D496009121DF32D700520803 /* RemoteLintServer.swift */,
|
||||||
|
D496009321DF376B00520803 /* RemoteRulePayload.swift */,
|
||||||
);
|
);
|
||||||
path = Models;
|
path = Models;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1831,6 +1873,7 @@
|
||||||
BFF028AE1CBCF8A500B38A9D /* TrailingWhitespaceConfiguration.swift in Sources */,
|
BFF028AE1CBCF8A500B38A9D /* TrailingWhitespaceConfiguration.swift in Sources */,
|
||||||
3B034B6E1E0BE549005D49A9 /* LineLengthConfiguration.swift in Sources */,
|
3B034B6E1E0BE549005D49A9 /* LineLengthConfiguration.swift in Sources */,
|
||||||
B25DCD0C1F7E9FA20028A199 /* MultilineArgumentsRule.swift in Sources */,
|
B25DCD0C1F7E9FA20028A199 /* MultilineArgumentsRule.swift in Sources */,
|
||||||
|
D414D6B021D34FA500960935 /* RemoteRule.swift in Sources */,
|
||||||
6258783B1FFC458100AC34F2 /* DiscouragedObjectLiteralRule.swift in Sources */,
|
6258783B1FFC458100AC34F2 /* DiscouragedObjectLiteralRule.swift in Sources */,
|
||||||
62A3E95D209E084000547A86 /* EmptyXCTestMethodRule.swift in Sources */,
|
62A3E95D209E084000547A86 /* EmptyXCTestMethodRule.swift in Sources */,
|
||||||
D4C4A34C1DEA4FF000E0E04C /* AttributesConfiguration.swift in Sources */,
|
D4C4A34C1DEA4FF000E0E04C /* AttributesConfiguration.swift in Sources */,
|
||||||
|
@ -1862,12 +1905,14 @@
|
||||||
D4DA1DFE1E1A10DB0037413D /* NumberSeparatorConfiguration.swift in Sources */,
|
D4DA1DFE1E1A10DB0037413D /* NumberSeparatorConfiguration.swift in Sources */,
|
||||||
E88198601BEA98F000333A11 /* IdentifierNameRule.swift in Sources */,
|
E88198601BEA98F000333A11 /* IdentifierNameRule.swift in Sources */,
|
||||||
E88DEA791B098D4400A66CB0 /* RuleParameter.swift in Sources */,
|
E88DEA791B098D4400A66CB0 /* RuleParameter.swift in Sources */,
|
||||||
|
D496009221DF32D700520803 /* RemoteLintServer.swift in Sources */,
|
||||||
8F715B83213B528B00427BD9 /* UnusedImportRule.swift in Sources */,
|
8F715B83213B528B00427BD9 /* UnusedImportRule.swift in Sources */,
|
||||||
626D02971F31CBCC0054788D /* XCTFailMessageRule.swift in Sources */,
|
626D02971F31CBCC0054788D /* XCTFailMessageRule.swift in Sources */,
|
||||||
D4DA1DFA1E18D6200037413D /* LargeTupleRule.swift in Sources */,
|
D4DA1DFA1E18D6200037413D /* LargeTupleRule.swift in Sources */,
|
||||||
D4B022A41E105636007E5297 /* GenericTypeNameRule.swift in Sources */,
|
D4B022A41E105636007E5297 /* GenericTypeNameRule.swift in Sources */,
|
||||||
E86396CB1BADB519002C9E88 /* CSVReporter.swift in Sources */,
|
E86396CB1BADB519002C9E88 /* CSVReporter.swift in Sources */,
|
||||||
37B3FA8B1DFD45A700AD30D2 /* Dictionary+SwiftLint.swift in Sources */,
|
37B3FA8B1DFD45A700AD30D2 /* Dictionary+SwiftLint.swift in Sources */,
|
||||||
|
D47820CA21D8CD2C00F24836 /* Lazy.swift in Sources */,
|
||||||
823EDC6221020D850070B7CD /* MultilineLiteralBracketsRule.swift in Sources */,
|
823EDC6221020D850070B7CD /* MultilineLiteralBracketsRule.swift in Sources */,
|
||||||
D47EF4801F69E3100012C4CA /* ColonRule+FunctionCall.swift in Sources */,
|
D47EF4801F69E3100012C4CA /* ColonRule+FunctionCall.swift in Sources */,
|
||||||
E88198561BEA94D800333A11 /* FileLengthRule.swift in Sources */,
|
E88198561BEA94D800333A11 /* FileLengthRule.swift in Sources */,
|
||||||
|
@ -1907,6 +1952,7 @@
|
||||||
C3EF547821B5A4000009262F /* LegacyHashingRule.swift in Sources */,
|
C3EF547821B5A4000009262F /* LegacyHashingRule.swift in Sources */,
|
||||||
31F1B6CC1F60BF4500A57456 /* SwitchCaseAlignmentRule.swift in Sources */,
|
31F1B6CC1F60BF4500A57456 /* SwitchCaseAlignmentRule.swift in Sources */,
|
||||||
E88DEA731B0984C400A66CB0 /* String+SwiftLint.swift in Sources */,
|
E88DEA731B0984C400A66CB0 /* String+SwiftLint.swift in Sources */,
|
||||||
|
D496009421DF376B00520803 /* RemoteRulePayload.swift in Sources */,
|
||||||
E88198591BEA95F100333A11 /* LeadingWhitespaceRule.swift in Sources */,
|
E88198591BEA95F100333A11 /* LeadingWhitespaceRule.swift in Sources */,
|
||||||
D42B45D91F0AF5E30086B683 /* StrictFilePrivateRule.swift in Sources */,
|
D42B45D91F0AF5E30086B683 /* StrictFilePrivateRule.swift in Sources */,
|
||||||
1EC163521D5992D900DD2928 /* VerticalWhitespaceRule.swift in Sources */,
|
1EC163521D5992D900DD2928 /* VerticalWhitespaceRule.swift in Sources */,
|
||||||
|
@ -2008,10 +2054,12 @@
|
||||||
CE8178ED1EAC039D0063186E /* UnusedOptionalBindingConfiguration.swift in Sources */,
|
CE8178ED1EAC039D0063186E /* UnusedOptionalBindingConfiguration.swift in Sources */,
|
||||||
62DEA1661FB21A9E00BCCCC6 /* PrivateActionRule.swift in Sources */,
|
62DEA1661FB21A9E00BCCCC6 /* PrivateActionRule.swift in Sources */,
|
||||||
D4FD58B21E12A0200019503C /* LinterCache.swift in Sources */,
|
D4FD58B21E12A0200019503C /* LinterCache.swift in Sources */,
|
||||||
|
D47820C821D8CBC000F24836 /* PluginDescription.swift in Sources */,
|
||||||
3BD9CD3D1C37175B009A5D25 /* YamlParser.swift in Sources */,
|
3BD9CD3D1C37175B009A5D25 /* YamlParser.swift in Sources */,
|
||||||
F22314B01D4FA4D7009AD165 /* LegacyNSGeometryFunctionsRule.swift in Sources */,
|
F22314B01D4FA4D7009AD165 /* LegacyNSGeometryFunctionsRule.swift in Sources */,
|
||||||
E88DEA8C1B0999A000A66CB0 /* ASTRule.swift in Sources */,
|
E88DEA8C1B0999A000A66CB0 /* ASTRule.swift in Sources */,
|
||||||
62426A032118BA6E007E6340 /* ClosureBodyLengthRule.swift in Sources */,
|
62426A032118BA6E007E6340 /* ClosureBodyLengthRule.swift in Sources */,
|
||||||
|
D414D6B221D3509B00960935 /* RemoteRuleResolver.swift in Sources */,
|
||||||
1E82D5591D7775C7009553D7 /* ClosureSpacingRule.swift in Sources */,
|
1E82D5591D7775C7009553D7 /* ClosureSpacingRule.swift in Sources */,
|
||||||
E80746F61ECB722F00548D31 /* CacheDescriptionProvider.swift in Sources */,
|
E80746F61ECB722F00548D31 /* CacheDescriptionProvider.swift in Sources */,
|
||||||
094385041D5D4F7C009168CF /* PrivateOutletRule.swift in Sources */,
|
094385041D5D4F7C009168CF /* PrivateOutletRule.swift in Sources */,
|
||||||
|
@ -2085,6 +2133,7 @@
|
||||||
D4C27C001E12DFF500DF713E /* LinterCacheTests.swift in Sources */,
|
D4C27C001E12DFF500DF713E /* LinterCacheTests.swift in Sources */,
|
||||||
D45255C81F0932F8003C9B56 /* RuleDescription+Examples.swift in Sources */,
|
D45255C81F0932F8003C9B56 /* RuleDescription+Examples.swift in Sources */,
|
||||||
E81ADD721ED5ED9D000CD451 /* RegionTests.swift in Sources */,
|
E81ADD721ED5ED9D000CD451 /* RegionTests.swift in Sources */,
|
||||||
|
D4D11B1D21D8AE2300FB9D93 /* RuleDescriptionTests.swift in Sources */,
|
||||||
D4998DE91DF194F20006E05D /* FileHeaderRuleTests.swift in Sources */,
|
D4998DE91DF194F20006E05D /* FileHeaderRuleTests.swift in Sources */,
|
||||||
750BBD0B214180AF007EC437 /* CollectionAlignmentRuleTests.swift in Sources */,
|
750BBD0B214180AF007EC437 /* CollectionAlignmentRuleTests.swift in Sources */,
|
||||||
8B01E50220A4349100C9233E /* FunctionParameterCountRuleTests.swift in Sources */,
|
8B01E50220A4349100C9233E /* FunctionParameterCountRuleTests.swift in Sources */,
|
||||||
|
@ -2092,6 +2141,7 @@
|
||||||
E81ADD741ED6052F000CD451 /* CommandTests.swift in Sources */,
|
E81ADD741ED6052F000CD451 /* CommandTests.swift in Sources */,
|
||||||
29FFC37D1F157BDE007E4825 /* FileLengthRuleTests.swift in Sources */,
|
29FFC37D1F157BDE007E4825 /* FileLengthRuleTests.swift in Sources */,
|
||||||
006204DE1E1E4E0A00FFFBE1 /* VerticalWhitespaceRuleTests.swift in Sources */,
|
006204DE1E1E4E0A00FFFBE1 /* VerticalWhitespaceRuleTests.swift in Sources */,
|
||||||
|
D47820CD21D9FA7100F24836 /* RemoteRuleResolverTests.swift in Sources */,
|
||||||
02FD8AEF1BFC18D60014BFFB /* ExtendedNSStringTests.swift in Sources */,
|
02FD8AEF1BFC18D60014BFFB /* ExtendedNSStringTests.swift in Sources */,
|
||||||
12E3D4DC2042729300B3E30E /* ExplicitTypeInterfaceRuleTests.swift in Sources */,
|
12E3D4DC2042729300B3E30E /* ExplicitTypeInterfaceRuleTests.swift in Sources */,
|
||||||
D48B51231F4F5E4B0068AB98 /* DocumentationTests.swift in Sources */,
|
D48B51231F4F5E4B0068AB98 /* DocumentationTests.swift in Sources */,
|
||||||
|
@ -2103,6 +2153,7 @@
|
||||||
6C7045441C6ADA450003F15A /* SourceKitCrashTests.swift in Sources */,
|
6C7045441C6ADA450003F15A /* SourceKitCrashTests.swift in Sources */,
|
||||||
820F451E21073D7200AA056A /* ConditionalReturnsOnNewlineRuleTests.swift in Sources */,
|
820F451E21073D7200AA056A /* ConditionalReturnsOnNewlineRuleTests.swift in Sources */,
|
||||||
D4246D6F1F30DB260097E658 /* PrivateOverFilePrivateRuleTests.swift in Sources */,
|
D4246D6F1F30DB260097E658 /* PrivateOverFilePrivateRuleTests.swift in Sources */,
|
||||||
|
D496009621DF39DF00520803 /* RemoteRuleTests.swift in Sources */,
|
||||||
B25DCD101F7EF6DC0028A199 /* MultilineArgumentsRuleTests.swift in Sources */,
|
B25DCD101F7EF6DC0028A199 /* MultilineArgumentsRuleTests.swift in Sources */,
|
||||||
3BB47D871C51DE6E00AE6A10 /* CustomRulesTests.swift in Sources */,
|
3BB47D871C51DE6E00AE6A10 /* CustomRulesTests.swift in Sources */,
|
||||||
E812249A1B04F85B001783D2 /* TestHelpers.swift in Sources */,
|
E812249A1B04F85B001783D2 /* TestHelpers.swift in Sources */,
|
||||||
|
@ -2135,6 +2186,7 @@
|
||||||
D4470D5B1EB76F44008A1B2E /* UnusedOptionalBindingRuleTests.swift in Sources */,
|
D4470D5B1EB76F44008A1B2E /* UnusedOptionalBindingRuleTests.swift in Sources */,
|
||||||
787CDE3B208F9C34005F3D2F /* SwitchCaseAlignmentRuleTests.swift in Sources */,
|
787CDE3B208F9C34005F3D2F /* SwitchCaseAlignmentRuleTests.swift in Sources */,
|
||||||
F480DC811F2609AB00099465 /* XCTestCase+BundlePath.swift in Sources */,
|
F480DC811F2609AB00099465 /* XCTestCase+BundlePath.swift in Sources */,
|
||||||
|
D47820C621D8B3ED00F24836 /* ConfigurationTests+Plugins.swift in Sources */,
|
||||||
B89F3BCE1FD5EE0200931E59 /* RequiredEnumCaseRuleTestCase.swift in Sources */,
|
B89F3BCE1FD5EE0200931E59 /* RequiredEnumCaseRuleTestCase.swift in Sources */,
|
||||||
C9802F2F1E0C8AEE008AB27F /* TrailingCommaRuleTests.swift in Sources */,
|
C9802F2F1E0C8AEE008AB27F /* TrailingCommaRuleTests.swift in Sources */,
|
||||||
3B63D46F1E1F09DF0057BE35 /* LineLengthRuleTests.swift in Sources */,
|
3B63D46F1E1F09DF0057BE35 /* LineLengthRuleTests.swift in Sources */,
|
||||||
|
@ -2186,7 +2238,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = D0D1212619E878CC005E4BAA /* Debug.xcconfig */;
|
baseConfigurationReference = D0D1212619E878CC005E4BAA /* Debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||||
SWIFT_VERSION = 4.0;
|
SWIFT_VERSION = 4.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
|
@ -2195,7 +2247,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = D0D1212819E878CC005E4BAA /* Release.xcconfig */;
|
baseConfigurationReference = D0D1212819E878CC005E4BAA /* Release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||||
SWIFT_VERSION = 4.0;
|
SWIFT_VERSION = 4.0;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
|
@ -2272,7 +2324,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = D0D1212719E878CC005E4BAA /* Profile.xcconfig */;
|
baseConfigurationReference = D0D1212719E878CC005E4BAA /* Profile.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||||
SWIFT_VERSION = 4.0;
|
SWIFT_VERSION = 4.0;
|
||||||
};
|
};
|
||||||
name = Profile;
|
name = Profile;
|
||||||
|
@ -2315,7 +2367,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = D0D1212919E878CC005E4BAA /* Test.xcconfig */;
|
baseConfigurationReference = D0D1212919E878CC005E4BAA /* Test.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||||
SWIFT_VERSION = 4.0;
|
SWIFT_VERSION = 4.0;
|
||||||
};
|
};
|
||||||
name = Test;
|
name = Test;
|
||||||
|
|
|
@ -22,4 +22,7 @@
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "group:Carthage/Checkouts/Yams/Yams.xcodeproj">
|
location = "group:Carthage/Checkouts/Yams/Yams.xcodeproj">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Carthage/Checkouts/BlueSocket/BlueSocket.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
</Workspace>
|
</Workspace>
|
||||||
|
|
|
@ -6,9 +6,10 @@ Pod::Spec.new do |s|
|
||||||
s.source = { :git => s.homepage + '.git', :tag => s.version }
|
s.source = { :git => s.homepage + '.git', :tag => s.version }
|
||||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||||
s.author = { 'JP Simard' => 'jp@jpsim.com' }
|
s.author = { 'JP Simard' => 'jp@jpsim.com' }
|
||||||
s.platform = :osx, '10.10'
|
s.platform = :osx, '10.11'
|
||||||
s.source_files = 'Source/SwiftLintFramework/**/*.swift'
|
s.source_files = 'Source/SwiftLintFramework/**/*.swift'
|
||||||
s.pod_target_xcconfig = { 'APPLICATION_EXTENSION_API_ONLY' => 'YES' }
|
s.pod_target_xcconfig = { 'APPLICATION_EXTENSION_API_ONLY' => 'YES' }
|
||||||
s.dependency 'SourceKittenFramework', '~> 0.22'
|
s.dependency 'SourceKittenFramework', '~> 0.22'
|
||||||
s.dependency 'Yams', '~> 1.0'
|
s.dependency 'Yams', '~> 1.0'
|
||||||
|
s.dependency 'BlueSocket', '~> 1.0.43'
|
||||||
end
|
end
|
||||||
|
|
|
@ -168,6 +168,10 @@ extension ConfigurationTests {
|
||||||
("testIndentationFallback", testIndentationFallback),
|
("testIndentationFallback", testIndentationFallback),
|
||||||
("testConfiguresCorrectlyFromDict", testConfiguresCorrectlyFromDict),
|
("testConfiguresCorrectlyFromDict", testConfiguresCorrectlyFromDict),
|
||||||
("testConfigureFallsBackCorrectly", testConfigureFallsBackCorrectly),
|
("testConfigureFallsBackCorrectly", testConfigureFallsBackCorrectly),
|
||||||
|
("testLoadsPlugins", testLoadsPlugins),
|
||||||
|
("testEnableAllRulesConfigurationWithPlugins", testEnableAllRulesConfigurationWithPlugins),
|
||||||
|
("testWhitelistRulesWithPlugins", testWhitelistRulesWithPlugins),
|
||||||
|
("testDisabledRulesWithPlugins", testDisabledRulesWithPlugins),
|
||||||
("testMerge", testMerge),
|
("testMerge", testMerge),
|
||||||
("testLevel0", testLevel0),
|
("testLevel0", testLevel0),
|
||||||
("testLevel1", testLevel1),
|
("testLevel1", testLevel1),
|
||||||
|
@ -1002,6 +1006,18 @@ extension RegionTests {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension RemoteRuleResolverTests {
|
||||||
|
static var allTests: [(String, (RemoteRuleResolverTests) -> () throws -> Void)] = [
|
||||||
|
("testCreatesRemoteRule", testCreatesRemoteRule)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
extension RemoteRuleTests {
|
||||||
|
static var allTests: [(String, (RemoteRuleTests) -> () throws -> Void)] = [
|
||||||
|
("testValidate", testValidate)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
extension ReporterTests {
|
extension ReporterTests {
|
||||||
static var allTests: [(String, (ReporterTests) -> () throws -> Void)] = [
|
static var allTests: [(String, (ReporterTests) -> () throws -> Void)] = [
|
||||||
("testReporterFromString", testReporterFromString),
|
("testReporterFromString", testReporterFromString),
|
||||||
|
@ -1071,6 +1087,12 @@ extension RuleConfigurationTests {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension RuleDescriptionTests {
|
||||||
|
static var allTests: [(String, (RuleDescriptionTests) -> () throws -> Void)] = [
|
||||||
|
("testCodableWithMissingValues", testCodableWithMissingValues)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
extension RuleTests {
|
extension RuleTests {
|
||||||
static var allTests: [(String, (RuleTests) -> () throws -> Void)] = [
|
static var allTests: [(String, (RuleTests) -> () throws -> Void)] = [
|
||||||
("testRuleIsEqualTo", testRuleIsEqualTo),
|
("testRuleIsEqualTo", testRuleIsEqualTo),
|
||||||
|
@ -1518,10 +1540,13 @@ XCTMain([
|
||||||
testCase(RedundantTypeAnnotationRuleTests.allTests),
|
testCase(RedundantTypeAnnotationRuleTests.allTests),
|
||||||
testCase(RedundantVoidReturnRuleTests.allTests),
|
testCase(RedundantVoidReturnRuleTests.allTests),
|
||||||
testCase(RegionTests.allTests),
|
testCase(RegionTests.allTests),
|
||||||
|
testCase(RemoteRuleResolverTests.allTests),
|
||||||
|
testCase(RemoteRuleTests.allTests),
|
||||||
testCase(ReporterTests.allTests),
|
testCase(ReporterTests.allTests),
|
||||||
testCase(RequiredEnumCaseRuleTestCase.allTests),
|
testCase(RequiredEnumCaseRuleTestCase.allTests),
|
||||||
testCase(ReturnArrowWhitespaceRuleTests.allTests),
|
testCase(ReturnArrowWhitespaceRuleTests.allTests),
|
||||||
testCase(RuleConfigurationTests.allTests),
|
testCase(RuleConfigurationTests.allTests),
|
||||||
|
testCase(RuleDescriptionTests.allTests),
|
||||||
testCase(RuleTests.allTests),
|
testCase(RuleTests.allTests),
|
||||||
testCase(RulesTests.allTests),
|
testCase(RulesTests.allTests),
|
||||||
testCase(ShorthandOperatorRuleTests.allTests),
|
testCase(ShorthandOperatorRuleTests.allTests),
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
@testable import SwiftLintFramework
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
extension ConfigurationTests {
|
||||||
|
func testLoadsPlugins() {
|
||||||
|
let configurationJSON = ["plugins": ["path/to/plugin"], "test": 10] as [String: Any]
|
||||||
|
let resolver = ResolverMock()
|
||||||
|
let configuration = Configuration(dict: configurationJSON, remoteRulesResolver: resolver)!
|
||||||
|
|
||||||
|
XCTAssertEqual(configuration.plugins, ["path/to/plugin"])
|
||||||
|
XCTAssertEqual(configuration.remoteRules.map { $0.ruleDescription.identifier }, ["test"])
|
||||||
|
XCTAssertEqual(resolver.executable, "path/to/plugin")
|
||||||
|
XCTAssertEqual(resolver.configuration?.bridge(), configurationJSON.bridge())
|
||||||
|
}
|
||||||
|
|
||||||
|
func testEnableAllRulesConfigurationWithPlugins() {
|
||||||
|
let configuration = Configuration(dict: ["plugins": ["path/to/plugin", "path/to/mock"]],
|
||||||
|
ruleList: masterRuleList,
|
||||||
|
enableAllRules: true, cachePath: nil,
|
||||||
|
remoteRulesResolver: ResolverMock())!
|
||||||
|
XCTAssertEqual(configuration.rules.count, masterRuleList.list.count)
|
||||||
|
XCTAssertEqual(configuration.remoteRules.count, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testWhitelistRulesWithPlugins() {
|
||||||
|
let config = Configuration(dict: ["whitelist_rules": ["nesting", "test"],
|
||||||
|
"plugins": ["path/to/plugin",
|
||||||
|
"path/to/mock"]],
|
||||||
|
remoteRulesResolver: ResolverMock())!
|
||||||
|
let configuredIdentifiers = config.rules.map {
|
||||||
|
type(of: $0).description.identifier
|
||||||
|
}.sorted()
|
||||||
|
|
||||||
|
XCTAssertEqual(["nesting"], configuredIdentifiers)
|
||||||
|
XCTAssertEqual(["test"], config.remoteRules.map { $0.ruleDescription.identifier })
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDisabledRulesWithPlugins() {
|
||||||
|
let resolver = ResolverMock()
|
||||||
|
let disabledConfig = Configuration(dict: ["disabled_rules": ["nesting", "test"],
|
||||||
|
"plugins": ["path/to/plugin",
|
||||||
|
"path/to/mock"]],
|
||||||
|
remoteRulesResolver: resolver)!
|
||||||
|
XCTAssertEqual(disabledConfig.disabledRules, ["nesting"])
|
||||||
|
let expectedIdentifiers = Set(masterRuleList.list.keys
|
||||||
|
.filter({ !(["nesting" ] + optInRules).contains($0) }))
|
||||||
|
let configuredIdentifiers = Set(disabledConfig.rules.map {
|
||||||
|
type(of: $0).description.identifier
|
||||||
|
})
|
||||||
|
|
||||||
|
XCTAssertEqual(expectedIdentifiers, configuredIdentifiers)
|
||||||
|
XCTAssertEqual(disabledConfig.remoteRules.identifiers, ["mock"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ResolverMock: RemoteRuleResolverProtocol {
|
||||||
|
private(set) var executable: String?
|
||||||
|
private(set) var configuration: [String: Any]?
|
||||||
|
|
||||||
|
private let identifiers = ["path/to/plugin": "test",
|
||||||
|
"path/to/mock": "mock"]
|
||||||
|
|
||||||
|
func remoteRule(forExecutable executable: String, configuration: [String: Any]?) throws -> RemoteRule {
|
||||||
|
self.executable = executable
|
||||||
|
self.configuration = configuration
|
||||||
|
|
||||||
|
let identifier = identifiers[executable] ?? ""
|
||||||
|
let ruleDescription = RuleDescription(identifier: identifier, name: "Test",
|
||||||
|
description: "", kind: .idiomatic)
|
||||||
|
let pluginDescription = PluginDescription(ruleDescription: ruleDescription)
|
||||||
|
return RemoteRule(description: pluginDescription, configuration: nil)
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,9 +3,9 @@ import SourceKittenFramework
|
||||||
@testable import SwiftLintFramework
|
@testable import SwiftLintFramework
|
||||||
import XCTest
|
import XCTest
|
||||||
|
|
||||||
private let optInRules = masterRuleList.list.filter({ $0.1.init() is OptInRule }).map({ $0.0 })
|
let optInRules = masterRuleList.list.filter({ $0.1.init() is OptInRule }).map({ $0.0 })
|
||||||
|
|
||||||
private extension Configuration {
|
extension Configuration {
|
||||||
var disabledRules: [String] {
|
var disabledRules: [String] {
|
||||||
let configuredRuleIDs = rules.map({ type(of: $0).description.identifier })
|
let configuredRuleIDs = rules.map({ type(of: $0).description.identifier })
|
||||||
let defaultRuleIDs = Set(masterRuleList.list.values.filter({
|
let defaultRuleIDs = Set(masterRuleList.list.values.filter({
|
||||||
|
@ -34,6 +34,8 @@ class ConfigurationTests: XCTestCase {
|
||||||
XCTAssertEqual(config.indentation, .spaces(count: 4))
|
XCTAssertEqual(config.indentation, .spaces(count: 4))
|
||||||
XCTAssertEqual(config.reporter, "xcode")
|
XCTAssertEqual(config.reporter, "xcode")
|
||||||
XCTAssertEqual(reporterFrom(identifier: config.reporter).identifier, "xcode")
|
XCTAssertEqual(reporterFrom(identifier: config.reporter).identifier, "xcode")
|
||||||
|
XCTAssertEqual(config.plugins, [])
|
||||||
|
XCTAssertTrue(config.remoteRules.isEmpty)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testInitWithRelativePathAndRootPath() {
|
func testInitWithRelativePathAndRootPath() {
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
import Foundation
|
||||||
|
import SourceKittenFramework
|
||||||
|
@testable import SwiftLintFramework
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
class RemoteRuleResolverTests: XCTestCase {
|
||||||
|
func testCreatesRemoteRule() throws {
|
||||||
|
let ruleDescription = RuleDescription(identifier: "test", name: "Test", description: "Test", kind: .lint)
|
||||||
|
let pluginDescription = PluginDescription(ruleDescription: ruleDescription, requiredInformation: [.structure])
|
||||||
|
|
||||||
|
let encoder = JSONEncoder()
|
||||||
|
encoder.keyEncodingStrategy = .convertToSnakeCase
|
||||||
|
|
||||||
|
let jsonString = String(decoding: try encoder.encode(pluginDescription), as: UTF8.self)
|
||||||
|
let scriptContent = """
|
||||||
|
#!/bin/bash
|
||||||
|
echo '\(jsonString)'
|
||||||
|
"""
|
||||||
|
let url = URL(fileURLWithPath: NSTemporaryDirectory())
|
||||||
|
.appendingPathComponent(UUID().uuidString)
|
||||||
|
try scriptContent.data(using: .utf8)!.write(to: url)
|
||||||
|
try FileManager.default.setAttributes([.posixPermissions: 0o777], ofItemAtPath: url.path)
|
||||||
|
|
||||||
|
let ruleConfiguration = [
|
||||||
|
"k1": "v1",
|
||||||
|
"k2": 2
|
||||||
|
] as [String: Any]
|
||||||
|
let configuration = [
|
||||||
|
"foo": 20,
|
||||||
|
"test": ruleConfiguration
|
||||||
|
] as [String: Any]
|
||||||
|
|
||||||
|
let resolver = RemoteRuleResolver()
|
||||||
|
let remoteRule = try resolver.remoteRule(forExecutable: url.path,
|
||||||
|
configuration: configuration)
|
||||||
|
|
||||||
|
XCTAssertEqual(remoteRule.ruleDescription.identifier, "test")
|
||||||
|
XCTAssertEqual(remoteRule.description.requiredInformation, [.structure])
|
||||||
|
|
||||||
|
XCTAssertEqual(remoteRule.configuration as? NSDictionary, ruleConfiguration.bridge())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
import Foundation
|
||||||
|
import SourceKittenFramework
|
||||||
|
@testable import SwiftLintFramework
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
class RemoteRuleTests: XCTestCase {
|
||||||
|
func testValidate() {
|
||||||
|
let ruleDescription = RuleDescription(identifier: "test", name: "Test", description: "Test", kind: .lint)
|
||||||
|
let pluginDescription = PluginDescription(ruleDescription: ruleDescription, requiredInformation: [.structure])
|
||||||
|
let configuration = ["key": "value"]
|
||||||
|
let fileContents = "let x = 10"
|
||||||
|
|
||||||
|
let server = RemoteLintServer(socketPath: "/tmp/test.socket")
|
||||||
|
let dispatchGroup = DispatchGroup()
|
||||||
|
|
||||||
|
let delegate = MockRemoteLintServerDelegate()
|
||||||
|
delegate.dispatchGroup = dispatchGroup
|
||||||
|
delegate.violationsToReturn = [
|
||||||
|
StyleViolation(ruleDescription: ruleDescription, severity: .error,
|
||||||
|
location: Location(file: nil, line: 1, character: 4),
|
||||||
|
reason: "Test violation")
|
||||||
|
]
|
||||||
|
|
||||||
|
server.delegate = delegate
|
||||||
|
|
||||||
|
dispatchGroup.enter()
|
||||||
|
server.run()
|
||||||
|
|
||||||
|
// wait until the server has started
|
||||||
|
dispatchGroup.wait()
|
||||||
|
|
||||||
|
let remoteRule = RemoteRule(description: pluginDescription, configuration: configuration)
|
||||||
|
let violations = remoteRule.validate(file: File(contents: fileContents))
|
||||||
|
|
||||||
|
XCTAssertEqual(violations, delegate.violationsToReturn)
|
||||||
|
XCTAssertEqual(delegate.payload?.contents.value, fileContents)
|
||||||
|
XCTAssertNil(delegate.payload!.path)
|
||||||
|
XCTAssertTrue(delegate.payload!.syntaxMap.value.isEmpty)
|
||||||
|
XCTAssertFalse(delegate.payload!.structure.value.isEmpty)
|
||||||
|
XCTAssertEqual(delegate.payload!.configuration as? [String: String], configuration)
|
||||||
|
|
||||||
|
server.shutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MockRemoteLintServerDelegate: RemoteLintServerDelegate {
|
||||||
|
var payload: RemoteRulePayload?
|
||||||
|
var dispatchGroup: DispatchGroup?
|
||||||
|
var violationsToReturn: [StyleViolation] = []
|
||||||
|
|
||||||
|
func server(_ server: RemoteLintServer, didReceivePayload payload: RemoteRulePayload) -> [StyleViolation] {
|
||||||
|
self.payload = payload
|
||||||
|
return violationsToReturn
|
||||||
|
}
|
||||||
|
|
||||||
|
func serverStartedListening(_ server: RemoteLintServer) {
|
||||||
|
dispatchGroup?.leave()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
import Foundation
|
||||||
|
import SwiftLintFramework
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
class RuleDescriptionTests: XCTestCase {
|
||||||
|
func testCodableWithMissingValues() throws {
|
||||||
|
let json = [
|
||||||
|
"identifier": "my_cool_rule",
|
||||||
|
"name": "Cool Rule",
|
||||||
|
"description": "Validates stuff",
|
||||||
|
"kind": "style"
|
||||||
|
]
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||||
|
let data = try JSONSerialization.data(withJSONObject: json)
|
||||||
|
let ruleDescription = try decoder.decode(RuleDescription.self, from: data)
|
||||||
|
|
||||||
|
let expectedDescription = RuleDescription(identifier: "my_cool_rule", name: "Cool Rule",
|
||||||
|
description: "Validates stuff", kind: .style)
|
||||||
|
|
||||||
|
// Comparing field by field because RuleDescription's == only checks the identifier
|
||||||
|
XCTAssertEqual(ruleDescription.identifier, expectedDescription.identifier)
|
||||||
|
XCTAssertEqual(ruleDescription.name, expectedDescription.name)
|
||||||
|
XCTAssertEqual(ruleDescription.description, expectedDescription.description)
|
||||||
|
XCTAssertEqual(ruleDescription.kind, expectedDescription.kind)
|
||||||
|
XCTAssertEqual(ruleDescription.triggeringExamples, expectedDescription.triggeringExamples)
|
||||||
|
XCTAssertEqual(ruleDescription.nonTriggeringExamples, expectedDescription.nonTriggeringExamples)
|
||||||
|
XCTAssertEqual(ruleDescription.corrections, expectedDescription.corrections)
|
||||||
|
XCTAssertEqual(ruleDescription.deprecatedAliases, expectedDescription.deprecatedAliases)
|
||||||
|
XCTAssertEqual(ruleDescription.minSwiftVersion, expectedDescription.minSwiftVersion)
|
||||||
|
XCTAssertEqual(ruleDescription.requiresFileOnDisk, expectedDescription.requiresFileOnDisk)
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,7 +59,7 @@ jobs:
|
||||||
|
|
||||||
linux_swift_4.2:
|
linux_swift_4.2:
|
||||||
docker:
|
docker:
|
||||||
- image: norionomura/swift:42
|
- image: norionomura/swift:421
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run: swift test --parallel
|
- run: swift test --parallel
|
||||||
|
|
Loading…
Reference in New Issue