Skip to content

Commit

Permalink
Add tests for RuleConfigurationMacros (#5256)
Browse files Browse the repository at this point in the history
  • Loading branch information
SimplyDanny authored Oct 3, 2023
1 parent 5d95b0a commit 4716f59
Show file tree
Hide file tree
Showing 3 changed files with 234 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Source/SwiftLintCoreMacros/RuleConfigurationMacros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import SwiftSyntaxMacros
private let configurationElementName = "ConfigurationElement"
private let acceptableByConfigurationElementName = "AcceptableByConfigurationElement"

private enum RuleConfigurationMacroError: String, DiagnosticMessage {
enum RuleConfigurationMacroError: String, DiagnosticMessage {
case notStruct = "Attribute can only be applied to structs"
case notEnum = "Attribute can only be applied to enums"
case noStringRawType = "Attribute can only be applied to enums with a 'String' raw type"
Expand Down
131 changes: 131 additions & 0 deletions Tests/MacroTests/AutoApplyTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
@testable import SwiftLintCoreMacros
import SwiftSyntaxMacrosTestSupport
import XCTest

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

final class AutoApplyTests: XCTestCase {
func testAttachToClass() {
assertMacroExpansion(
"""
@AutoApply
class C {
}
""",
expandedSource:
"""
class C {
}
""",
diagnostics: [
DiagnosticSpec(message: RuleConfigurationMacroError.notStruct.message, line: 1, column: 1)
],
macros: macros)
}

func testNoConfigurationElements() {
assertMacroExpansion(
"""
@AutoApply
struct S {
}
""",
expandedSource:
"""
struct S {
mutating func apply(configuration: Any) throws {
guard let _ = configuration as? [String: Any] else {
throw Issue.invalidConfiguration(ruleID: Parent.description.identifier)
}
if !supportedKeys.isSuperset(of: configuration.keys) {
let unknownKeys = Set(configuration.keys).subtracting(supportedKeys)
throw Issue.invalidConfigurationKeys(unknownKeys.sorted())
}
}
}
""",
macros: macros
)
}

func testConfigurationElementsWithoutKeys() {
assertMacroExpansion(
"""
@AutoApply
struct S {
@ConfigurationElement
var e1 = 1
@ConfigurationElement(value: 7)
var e2 = 2
}
""",
expandedSource:
"""
struct S {
@ConfigurationElement
var e1 = 1
@ConfigurationElement(value: 7)
var e2 = 2
mutating func apply(configuration: Any) throws {
try e1.apply(configuration, ruleID: Parent.identifier)
try e2.apply(configuration, ruleID: Parent.identifier)
guard let _ = configuration as? [String: Any] else {
return
}
if !supportedKeys.isSuperset(of: configuration.keys) {
let unknownKeys = Set(configuration.keys).subtracting(supportedKeys)
throw Issue.invalidConfigurationKeys(unknownKeys.sorted())
}
}
}
""",
macros: macros
)
}

func testConfigurationElementsWithKeys() {
assertMacroExpansion(
"""
@AutoApply
struct S {
@ConfigurationElement(key: "e1")
var e1 = 1
@ConfigurationElement(key: "e2", other: 7)
var e2 = 2
}
""",
expandedSource:
"""
struct S {
@ConfigurationElement(key: "e1")
var e1 = 1
@ConfigurationElement(key: "e2", other: 7)
var e2 = 2
mutating func apply(configuration: Any) throws {
guard let configuration = configuration as? [String: Any] else {
throw Issue.invalidConfiguration(ruleID: Parent.description.identifier)
}
try e1.apply(configuration[$e1.key], ruleID: Parent.identifier)
try $e1.performAfterParseOperations()
try e2.apply(configuration[$e2.key], ruleID: Parent.identifier)
try $e2.performAfterParseOperations()
if !supportedKeys.isSuperset(of: configuration.keys) {
let unknownKeys = Set(configuration.keys).subtracting(supportedKeys)
throw Issue.invalidConfigurationKeys(unknownKeys.sorted())
}
}
}
""",
macros: macros
)
}
}
102 changes: 102 additions & 0 deletions Tests/MacroTests/MakeAcceptableByConfigurationElementTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
@testable import SwiftLintCoreMacros
import SwiftSyntaxMacrosTestSupport
import XCTest

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

// swiftlint:disable:next type_name
final class MakeAcceptableByConfigurationElementTests: XCTestCase {
func testNoEnum() {
assertMacroExpansion(
"""
@MakeAcceptableByConfigurationElement
struct S {
}
""",
expandedSource:
"""
struct S {
}
""",
diagnostics: [
DiagnosticSpec(message: RuleConfigurationMacroError.notEnum.message, line: 1, column: 1)
],
macros: macros)
}

func testNoStringRawType() {
assertMacroExpansion(
"""
@MakeAcceptableByConfigurationElement
enum E {
}
""",
expandedSource:
"""
enum E {
}
""",
diagnostics: [
DiagnosticSpec(message: RuleConfigurationMacroError.noStringRawType.message, line: 1, column: 1)
],
macros: macros)
}

func testPrivateEnum() {
assertMacroExpansion(
"""
@MakeAcceptableByConfigurationElement
private enum E: String {
}
""",
expandedSource:
"""
private enum E: String {
}
extension E: AcceptableByConfigurationElement {
private func asOption() -> OptionType {
.symbol(rawValue)
}
private init(fromAny value: Any, context ruleID: String) throws {
if let value = value as? String, let newSelf = Self (rawValue: value) {
self = newSelf
} else {
throw Issue.unknownConfiguration(ruleID: ruleID)
}
}
}
""",
macros: macros)
}

func testPublicEnum() {
assertMacroExpansion(
"""
@MakeAcceptableByConfigurationElement
public enum E: String {
}
""",
expandedSource:
"""
public enum E: String {
}
extension E: AcceptableByConfigurationElement {
public func asOption() -> OptionType {
.symbol(rawValue)
}
public init(fromAny value: Any, context ruleID: String) throws {
if let value = value as? String, let newSelf = Self (rawValue: value) {
self = newSelf
} else {
throw Issue.unknownConfiguration(ruleID: ruleID)
}
}
}
""",
macros: macros)
}
}

0 comments on commit 4716f59

Please sign in to comment.