Compare commits
9 Commits
main
...
jp-reenabl
Author | SHA1 | Date |
---|---|---|
![]() |
da7ef33c38 | |
![]() |
41509fe7f0 | |
![]() |
07861f2caa | |
![]() |
b4854f08f3 | |
![]() |
286c8403f8 | |
![]() |
b50e0ce4b9 | |
![]() |
63c6b602e4 | |
![]() |
48834fb887 | |
![]() |
ab3b57bb0d |
19
CHANGELOG.md
19
CHANGELOG.md
|
@ -11,12 +11,31 @@
|
||||||
[Marcelo Fabri](https://github.com/marcelofabri)
|
[Marcelo Fabri](https://github.com/marcelofabri)
|
||||||
[#1387](https://github.com/realm/SwiftLint/issues/1453)
|
[#1387](https://github.com/realm/SwiftLint/issues/1453)
|
||||||
|
|
||||||
|
* Add `modificationDate(forFileAtPath:)` function requirement to
|
||||||
|
`LintableFileManager` protocol.
|
||||||
|
[Victor Pimentel](https://github.com/victorpimentel)
|
||||||
|
|
||||||
|
* Replace `configurationHash` parameters in all `LinterCache` initializers
|
||||||
|
with `configurationDescription` parameters.
|
||||||
|
[Victor Pimentel](https://github.com/victorpimentel)
|
||||||
|
|
||||||
|
* Remove `fileHash` parameter from `LinterCache.cache(violations:forFile:)`
|
||||||
|
and `LinterCache.violations(forFile:)` functions.
|
||||||
|
[Victor Pimentel](https://github.com/victorpimentel)
|
||||||
|
|
||||||
|
* Remove `hash` attribute from `Configuration` struct.
|
||||||
|
[Victor Pimentel](https://github.com/victorpimentel)
|
||||||
|
|
||||||
* Rename `ConditionalReturnsOnNewline` struct to
|
* Rename `ConditionalReturnsOnNewline` struct to
|
||||||
`ConditionalReturnsOnNewlineRule` to match rule naming conventions.
|
`ConditionalReturnsOnNewlineRule` to match rule naming conventions.
|
||||||
[JP Simard](https://github.com/jpsim)
|
[JP Simard](https://github.com/jpsim)
|
||||||
|
|
||||||
##### Enhancements
|
##### Enhancements
|
||||||
|
|
||||||
|
* Cache linter results for files unmodified since the previous linter run.
|
||||||
|
[Victor Pimentel](https://github.com/victorpimentel)
|
||||||
|
[#1184](https://github.com/realm/SwiftLint/issues/1184)
|
||||||
|
|
||||||
* Add opt-in configurations to `generic_type_name`, `identifier_name` and
|
* Add opt-in configurations to `generic_type_name`, `identifier_name` and
|
||||||
`type_name` rules to allow excluding non-alphanumeric characters and names
|
`type_name` rules to allow excluding non-alphanumeric characters and names
|
||||||
that start with uppercase.
|
that start with uppercase.
|
||||||
|
|
|
@ -10,6 +10,7 @@ import Foundation
|
||||||
|
|
||||||
public protocol LintableFileManager {
|
public protocol LintableFileManager {
|
||||||
func filesToLint(inPath: String, rootDirectory: String?) -> [String]
|
func filesToLint(inPath: String, rootDirectory: String?) -> [String]
|
||||||
|
func modificationDate(forFileAtPath: String) -> Date?
|
||||||
}
|
}
|
||||||
|
|
||||||
extension FileManager: LintableFileManager {
|
extension FileManager: LintableFileManager {
|
||||||
|
@ -31,4 +32,8 @@ extension FileManager: LintableFileManager {
|
||||||
return nil
|
return nil
|
||||||
} ?? []
|
} ?? []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func modificationDate(forFileAtPath path: String) -> Date? {
|
||||||
|
return (try? attributesOfItem(atPath: path))?[.modificationDate] as? Date
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import SourceKittenFramework
|
import SourceKittenFramework
|
||||||
|
|
||||||
private let fileManager = FileManager.default
|
|
||||||
|
|
||||||
private enum ConfigurationKey: String {
|
private enum ConfigurationKey: String {
|
||||||
case cachePath = "cache_path"
|
case cachePath = "cache_path"
|
||||||
case disabledRules = "disabled_rules"
|
case disabledRules = "disabled_rules"
|
||||||
|
@ -34,9 +32,25 @@ public struct Configuration: Equatable {
|
||||||
public let rules: [Rule]
|
public let rules: [Rule]
|
||||||
public var rootPath: String? // the root path to search for nested configurations
|
public var rootPath: String? // the root path to search for nested configurations
|
||||||
public var configurationPath: String? // if successfully loaded from a path
|
public var configurationPath: String? // if successfully loaded from a path
|
||||||
public var hash: Int?
|
|
||||||
public let cachePath: String?
|
public let cachePath: String?
|
||||||
|
|
||||||
|
public var cacheDescription: String {
|
||||||
|
let cacheRulesDescriptions: [String: Any] = rules.reduce([:]) { accu, element in
|
||||||
|
var accu = accu
|
||||||
|
accu[type(of: element).description.identifier] = element.cacheDescription
|
||||||
|
return accu
|
||||||
|
}
|
||||||
|
let dict: [String: Any] = [
|
||||||
|
"root": rootPath ?? FileManager.default.currentDirectoryPath,
|
||||||
|
"rules": cacheRulesDescriptions
|
||||||
|
]
|
||||||
|
if let jsonData = try? JSONSerialization.data(withJSONObject: dict),
|
||||||
|
let jsonString = String(data: jsonData, encoding: .utf8) {
|
||||||
|
return jsonString
|
||||||
|
}
|
||||||
|
fatalError("Could not serialize configuration for cache")
|
||||||
|
}
|
||||||
|
|
||||||
public init?(disabledRules: [String] = [],
|
public init?(disabledRules: [String] = [],
|
||||||
optInRules: [String] = [],
|
optInRules: [String] = [],
|
||||||
enableAllRules: Bool = false,
|
enableAllRules: Bool = false,
|
||||||
|
@ -176,7 +190,6 @@ public struct Configuration: Equatable {
|
||||||
}
|
}
|
||||||
self.init(dict: dict, enableAllRules: enableAllRules)!
|
self.init(dict: dict, enableAllRules: enableAllRules)!
|
||||||
configurationPath = fullPath
|
configurationPath = fullPath
|
||||||
hash = dict.description.hashValue
|
|
||||||
self.rootPath = rootPath
|
self.rootPath = rootPath
|
||||||
return
|
return
|
||||||
} catch YamlParserError.yamlParsing(let message) {
|
} catch YamlParserError.yamlParsing(let message) {
|
||||||
|
@ -192,7 +205,7 @@ public struct Configuration: Equatable {
|
||||||
optional: !CommandLine.arguments.contains("--config"), quiet: quiet, enableAllRules: enableAllRules)
|
optional: !CommandLine.arguments.contains("--config"), quiet: quiet, enableAllRules: enableAllRules)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func lintablePaths(inPath path: String, fileManager: LintableFileManager = fileManager) -> [String] {
|
public func lintablePaths(inPath path: String, fileManager: LintableFileManager = FileManager.default) -> [String] {
|
||||||
// If path is a Swift file, skip filtering with excluded/included paths
|
// If path is a Swift file, skip filtering with excluded/included paths
|
||||||
if path.bridge().isSwiftFile() && path.isFile {
|
if path.bridge().isSwiftFile() && path.isFile {
|
||||||
return [path]
|
return [path]
|
||||||
|
|
|
@ -85,8 +85,7 @@ public struct Linter {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let cache = cache, let path = file.path {
|
if let cache = cache, let path = file.path {
|
||||||
let hash = file.contents.hash
|
cache.cache(violations: violations, forFile: path)
|
||||||
cache.cache(violations: violations, forFile: path, fileHash: hash)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (deprecatedIdentifier, identifier) in deprecatedToValidIdentifier {
|
for (deprecatedIdentifier, identifier) in deprecatedToValidIdentifier {
|
||||||
|
@ -99,10 +98,7 @@ public struct Linter {
|
||||||
|
|
||||||
private func cachedStyleViolations(benchmark: Bool = false) -> ([StyleViolation], [(id: String, time: Double)])? {
|
private func cachedStyleViolations(benchmark: Bool = false) -> ([StyleViolation], [(id: String, time: Double)])? {
|
||||||
let start: Date! = benchmark ? Date() : nil
|
let start: Date! = benchmark ? Date() : nil
|
||||||
guard let cache = cache,
|
guard let cache = cache, let file = file.path, let cachedViolations = cache.violations(forFile: file) else {
|
||||||
let file = file.path,
|
|
||||||
case let hash = self.file.contents.hash,
|
|
||||||
let cachedViolations = cache.violations(forFile: file, hash: hash) else {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,25 +18,26 @@ public enum LinterCacheError: Error {
|
||||||
public final class LinterCache {
|
public final class LinterCache {
|
||||||
private var cache: [String: Any]
|
private var cache: [String: Any]
|
||||||
private let lock = NSLock()
|
private let lock = NSLock()
|
||||||
|
internal lazy var fileManager: LintableFileManager = FileManager.default
|
||||||
|
|
||||||
public init(currentVersion: Version = .current, configurationHash: Int? = nil) {
|
public init(currentVersion: Version = .current, configurationDescription: String? = nil) {
|
||||||
cache = [
|
cache = [
|
||||||
"version": currentVersion.value,
|
Key.version.rawValue: currentVersion.value,
|
||||||
"files": [:]
|
Key.files.rawValue: [:]
|
||||||
]
|
]
|
||||||
cache["configuration_hash"] = configurationHash
|
cache[Key.configuration.rawValue] = configurationDescription
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(cache: Any, currentVersion: Version = .current, configurationHash: Int? = nil) throws {
|
public init(cache: Any, currentVersion: Version = .current, configurationDescription: String? = nil) throws {
|
||||||
guard let dictionary = cache as? [String: Any] else {
|
guard let dictionary = cache as? [String: Any] else {
|
||||||
throw LinterCacheError.invalidFormat
|
throw LinterCacheError.invalidFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let version = dictionary["version"] as? String, version == currentVersion.value else {
|
guard dictionary[Key.version.rawValue] as? String == currentVersion.value else {
|
||||||
throw LinterCacheError.differentVersion
|
throw LinterCacheError.differentVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
if dictionary["configuration_hash"] as? Int != configurationHash {
|
guard dictionary[Key.configuration.rawValue] as? String == configurationDescription else {
|
||||||
throw LinterCacheError.differentConfiguration
|
throw LinterCacheError.differentConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,32 +45,40 @@ public final class LinterCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(contentsOf url: URL, currentVersion: Version = .current,
|
public convenience init(contentsOf url: URL, currentVersion: Version = .current,
|
||||||
configurationHash: Int? = nil) throws {
|
configurationDescription: String? = nil) throws {
|
||||||
let data = try Data(contentsOf: url)
|
let data = try Data(contentsOf: url)
|
||||||
let json = try JSONSerialization.jsonObject(with: data, options: [])
|
let json = try JSONSerialization.jsonObject(with: data, options: [])
|
||||||
try self.init(cache: json, currentVersion: currentVersion,
|
try self.init(cache: json, currentVersion: currentVersion,
|
||||||
configurationHash: configurationHash)
|
configurationDescription: configurationDescription)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func cache(violations: [StyleViolation], forFile file: String) {
|
||||||
|
guard let lastModification = fileManager.modificationDate(forFileAtPath: file) else {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
public func cache(violations: [StyleViolation], forFile file: String, fileHash: Int) {
|
|
||||||
lock.lock()
|
lock.lock()
|
||||||
var filesCache = (cache["files"] as? [String: Any]) ?? [:]
|
var filesCache = (cache[Key.files.rawValue] as? [String: Any]) ?? [:]
|
||||||
filesCache[file] = [
|
filesCache[file] = [
|
||||||
"violations": violations.map(dictionary(for:)),
|
Key.violations.rawValue: violations.map(dictionary(for:)),
|
||||||
"hash": fileHash
|
Key.lastModification.rawValue: lastModification.timeIntervalSinceReferenceDate
|
||||||
]
|
]
|
||||||
cache["files"] = filesCache
|
cache[Key.files.rawValue] = filesCache
|
||||||
lock.unlock()
|
lock.unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func violations(forFile file: String, hash: Int) -> [StyleViolation]? {
|
public func violations(forFile file: String) -> [StyleViolation]? {
|
||||||
|
guard let lastModification = fileManager.modificationDate(forFileAtPath: file) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
lock.lock()
|
lock.lock()
|
||||||
|
|
||||||
guard let filesCache = cache["files"] as? [String: Any],
|
guard let filesCache = cache[Key.files.rawValue] as? [String: Any],
|
||||||
let entry = filesCache[file] as? [String: Any],
|
let entry = filesCache[file] as? [String: Any],
|
||||||
let cacheHash = entry["hash"] as? Int,
|
let cacheLastModification = entry[Key.lastModification.rawValue] as? TimeInterval,
|
||||||
cacheHash == hash,
|
cacheLastModification == lastModification.timeIntervalSinceReferenceDate,
|
||||||
let violations = entry["violations"] as? [[String: Any]] else {
|
let violations = entry[Key.violations.rawValue] as? [[String: Any]] else {
|
||||||
lock.unlock()
|
lock.unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -87,29 +96,46 @@ public final class LinterCache {
|
||||||
|
|
||||||
private func dictionary(for violation: StyleViolation) -> [String: Any] {
|
private func dictionary(for violation: StyleViolation) -> [String: Any] {
|
||||||
return [
|
return [
|
||||||
"line": violation.location.line ?? NSNull() as Any,
|
Key.line.rawValue: violation.location.line ?? NSNull() as Any,
|
||||||
"character": violation.location.character ?? NSNull() as Any,
|
Key.character.rawValue: violation.location.character ?? NSNull() as Any,
|
||||||
"severity": violation.severity.rawValue,
|
Key.severity.rawValue: violation.severity.rawValue,
|
||||||
"type": violation.ruleDescription.name,
|
Key.type.rawValue: violation.ruleDescription.name,
|
||||||
"rule_id": violation.ruleDescription.identifier,
|
Key.ruleID.rawValue: violation.ruleDescription.identifier,
|
||||||
"reason": violation.reason
|
Key.reason.rawValue: violation.reason
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension LinterCache {
|
||||||
|
fileprivate enum Key: String {
|
||||||
|
case character
|
||||||
|
case configuration
|
||||||
|
case files
|
||||||
|
case lastModification = "last_modification"
|
||||||
|
case line
|
||||||
|
case reason
|
||||||
|
case ruleID = "rule_id"
|
||||||
|
case severity
|
||||||
|
case type
|
||||||
|
case version
|
||||||
|
case violations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension StyleViolation {
|
extension StyleViolation {
|
||||||
fileprivate static func from(cache: [String: Any], file: String) -> StyleViolation? {
|
fileprivate static func from(cache: [String: Any], file: String) -> StyleViolation? {
|
||||||
guard let severity = (cache["severity"] as? String).flatMap({ ViolationSeverity(rawValue: $0) }),
|
guard let severityString = (cache[LinterCache.Key.severity.rawValue] as? String),
|
||||||
let name = cache["type"] as? String,
|
let severity = ViolationSeverity(rawValue: severityString),
|
||||||
let ruleId = cache["rule_id"] as? String,
|
let name = cache[LinterCache.Key.type.rawValue] as? String,
|
||||||
let reason = cache["reason"] as? String else {
|
let ruleID = cache[LinterCache.Key.ruleID.rawValue] as? String,
|
||||||
|
let reason = cache[LinterCache.Key.reason.rawValue] as? String else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
let line = cache["line"] as? Int
|
let line = cache[LinterCache.Key.line.rawValue] as? Int
|
||||||
let character = cache["character"] as? Int
|
let character = cache[LinterCache.Key.character.rawValue] as? Int
|
||||||
|
|
||||||
let ruleDescription = RuleDescription(identifier: ruleId, name: name, description: reason)
|
let ruleDescription = RuleDescription(identifier: ruleID, name: name, description: reason)
|
||||||
let location = Location(file: file, line: line, character: character)
|
let location = Location(file: file, line: line, character: character)
|
||||||
let violation = StyleViolation(ruleDescription: ruleDescription, severity: severity,
|
let violation = StyleViolation(ruleDescription: ruleDescription, severity: severity,
|
||||||
location: location, reason: reason)
|
location: location, reason: reason)
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
//
|
||||||
|
// CacheDescriptionProvider.swift
|
||||||
|
// SwiftLint
|
||||||
|
//
|
||||||
|
// Created by JP Simard on 5/16/17.
|
||||||
|
// Copyright © 2017 Realm. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
internal protocol CacheDescriptionProvider {
|
||||||
|
var cacheDescription: String { get }
|
||||||
|
}
|
|
@ -21,6 +21,10 @@ extension Rule {
|
||||||
public func isEqualTo(_ rule: Rule) -> Bool {
|
public func isEqualTo(_ rule: Rule) -> Bool {
|
||||||
return type(of: self).description == type(of: rule).description
|
return type(of: self).description == type(of: rule).description
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal var cacheDescription: String {
|
||||||
|
return (self as? CacheDescriptionProvider)?.cacheDescription ?? configurationDescription
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol OptInRule: Rule {}
|
public protocol OptInRule: Rule {}
|
||||||
|
|
|
@ -6,14 +6,18 @@
|
||||||
// Copyright © 2016 Realm. All rights reserved.
|
// Copyright © 2016 Realm. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
public protocol RuleConfiguration {
|
public protocol RuleConfiguration {
|
||||||
mutating func apply(configuration: Any) throws
|
mutating func apply(configuration: Any) throws
|
||||||
func isEqualTo(_ ruleConfiguration: RuleConfiguration) -> Bool
|
func isEqualTo(_ ruleConfiguration: RuleConfiguration) -> Bool
|
||||||
var consoleDescription: String { get }
|
var consoleDescription: String { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension RuleConfiguration {
|
||||||
|
internal var cacheDescription: String {
|
||||||
|
return (self as? CacheDescriptionProvider)?.cacheDescription ?? consoleDescription
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension RuleConfiguration where Self: Equatable {
|
extension RuleConfiguration where Self: Equatable {
|
||||||
public func isEqualTo(_ ruleConfiguration: RuleConfiguration) -> Bool {
|
public func isEqualTo(_ ruleConfiguration: RuleConfiguration) -> Bool {
|
||||||
return self == ruleConfiguration as? Self
|
return self == ruleConfiguration as? Self
|
||||||
|
|
|
@ -17,8 +17,11 @@ private extension Region {
|
||||||
|
|
||||||
// MARK: - CustomRulesConfiguration
|
// MARK: - CustomRulesConfiguration
|
||||||
|
|
||||||
public struct CustomRulesConfiguration: RuleConfiguration, Equatable {
|
public struct CustomRulesConfiguration: RuleConfiguration, Equatable, CacheDescriptionProvider {
|
||||||
public var consoleDescription: String { return "user-defined" }
|
public var consoleDescription: String { return "user-defined" }
|
||||||
|
internal var cacheDescription: String {
|
||||||
|
return customRuleConfigurations.map({ $0.cacheDescription }).joined(separator: "\n")
|
||||||
|
}
|
||||||
public var customRuleConfigurations = [RegexConfiguration]()
|
public var customRuleConfigurations = [RegexConfiguration]()
|
||||||
|
|
||||||
public init() {}
|
public init() {}
|
||||||
|
@ -42,7 +45,11 @@ public func == (lhs: CustomRulesConfiguration, rhs: CustomRulesConfiguration) ->
|
||||||
|
|
||||||
// MARK: - CustomRules
|
// MARK: - CustomRules
|
||||||
|
|
||||||
public struct CustomRules: Rule, ConfigurationProviderRule {
|
public struct CustomRules: Rule, ConfigurationProviderRule, CacheDescriptionProvider {
|
||||||
|
|
||||||
|
internal var cacheDescription: String {
|
||||||
|
return configuration.cacheDescription
|
||||||
|
}
|
||||||
|
|
||||||
public static let description = RuleDescription(
|
public static let description = RuleDescription(
|
||||||
identifier: "custom_rules",
|
identifier: "custom_rules",
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import SourceKittenFramework
|
import SourceKittenFramework
|
||||||
|
|
||||||
public struct RegexConfiguration: RuleConfiguration, Equatable {
|
public struct RegexConfiguration: RuleConfiguration, Equatable, CacheDescriptionProvider {
|
||||||
public let identifier: String
|
public let identifier: String
|
||||||
public var name: String?
|
public var name: String?
|
||||||
public var message = "Regex matched."
|
public var message = "Regex matched."
|
||||||
|
@ -27,6 +27,23 @@ public struct RegexConfiguration: RuleConfiguration, Equatable {
|
||||||
return "\(severity.rawValue): \(regex.pattern)"
|
return "\(severity.rawValue): \(regex.pattern)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal var cacheDescription: String {
|
||||||
|
var dict = [String: Any]()
|
||||||
|
dict["identifier"] = identifier
|
||||||
|
dict["name"] = name
|
||||||
|
dict["message"] = message
|
||||||
|
dict["regex"] = regex.pattern
|
||||||
|
dict["included"] = included?.pattern
|
||||||
|
dict["excluded"] = excluded?.pattern
|
||||||
|
dict["match_kinds"] = matchKinds.map { $0.rawValue }
|
||||||
|
dict["severity"] = severityConfiguration.consoleDescription
|
||||||
|
if let jsonData = try? JSONSerialization.data(withJSONObject: dict),
|
||||||
|
let jsonString = String(data: jsonData, encoding: .utf8) {
|
||||||
|
return jsonString
|
||||||
|
}
|
||||||
|
fatalError("Could not serialize regex configuration for cache")
|
||||||
|
}
|
||||||
|
|
||||||
public var description: RuleDescription {
|
public var description: RuleDescription {
|
||||||
return RuleDescription(identifier: identifier, name: name ?? identifier, description: "")
|
return RuleDescription(identifier: identifier, name: name ?? identifier, description: "")
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,7 @@ struct LintOptions: OptionsProtocol {
|
||||||
// swiftlint:disable line_length
|
// swiftlint:disable line_length
|
||||||
static func create(_ path: String) -> (_ useSTDIN: Bool) -> (_ configurationFile: String) -> (_ strict: Bool) -> (_ lenient: Bool) -> (_ useScriptInputFiles: Bool) -> (_ benchmark: Bool) -> (_ reporter: String) -> (_ quiet: Bool) -> (_ cachePath: String) -> (_ ignoreCache: Bool) -> (_ enableAllRules: Bool) -> LintOptions {
|
static func create(_ path: String) -> (_ useSTDIN: Bool) -> (_ configurationFile: String) -> (_ strict: Bool) -> (_ lenient: Bool) -> (_ useScriptInputFiles: Bool) -> (_ benchmark: Bool) -> (_ reporter: String) -> (_ quiet: Bool) -> (_ cachePath: String) -> (_ ignoreCache: Bool) -> (_ enableAllRules: Bool) -> LintOptions {
|
||||||
return { useSTDIN in { configurationFile in { strict in { lenient in { useScriptInputFiles in { benchmark in { reporter in { quiet in { cachePath in { ignoreCache in { enableAllRules in
|
return { useSTDIN in { configurationFile in { strict in { lenient in { useScriptInputFiles in { benchmark in { reporter in { quiet in { cachePath in { ignoreCache in { enableAllRules in
|
||||||
self.init(path: path, useSTDIN: useSTDIN, configurationFile: configurationFile, strict: strict, lenient: lenient, useScriptInputFiles: useScriptInputFiles, benchmark: benchmark, reporter: reporter, quiet: quiet, cachePath: cachePath, ignoreCache: true, enableAllRules: enableAllRules)
|
self.init(path: path, useSTDIN: useSTDIN, configurationFile: configurationFile, strict: strict, lenient: lenient, useScriptInputFiles: useScriptInputFiles, benchmark: benchmark, reporter: reporter, quiet: quiet, cachePath: cachePath, ignoreCache: ignoreCache, enableAllRules: enableAllRules)
|
||||||
}}}}}}}}}}}
|
}}}}}}}}}}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,12 @@ extension LinterCache {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
let configurationHash = configuration.hash
|
let configurationDescription = configuration.cacheDescription
|
||||||
let cache: LinterCache
|
let cache: LinterCache
|
||||||
do {
|
do {
|
||||||
cache = try LinterCache(contentsOf: url, configurationHash: configurationHash)
|
cache = try LinterCache(contentsOf: url, configurationDescription: configurationDescription)
|
||||||
} catch {
|
} catch {
|
||||||
cache = LinterCache(configurationHash: configurationHash)
|
cache = LinterCache(configurationDescription: configurationDescription)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cache
|
return cache
|
||||||
|
@ -50,7 +50,7 @@ private func defaultCacheURL(options: LintOptions) -> URL {
|
||||||
#if os(Linux)
|
#if os(Linux)
|
||||||
let baseURL = URL(fileURLWithPath: "/var/tmp/")
|
let baseURL = URL(fileURLWithPath: "/var/tmp/")
|
||||||
#else
|
#else
|
||||||
let baseURL = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0]
|
let baseURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
let fileName = String(rootPath.hash) + ".json"
|
let fileName = String(rootPath.hash) + ".json"
|
||||||
|
|
|
@ -120,8 +120,8 @@
|
||||||
D44254201DB87CA200492EA4 /* ValidIBInspectableRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D442541E1DB87C3D00492EA4 /* ValidIBInspectableRule.swift */; };
|
D44254201DB87CA200492EA4 /* ValidIBInspectableRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D442541E1DB87C3D00492EA4 /* ValidIBInspectableRule.swift */; };
|
||||||
D44254271DB9C15C00492EA4 /* SyntacticSugarRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44254251DB9C12300492EA4 /* SyntacticSugarRule.swift */; };
|
D44254271DB9C15C00492EA4 /* SyntacticSugarRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44254251DB9C12300492EA4 /* SyntacticSugarRule.swift */; };
|
||||||
D4470D571EB69225008A1B2E /* ImplicitReturnRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4470D561EB69225008A1B2E /* ImplicitReturnRule.swift */; };
|
D4470D571EB69225008A1B2E /* ImplicitReturnRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4470D561EB69225008A1B2E /* ImplicitReturnRule.swift */; };
|
||||||
D4470D5B1EB76F44008A1B2E /* UnusedOptionalBindingRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4470D5A1EB76F44008A1B2E /* UnusedOptionalBindingRuleTests.swift */; };
|
|
||||||
D4470D591EB6B4D1008A1B2E /* EmptyEnumArgumentsRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4470D581EB6B4D1008A1B2E /* EmptyEnumArgumentsRule.swift */; };
|
D4470D591EB6B4D1008A1B2E /* EmptyEnumArgumentsRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4470D581EB6B4D1008A1B2E /* EmptyEnumArgumentsRule.swift */; };
|
||||||
|
D4470D5B1EB76F44008A1B2E /* UnusedOptionalBindingRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4470D5A1EB76F44008A1B2E /* UnusedOptionalBindingRuleTests.swift */; };
|
||||||
D44AD2761C0AA5350048F7B0 /* LegacyConstructorRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44AD2741C0AA3730048F7B0 /* LegacyConstructorRule.swift */; };
|
D44AD2761C0AA5350048F7B0 /* LegacyConstructorRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44AD2741C0AA3730048F7B0 /* LegacyConstructorRule.swift */; };
|
||||||
D462021F1E15F52D0027AAD1 /* NumberSeparatorRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = D462021E1E15F52D0027AAD1 /* NumberSeparatorRuleExamples.swift */; };
|
D462021F1E15F52D0027AAD1 /* NumberSeparatorRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = D462021E1E15F52D0027AAD1 /* NumberSeparatorRuleExamples.swift */; };
|
||||||
D46252541DF63FB200BE2CA1 /* NumberSeparatorRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D46252531DF63FB200BE2CA1 /* NumberSeparatorRule.swift */; };
|
D46252541DF63FB200BE2CA1 /* NumberSeparatorRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D46252531DF63FB200BE2CA1 /* NumberSeparatorRule.swift */; };
|
||||||
|
@ -170,6 +170,7 @@
|
||||||
E315B83C1DFA4BC500621B44 /* DynamicInlineRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E315B83B1DFA4BC500621B44 /* DynamicInlineRule.swift */; };
|
E315B83C1DFA4BC500621B44 /* DynamicInlineRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E315B83B1DFA4BC500621B44 /* DynamicInlineRule.swift */; };
|
||||||
E57B23C11B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E57B23C01B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift */; };
|
E57B23C11B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E57B23C01B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift */; };
|
||||||
E802ED001C56A56000A35AE1 /* Benchmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = E802ECFF1C56A56000A35AE1 /* Benchmark.swift */; };
|
E802ED001C56A56000A35AE1 /* Benchmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = E802ECFF1C56A56000A35AE1 /* Benchmark.swift */; };
|
||||||
|
E80746F61ECB722F00548D31 /* CacheDescriptionProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E80746F51ECB722F00548D31 /* CacheDescriptionProvider.swift */; };
|
||||||
E809EDA11B8A71DF00399043 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E809EDA01B8A71DF00399043 /* Configuration.swift */; };
|
E809EDA11B8A71DF00399043 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E809EDA01B8A71DF00399043 /* Configuration.swift */; };
|
||||||
E809EDA31B8A73FB00399043 /* ConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E809EDA21B8A73FB00399043 /* ConfigurationTests.swift */; };
|
E809EDA31B8A73FB00399043 /* ConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E809EDA21B8A73FB00399043 /* ConfigurationTests.swift */; };
|
||||||
E80E018D1B92C0F60078EB70 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = E80E018C1B92C0F60078EB70 /* Command.swift */; };
|
E80E018D1B92C0F60078EB70 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = E80E018C1B92C0F60078EB70 /* Command.swift */; };
|
||||||
|
@ -409,8 +410,8 @@
|
||||||
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>"; };
|
||||||
D44254251DB9C12300492EA4 /* SyntacticSugarRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyntacticSugarRule.swift; sourceTree = "<group>"; };
|
D44254251DB9C12300492EA4 /* SyntacticSugarRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyntacticSugarRule.swift; sourceTree = "<group>"; };
|
||||||
D4470D561EB69225008A1B2E /* ImplicitReturnRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImplicitReturnRule.swift; sourceTree = "<group>"; };
|
D4470D561EB69225008A1B2E /* ImplicitReturnRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImplicitReturnRule.swift; sourceTree = "<group>"; };
|
||||||
D4470D5A1EB76F44008A1B2E /* UnusedOptionalBindingRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnusedOptionalBindingRuleTests.swift; sourceTree = "<group>"; };
|
|
||||||
D4470D581EB6B4D1008A1B2E /* EmptyEnumArgumentsRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyEnumArgumentsRule.swift; sourceTree = "<group>"; };
|
D4470D581EB6B4D1008A1B2E /* EmptyEnumArgumentsRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyEnumArgumentsRule.swift; sourceTree = "<group>"; };
|
||||||
|
D4470D5A1EB76F44008A1B2E /* UnusedOptionalBindingRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnusedOptionalBindingRuleTests.swift; sourceTree = "<group>"; };
|
||||||
D44AD2741C0AA3730048F7B0 /* LegacyConstructorRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacyConstructorRule.swift; sourceTree = "<group>"; };
|
D44AD2741C0AA3730048F7B0 /* LegacyConstructorRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacyConstructorRule.swift; sourceTree = "<group>"; };
|
||||||
D462021E1E15F52D0027AAD1 /* NumberSeparatorRuleExamples.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberSeparatorRuleExamples.swift; sourceTree = "<group>"; };
|
D462021E1E15F52D0027AAD1 /* NumberSeparatorRuleExamples.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberSeparatorRuleExamples.swift; sourceTree = "<group>"; };
|
||||||
D46252531DF63FB200BE2CA1 /* NumberSeparatorRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberSeparatorRule.swift; sourceTree = "<group>"; };
|
D46252531DF63FB200BE2CA1 /* NumberSeparatorRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberSeparatorRule.swift; sourceTree = "<group>"; };
|
||||||
|
@ -460,6 +461,7 @@
|
||||||
E57B23C01B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReturnArrowWhitespaceRule.swift; sourceTree = "<group>"; };
|
E57B23C01B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReturnArrowWhitespaceRule.swift; sourceTree = "<group>"; };
|
||||||
E5A167C81B25A0B000CF2D03 /* OperatorFunctionWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorFunctionWhitespaceRule.swift; sourceTree = "<group>"; };
|
E5A167C81B25A0B000CF2D03 /* OperatorFunctionWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorFunctionWhitespaceRule.swift; sourceTree = "<group>"; };
|
||||||
E802ECFF1C56A56000A35AE1 /* Benchmark.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Benchmark.swift; sourceTree = "<group>"; };
|
E802ECFF1C56A56000A35AE1 /* Benchmark.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Benchmark.swift; sourceTree = "<group>"; };
|
||||||
|
E80746F51ECB722F00548D31 /* CacheDescriptionProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CacheDescriptionProvider.swift; sourceTree = "<group>"; };
|
||||||
E809EDA01B8A71DF00399043 /* Configuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
|
E809EDA01B8A71DF00399043 /* Configuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
|
||||||
E809EDA21B8A73FB00399043 /* ConfigurationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurationTests.swift; sourceTree = "<group>"; };
|
E809EDA21B8A73FB00399043 /* ConfigurationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurationTests.swift; sourceTree = "<group>"; };
|
||||||
E80E018C1B92C0F60078EB70 /* Command.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = "<group>"; };
|
E80E018C1B92C0F60078EB70 /* Command.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = "<group>"; };
|
||||||
|
@ -935,6 +937,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E88DEA8B1B0999A000A66CB0 /* ASTRule.swift */,
|
E88DEA8B1B0999A000A66CB0 /* ASTRule.swift */,
|
||||||
|
E80746F51ECB722F00548D31 /* CacheDescriptionProvider.swift */,
|
||||||
E86396C11BADAAE5002C9E88 /* Reporter.swift */,
|
E86396C11BADAAE5002C9E88 /* Reporter.swift */,
|
||||||
E88DEA761B098D0C00A66CB0 /* Rule.swift */,
|
E88DEA761B098D0C00A66CB0 /* Rule.swift */,
|
||||||
3B828E521C546468000D180E /* RuleConfiguration.swift */,
|
3B828E521C546468000D180E /* RuleConfiguration.swift */,
|
||||||
|
@ -1330,6 +1333,7 @@
|
||||||
F22314B01D4FA4D7009AD165 /* LegacyNSGeometryFunctionsRule.swift in Sources */,
|
F22314B01D4FA4D7009AD165 /* LegacyNSGeometryFunctionsRule.swift in Sources */,
|
||||||
E88DEA8C1B0999A000A66CB0 /* ASTRule.swift in Sources */,
|
E88DEA8C1B0999A000A66CB0 /* ASTRule.swift in Sources */,
|
||||||
1E82D5591D7775C7009553D7 /* ClosureSpacingRule.swift in Sources */,
|
1E82D5591D7775C7009553D7 /* ClosureSpacingRule.swift in Sources */,
|
||||||
|
E80746F61ECB722F00548D31 /* CacheDescriptionProvider.swift in Sources */,
|
||||||
094385041D5D4F7C009168CF /* PrivateOutletRule.swift in Sources */,
|
094385041D5D4F7C009168CF /* PrivateOutletRule.swift in Sources */,
|
||||||
E88DEA6B1B0983FE00A66CB0 /* StyleViolation.swift in Sources */,
|
E88DEA6B1B0983FE00A66CB0 /* StyleViolation.swift in Sources */,
|
||||||
3BB47D831C514E8100AE6A10 /* RegexConfiguration.swift in Sources */,
|
3BB47D831C514E8100AE6A10 /* RegexConfiguration.swift in Sources */,
|
||||||
|
|
|
@ -131,6 +131,10 @@ class ConfigurationTests: XCTestCase {
|
||||||
XCTFail("Should not be called with path \(path)")
|
XCTFail("Should not be called with path \(path)")
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func modificationDate(forFileAtPath path: String) -> Date? {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testExcludedPaths() {
|
func testExcludedPaths() {
|
||||||
|
|
|
@ -12,6 +12,20 @@ import XCTest
|
||||||
|
|
||||||
class LinterCacheTests: XCTestCase {
|
class LinterCacheTests: XCTestCase {
|
||||||
|
|
||||||
|
private class TestFileManager: LintableFileManager {
|
||||||
|
func filesToLint(inPath: String, rootDirectory: String? = nil) -> [String] {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
internal var stubbedModificationDateByPath: [String: Date] = [:]
|
||||||
|
|
||||||
|
public func modificationDate(forFileAtPath path: String) -> Date? {
|
||||||
|
return stubbedModificationDateByPath[path]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private let fileManager = TestFileManager()
|
||||||
|
|
||||||
func testInitThrowsWhenUsingDifferentVersion() {
|
func testInitThrowsWhenUsingDifferentVersion() {
|
||||||
let cache = ["version": "0.1.0"]
|
let cache = ["version": "0.1.0"]
|
||||||
checkError(LinterCacheError.differentVersion) {
|
checkError(LinterCacheError.differentVersion) {
|
||||||
|
@ -27,10 +41,10 @@ class LinterCacheTests: XCTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testInitThrowsWhenUsingDifferentConfiguration() {
|
func testInitThrowsWhenUsingDifferentConfiguration() {
|
||||||
let cache = ["version": "0.1.0", "configuration_hash": 1] as [String : Any]
|
let cache = ["version": "0.1.0", "configuration": "Configuration 1"] as [String : Any]
|
||||||
checkError(LinterCacheError.differentConfiguration) {
|
checkError(LinterCacheError.differentConfiguration) {
|
||||||
_ = try LinterCache(cache: cache, currentVersion: Version(value: "0.1.0"),
|
_ = try LinterCache(cache: cache, currentVersion: Version(value: "0.1.0"),
|
||||||
configurationHash: 2)
|
configurationDescription: "Configuration 2")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,15 +54,16 @@ class LinterCacheTests: XCTestCase {
|
||||||
XCTAssertNotNil(linterCache)
|
XCTAssertNotNil(linterCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testInitSucceedsWithConfigurationHash() {
|
func testInitSucceedsWithConfiguration() {
|
||||||
let cache = ["version": "0.2.0", "configuration_hash": 1] as [String : Any]
|
let cache = ["version": "0.2.0", "configuration": "Configuration 1"] as [String : Any]
|
||||||
let linterCache = try? LinterCache(cache: cache, currentVersion: Version(value: "0.2.0"),
|
let linterCache = try? LinterCache(cache: cache, currentVersion: Version(value: "0.2.0"),
|
||||||
configurationHash: 1)
|
configurationDescription: "Configuration 1")
|
||||||
XCTAssertNotNil(linterCache)
|
XCTAssertNotNil(linterCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testParsesViolations() {
|
func testParsesViolations() {
|
||||||
let cache = LinterCache(currentVersion: Version(value: "0.2.0"))
|
let cache = LinterCache(currentVersion: Version(value: "0.2.0"))
|
||||||
|
cache.fileManager = fileManager
|
||||||
let file = "foo.swift"
|
let file = "foo.swift"
|
||||||
let ruleDescription = RuleDescription(identifier: "rule", name: "Some rule",
|
let ruleDescription = RuleDescription(identifier: "rule", name: "Some rule",
|
||||||
description: "Validates stuff")
|
description: "Validates stuff")
|
||||||
|
@ -62,27 +77,72 @@ class LinterCacheTests: XCTestCase {
|
||||||
location: Location(file: file, line: 5, character: nil),
|
location: Location(file: file, line: 5, character: nil),
|
||||||
reason: "Something is wrong.")
|
reason: "Something is wrong.")
|
||||||
]
|
]
|
||||||
|
fileManager.stubbedModificationDateByPath[file] = Date()
|
||||||
|
|
||||||
cache.cache(violations: violations, forFile: file, fileHash: 1)
|
cache.cache(violations: violations, forFile: file)
|
||||||
let cachedViolations = cache.violations(forFile: file, hash: 1)
|
let cachedViolations = cache.violations(forFile: file)
|
||||||
|
|
||||||
XCTAssertNotNil(cachedViolations)
|
XCTAssertNotNil(cachedViolations)
|
||||||
XCTAssertEqual(cachedViolations!, violations)
|
XCTAssertEqual(cachedViolations!, violations)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testParsesViolationsWithModifiedHash() {
|
func testParsesViolationsWithEmptyViolations() {
|
||||||
let cache = LinterCache(currentVersion: Version(value: "0.2.0"))
|
let cache = LinterCache(currentVersion: Version(value: "0.2.0"))
|
||||||
|
cache.fileManager = fileManager
|
||||||
let file = "foo.swift"
|
let file = "foo.swift"
|
||||||
cache.cache(violations: [], forFile: file, fileHash: 1)
|
fileManager.stubbedModificationDateByPath[file] = Date()
|
||||||
let cachedViolations = cache.violations(forFile: file, hash: 2)
|
|
||||||
|
let cachedViolations = cache.violations(forFile: file)
|
||||||
|
|
||||||
XCTAssertNil(cachedViolations)
|
XCTAssertNil(cachedViolations)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testParsesViolationsWithEmptyViolations() {
|
func testParsesViolationsWithNoDate() {
|
||||||
let cache = LinterCache(currentVersion: Version(value: "0.2.0"))
|
let cache = LinterCache(currentVersion: Version(value: "0.2.0"))
|
||||||
|
cache.fileManager = fileManager
|
||||||
let file = "foo.swift"
|
let file = "foo.swift"
|
||||||
let cachedViolations = cache.violations(forFile: file, hash: 2)
|
let ruleDescription = RuleDescription(identifier: "rule", name: "Some rule",
|
||||||
|
description: "Validates stuff")
|
||||||
|
let violations = [
|
||||||
|
StyleViolation(ruleDescription: ruleDescription,
|
||||||
|
severity: .warning,
|
||||||
|
location: Location(file: file, line: 10, character: 2),
|
||||||
|
reason: "Something is not right."),
|
||||||
|
StyleViolation(ruleDescription: ruleDescription,
|
||||||
|
severity: .error,
|
||||||
|
location: Location(file: file, line: 5, character: nil),
|
||||||
|
reason: "Something is wrong.")
|
||||||
|
]
|
||||||
|
fileManager.stubbedModificationDateByPath[file] = Date()
|
||||||
|
|
||||||
|
cache.cache(violations: violations, forFile: file)
|
||||||
|
fileManager.stubbedModificationDateByPath[file] = nil
|
||||||
|
let cachedViolations = cache.violations(forFile: file)
|
||||||
|
|
||||||
|
XCTAssertNil(cachedViolations)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testParsesViolationsWithDifferentDate() {
|
||||||
|
let cache = LinterCache(currentVersion: Version(value: "0.2.0"))
|
||||||
|
cache.fileManager = fileManager
|
||||||
|
let file = "foo.swift"
|
||||||
|
let ruleDescription = RuleDescription(identifier: "rule", name: "Some rule",
|
||||||
|
description: "Validates stuff")
|
||||||
|
let violations = [
|
||||||
|
StyleViolation(ruleDescription: ruleDescription,
|
||||||
|
severity: .warning,
|
||||||
|
location: Location(file: file, line: 10, character: 2),
|
||||||
|
reason: "Something is not right."),
|
||||||
|
StyleViolation(ruleDescription: ruleDescription,
|
||||||
|
severity: .error,
|
||||||
|
location: Location(file: file, line: 5, character: nil),
|
||||||
|
reason: "Something is wrong.")
|
||||||
|
]
|
||||||
|
fileManager.stubbedModificationDateByPath[file] = Date()
|
||||||
|
|
||||||
|
cache.cache(violations: violations, forFile: file)
|
||||||
|
fileManager.stubbedModificationDateByPath[file] = Date()
|
||||||
|
let cachedViolations = cache.violations(forFile: file)
|
||||||
|
|
||||||
XCTAssertNil(cachedViolations)
|
XCTAssertNil(cachedViolations)
|
||||||
}
|
}
|
||||||
|
@ -95,10 +155,11 @@ extension LinterCacheTests {
|
||||||
("testInitThrowsWhenUsingInvalidCacheFormat", testInitThrowsWhenUsingInvalidCacheFormat),
|
("testInitThrowsWhenUsingInvalidCacheFormat", testInitThrowsWhenUsingInvalidCacheFormat),
|
||||||
("testInitThrowsWhenUsingDifferentConfiguration", testInitThrowsWhenUsingDifferentConfiguration),
|
("testInitThrowsWhenUsingDifferentConfiguration", testInitThrowsWhenUsingDifferentConfiguration),
|
||||||
("testInitSucceeds", testInitSucceeds),
|
("testInitSucceeds", testInitSucceeds),
|
||||||
("testInitSucceedsWithConfigurationHash", testInitSucceedsWithConfigurationHash),
|
("testInitSucceedsWithConfiguration", testInitSucceedsWithConfiguration),
|
||||||
("testParsesViolations", testParsesViolations),
|
("testParsesViolations", testParsesViolations),
|
||||||
("testParsesViolationsWithModifiedHash", testParsesViolationsWithModifiedHash),
|
("testParsesViolationsWithEmptyViolations", testParsesViolationsWithEmptyViolations),
|
||||||
("testParsesViolationsWithEmptyViolations", testParsesViolationsWithEmptyViolations)
|
("testParsesViolationsWithNoDate", testParsesViolationsWithNoDate),
|
||||||
|
("testParsesViolationsWithDifferentDate", testParsesViolationsWithDifferentDate)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue