mirror of
https://github.com/realm/SwiftLint.git
synced 2026-05-07 20:12:49 +00:00
82 lines
2.8 KiB
Swift
82 lines
2.8 KiB
Swift
import SwiftSyntax
|
|
import SwiftSyntaxBuilder
|
|
import SwiftSyntaxMacros
|
|
|
|
enum SwiftSyntaxRule: ExtensionMacro {
|
|
static func expansion(
|
|
of node: AttributeSyntax,
|
|
attachedTo _: some DeclGroupSyntax,
|
|
providingExtensionsOf type: some TypeSyntaxProtocol,
|
|
conformingTo _: [TypeSyntax],
|
|
in context: some MacroExpansionContext
|
|
) throws -> [ExtensionDeclSyntax] {
|
|
[
|
|
try ExtensionDeclSyntax("""
|
|
extension \(type): SwiftSyntaxRule {
|
|
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor<ConfigurationType> {
|
|
Visitor(configuration: configuration, file: file)
|
|
}
|
|
}
|
|
"""
|
|
),
|
|
try node.foldArgument(context).ifTrue(
|
|
try ExtensionDeclSyntax("""
|
|
extension \(type) {
|
|
func preprocess(file: SwiftLintFile) -> SourceFileSyntax? {
|
|
file.foldedSyntaxTree
|
|
}
|
|
}
|
|
"""
|
|
)
|
|
),
|
|
try node.explicitRewriterArgument(context).ifTrue(
|
|
try ExtensionDeclSyntax("""
|
|
extension \(type): SwiftSyntaxCorrectableRule {
|
|
func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter<ConfigurationType>? {
|
|
Rewriter(configuration: configuration, file: file)
|
|
}
|
|
}
|
|
"""
|
|
)
|
|
),
|
|
].compactMap { $0 }
|
|
}
|
|
}
|
|
|
|
private extension AttributeSyntax {
|
|
func foldArgument(_ context: some MacroExpansionContext) -> Bool {
|
|
findArgument(withName: "foldExpressions", in: context)
|
|
}
|
|
|
|
func explicitRewriterArgument(_ context: some MacroExpansionContext) -> Bool {
|
|
findArgument(withName: "explicitRewriter", in: context)
|
|
}
|
|
|
|
private func findArgument(withName name: String, in context: some MacroExpansionContext) -> Bool {
|
|
if case let .argumentList(args) = arguments, let first = args.first(where: { $0.label?.text == name }) {
|
|
let expr = first.expression
|
|
if expr.isBooleanLiteral {
|
|
return expr.isTrueLiteral
|
|
}
|
|
context.diagnose(SwiftLintCoreMacroError.noBooleanLiteral.diagnose(at: expr))
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
|
|
private extension ExprSyntax {
|
|
var isBooleanLiteral: Bool {
|
|
`is`(BooleanLiteralExprSyntax.self)
|
|
}
|
|
|
|
var isTrueLiteral: Bool {
|
|
`as`(BooleanLiteralExprSyntax.self)?.literal.text == "true"
|
|
}
|
|
}
|
|
|
|
private extension Bool {
|
|
func ifTrue<P: SyntaxProtocol>(_ result: @autoclosure () throws -> P) rethrows -> P? {
|
|
self ? try result() : nil
|
|
}
|
|
}
|