Skip to content

Commit

Permalink
Configure expression folding by argument of @SwiftSyntaxRule macro (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
SimplyDanny authored Oct 3, 2023
1 parent 4716f59 commit f6e5f77
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 91 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import SwiftSyntax

@Fold
@SwiftSyntaxRule
@SwiftSyntaxRule(foldExpressions: true)
struct LegacyMultipleRule: OptInRule, ConfigurationProviderRule {
var configuration = SeverityConfiguration<Self>(.warning)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import SwiftSyntax

@Fold
@SwiftSyntaxRule
@SwiftSyntaxRule(foldExpressions: true)
struct IdenticalOperandsRule: ConfigurationProviderRule, OptInRule {
var configuration = SeverityConfiguration<Self>(.warning)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import SwiftSyntax

@Fold
@SwiftSyntaxRule
@SwiftSyntaxRule(foldExpressions: true)
struct ContainsOverFirstNotNilRule: OptInRule, ConfigurationProviderRule {
var configuration = SeverityConfiguration<Self>(.warning)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import SwiftSyntax

@Fold
@SwiftSyntaxRule
@SwiftSyntaxRule(foldExpressions: true)
struct ContainsOverRangeNilComparisonRule: OptInRule, ConfigurationProviderRule {
var configuration = SeverityConfiguration<Self>(.warning)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import SwiftSyntax

@Fold
struct EmptyCountRule: ConfigurationProviderRule, OptInRule, SwiftSyntaxRule {
var configuration = EmptyCountConfiguration()

Expand Down Expand Up @@ -37,6 +36,10 @@ struct EmptyCountRule: ConfigurationProviderRule, OptInRule, SwiftSyntaxRule {
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
Visitor(onlyAfterDot: configuration.onlyAfterDot)
}

func preprocess(file: SwiftLintFile) -> SourceFileSyntax? {
file.foldedSyntaxTree
}
}

private extension EmptyCountRule {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import SwiftSyntax

@Fold
@SwiftSyntaxRule
@SwiftSyntaxRule(foldExpressions: true)
struct ShorthandOperatorRule: ConfigurationProviderRule {
var configuration = SeverityConfiguration<Self>(.error)

Expand Down
14 changes: 4 additions & 10 deletions Source/SwiftLintCore/Helpers/Macros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,10 @@ public macro MakeAcceptableByConfigurationElement() = #externalMacro(
)

/// Macro that adds a conformance to the `SwiftSyntaxRule` protocol and a default `makeVisitor(file:)` implementation
/// that creates a visitor defined in the same file.
@attached(extension, conformances: SwiftSyntaxRule, names: named(makeVisitor(file:)))
public macro SwiftSyntaxRule() = #externalMacro(
/// that creates a visitor defined in the same file. It also adds an implementation of `preprocess(file:)` which folds
/// expressions if the `foldExpressions` argument is set.
@attached(extension, conformances: SwiftSyntaxRule, names: named(makeVisitor(file:)), named(preprocess(file:)))
public macro SwiftSyntaxRule(foldExpressions: Bool = false) = #externalMacro(
module: "SwiftLintCoreMacros",
type: "SwiftSyntaxRule"
)

/// Macro that preprocesses the file by folding its operators before processing it for rule violations.
@attached(extension, names: named(preprocess(file:)))
public macro Fold() = #externalMacro(
module: "SwiftLintCoreMacros",
type: "Fold"
)
22 changes: 0 additions & 22 deletions Source/SwiftLintCoreMacros/Fold.swift

This file was deleted.

1 change: 0 additions & 1 deletion Source/SwiftLintCoreMacros/SwiftLintCoreMacros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import SwiftSyntaxMacros
struct SwiftLintCoreMacros: CompilerPlugin {
let providingMacros: [Macro.Type] = [
AutoApply.self,
Fold.self,
MakeAcceptableByConfigurationElement.self,
SwiftSyntaxRule.self
]
Expand Down
34 changes: 34 additions & 0 deletions Source/SwiftLintCoreMacros/SwiftSyntaxRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,42 @@ struct SwiftSyntaxRule: ExtensionMacro {
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
Visitor(viewMode: .sourceAccurate)
}
\(createFoldingPreprocessor(from: node.foldArgument))
}
""")
]
}

private static func createFoldingPreprocessor(from foldArgument: ExprSyntax?) -> DeclSyntax {
guard let foldArgument else {
return ""
}
if let booleanLiteral = foldArgument.as(BooleanLiteralExprSyntax.self)?.literal {
if booleanLiteral.text == "true" {
return """
func preprocess(file: SwiftLintFile) -> SourceFileSyntax? {
file.foldedSyntaxTree
}
"""
}
if booleanLiteral.text == "false" {
return ""
}
}
return """
func preprocess(file: SwiftLintFile) -> SourceFileSyntax? {
if \(foldArgument) { file.foldedSyntaxTree } else { nil }
}
"""
}
}

private extension AttributeSyntax {
var foldArgument: ExprSyntax? {
if case let .argumentList(args) = arguments, let first = args.first, first.label?.text == "foldExpressions" {
first.expression
} else {
nil
}
}
}
47 changes: 0 additions & 47 deletions Tests/MacroTests/MacroTests.swift

This file was deleted.

97 changes: 97 additions & 0 deletions Tests/MacroTests/SwiftSyntaxRuleTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
@testable import SwiftLintCoreMacros
import SwiftSyntaxMacrosTestSupport
import XCTest

private let macros = [
"SwiftSyntaxRule": SwiftSyntaxRule.self
]

final class SwiftSyntaxRuleTests: XCTestCase {
func testNoFoldArgument() {
assertMacroExpansion(
"""
@SwiftSyntaxRule
struct Hello {}
""",
expandedSource: """
struct Hello {}
extension Hello: SwiftSyntaxRule {
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
Visitor(viewMode: .sourceAccurate)
}
}
""",
macros: macros
)
}

func testFalseFoldArgument() {
assertMacroExpansion(
"""
@SwiftSyntaxRule(foldExpressions: false)
struct Hello {}
""",
expandedSource: """
struct Hello {}
extension Hello: SwiftSyntaxRule {
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
Visitor(viewMode: .sourceAccurate)
}
}
""",
macros: macros
)
}

func testTrueFoldArgument() {
assertMacroExpansion(
"""
@SwiftSyntaxRule(foldExpressions: true)
struct Hello {}
""",
expandedSource: """
struct Hello {}
extension Hello: SwiftSyntaxRule {
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
Visitor(viewMode: .sourceAccurate)
}
func preprocess(file: SwiftLintFile) -> SourceFileSyntax? {
file.foldedSyntaxTree
}
}
""",
macros: macros
)
}

func testArbitraryFoldArgument() {
assertMacroExpansion(
"""
@SwiftSyntaxRule(foldExpressions: variable)
struct Hello {}
""",
expandedSource: """
struct Hello {}
extension Hello: SwiftSyntaxRule {
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
Visitor(viewMode: .sourceAccurate)
}
func preprocess(file: SwiftLintFile) -> SourceFileSyntax? {
if variable {
file.foldedSyntaxTree
} else {
nil
}
}
}
""",
macros: macros
)
}
}

0 comments on commit f6e5f77

Please sign in to comment.