Files
SwiftLint/Source/SwiftLintFramework/Protocols/ASTRule.swift
T
JP Simard 5a30991fa4 Add SwiftSyntax rule helpers (#4126)
This cuts down on the boilerplate involved in writing SwiftSyntax-based
rules. May not be significant right now since most rules are still built
with SourceKit, but as we migrate more rules moving forward, this should
make it easier for rule authors to write rules that behave performantly
and correctly.
2022-08-26 14:46:32 +00:00

65 lines
2.6 KiB
Swift

import SourceKittenFramework
/// A rule that leverages the Swift source's pre-typechecked Abstract Syntax Tree to recurse into the source's
/// structure, validating the rule recursively in nested source bodies.
public protocol ASTRule: Rule {
/// The kind of token being recursed over.
associatedtype KindType: RawRepresentable
/// Executes the rule on a file and a subset of its AST structure, returning any violations to the rule's
/// expectations.
///
/// - parameter file: The file for which to execute the rule.
/// - parameter kind: The kind of token being recursed over.
/// - parameter dictionary: The dictionary for an AST subset to validate.
///
/// - returns: All style violations to the rule's expectations.
func validate(file: SwiftLintFile, kind: KindType, dictionary: SourceKittenDictionary) -> [StyleViolation]
/// Get the `kind` from the specified dictionary.
///
/// - parameter dictionary: The `SourceKittenDictionary` representing the source structure from which to extract the
/// `kind`.
///
/// - returns: The `kind` from the specified dictionary, if one was found.
func kind(from dictionary: SourceKittenDictionary) -> KindType?
}
public extension ASTRule {
func validate(file: SwiftLintFile) -> [StyleViolation] {
return validate(file: file, dictionary: file.structureDictionary)
}
/// Executes the rule on a file and a subset of its AST structure, returning any violations to the rule's
/// expectations.
///
/// - parameter file: The file for which to execute the rule.
/// - parameter dictionary: The dictionary for an AST subset to validate.
///
/// - returns: All style violations to the rule's expectations.
func validate(file: SwiftLintFile, dictionary: SourceKittenDictionary) -> [StyleViolation] {
return dictionary.traverseDepthFirst { subDict in
guard let kind = self.kind(from: subDict) else { return nil }
return validate(file: file, kind: kind, dictionary: subDict)
}
}
}
public extension ASTRule where KindType == SwiftDeclarationKind {
func kind(from dictionary: SourceKittenDictionary) -> KindType? {
return dictionary.declarationKind
}
}
public extension ASTRule where KindType == SwiftExpressionKind {
func kind(from dictionary: SourceKittenDictionary) -> KindType? {
return dictionary.expressionKind
}
}
public extension ASTRule where KindType == StatementKind {
func kind(from dictionary: SourceKittenDictionary) -> KindType? {
return dictionary.statementKind
}
}