Files
SwiftLint/Source/SwiftLintFramework/Protocols/Rule.swift
T
JP Simard 2bcea4b04d Add ability for SwiftLint to lint files with full type-checked AST awareness (#2379)
* Add LintableFilesVisitor

* Move LintCommand logic into LintOrAnalyzeCommand

to prepare for the upcoming analyze command

* Add AnalyzeCommand (not fully implemented yet in SwiftLintFramework)

* Add analyzerRules configuration member

* Add AnalyzerRule protocol

* Pass compiler arguments to validate/correct

* Add requiresFileOnDisk member to RuleDescription

This will be used by AnalyzerRules because they need a file on disk
to pass in the compiler arguments to SourceKit.

* Exclusively run AnalyzerRules when the Linter has compiler arguments

* Enable testing AnalyzerRules in TestHelpers

* Add ExplicitSelfRule

* Update documentation

* Fix `analyze --autocorrect`

* Improve performance of CompilerArgumentsExtractor

* Fix lint command actually running analyze

* Move File operations in TestHelpers into a private extension

* Add analyzer column to rules command and markdown documentation

* Use a Set literal

* Make AnalyzerRule inherit from OptInRule

* Mention analyzer_rules in readme

* Mention that analyzer rules are slow
2018-09-02 00:13:27 -07:00

92 lines
2.6 KiB
Swift

import SourceKittenFramework
public protocol Rule {
static var description: RuleDescription { get }
var configurationDescription: String { get }
init() // Rules need to be able to be initialized with default values
init(configuration: Any) throws
func validate(file: File, compilerArguments: [String]) -> [StyleViolation]
func validate(file: File) -> [StyleViolation]
func isEqualTo(_ rule: Rule) -> Bool
}
extension Rule {
public func validate(file: File, compilerArguments: [String]) -> [StyleViolation] {
return validate(file: file)
}
public func isEqualTo(_ rule: Rule) -> Bool {
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 AutomaticTestableRule: Rule {}
public protocol ConfigurationProviderRule: Rule {
associatedtype ConfigurationType: RuleConfiguration
var configuration: ConfigurationType { get set }
}
public protocol CorrectableRule: Rule {
func correct(file: File, compilerArguments: [String]) -> [Correction]
func correct(file: File) -> [Correction]
}
public extension CorrectableRule {
func correct(file: File, compilerArguments: [String]) -> [Correction] {
return correct(file: file)
}
}
public protocol SourceKitFreeRule: Rule {}
public protocol AnalyzerRule: OptInRule {}
public extension AnalyzerRule {
func validate(file: File) -> [StyleViolation] {
queuedFatalError("Must call `validate(file:compilerArguments:)` for AnalyzerRule")
}
}
public extension AnalyzerRule where Self: CorrectableRule {
func correct(file: File) -> [Correction] {
queuedFatalError("Must call `correct(file:compilerArguments:)` for AnalyzerRule")
}
}
// MARK: - ConfigurationProviderRule conformance to Configurable
public extension ConfigurationProviderRule {
init(configuration: Any) throws {
self.init()
try self.configuration.apply(configuration: configuration)
}
func isEqualTo(_ rule: Rule) -> Bool {
if let rule = rule as? Self {
return configuration.isEqualTo(rule.configuration)
}
return false
}
var configurationDescription: String {
return configuration.consoleDescription
}
}
// MARK: - == Implementations
public func == (lhs: [Rule], rhs: [Rule]) -> Bool {
if lhs.count != rhs.count { return false }
return !zip(lhs, rhs).contains { !$0.0.isEqualTo($0.1) }
}