diff --git a/Package.resolved b/Package.resolved index fc60154..ab933cd 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "c6efe50626096d7a88b43a6407659792896790a0139e87f92ae1600957fb541f", + "originHash" : "3894eea68b27a911eb20a3ced56cc3cb9fb46e91a4969d5e3d9da94d9ae10e21", "pins" : [ { "identity" : "swift-binary-parsing", @@ -19,6 +19,15 @@ "version" : "1.1.6" } }, + { + "identity" : "swift-custom-dump", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-custom-dump", + "state" : { + "revision" : "82645ec760917961cfa08c9c0c7104a57a0fa4b1", + "version" : "1.3.3" + } + }, { "identity" : "swift-docc-plugin", "kind" : "remoteSourceControl", @@ -37,6 +46,24 @@ "version" : "1.0.0" } }, + { + "identity" : "swift-macro-testing", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-macro-testing.git", + "state" : { + "revision" : "9ab11325daa51c7c5c10fcf16c92bac906717c7e", + "version" : "0.6.4" + } + }, + { + "identity" : "swift-snapshot-testing", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-snapshot-testing", + "state" : { + "revision" : "a8b7c5e0ed33d8ab8887d1654d9b59f2cbad529b", + "version" : "1.18.7" + } + }, { "identity" : "swift-syntax", "kind" : "remoteSourceControl", @@ -45,6 +72,15 @@ "revision" : "4799286537280063c85a32f09884cfbca301b1a1", "version" : "602.0.0" } + }, + { + "identity" : "xctest-dynamic-overlay", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", + "state" : { + "revision" : "4c27acf5394b645b70d8ba19dc249c0472d5f618", + "version" : "1.7.0" + } } ], "version" : 3 diff --git a/Package.swift b/Package.swift index ec242ae..d9ba23f 100644 --- a/Package.swift +++ b/Package.swift @@ -26,6 +26,7 @@ let package = Package( .upToNextMinor(from: "1.1.0"), ), .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.4.5"), + .package(url: "https://github.com/pointfreeco/swift-macro-testing.git", from: "0.6.4"), ], targets: [ .macro( @@ -75,6 +76,7 @@ let package = Package( dependencies: [ "BinaryParseKitMacros", .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"), + .product(name: "MacroTesting", package: "swift-macro-testing"), ], ), .testTarget( diff --git a/Sources/BinaryParseKitMacros/Macros/ParseEnum/ParseEnumCase.swift b/Sources/BinaryParseKitMacros/Macros/ParseEnum/ParseEnumCase.swift index 22bc316..ea63973 100644 --- a/Sources/BinaryParseKitMacros/Macros/ParseEnum/ParseEnumCase.swift +++ b/Sources/BinaryParseKitMacros/Macros/ParseEnum/ParseEnumCase.swift @@ -8,11 +8,11 @@ import SwiftDiagnostics import SwiftSyntax import SwiftSyntaxMacros -class ParseEnumCase: SyntaxVisitor { - private let context: C +class ParseEnumCase: SyntaxVisitor { + private let context: any MacroExpansionContext private var workEnum: EnumDeclSyntax? - private var currentParseMacroVisitor: MacroAttributeCollector? + private var currentParseMacroVisitor: MacroAttributeCollector? private var currentCaseElements: EnumCaseElementListSyntax? private var caseParseInfo: [EnumCaseParseInfo] = [] private(set) var parsedInfo: EnumParseInfo? @@ -21,7 +21,7 @@ class ParseEnumCase: SyntaxVisitor { private var errors: [Diagnostic] = [] - init(context: C) { + init(context: any MacroExpansionContext) { self.context = context super.init(viewMode: .sourceAccurate) } diff --git a/Sources/BinaryParseKitMacros/Macros/ParseStruct/ParseStructField.swift b/Sources/BinaryParseKitMacros/Macros/ParseStruct/ParseStructField.swift index fecdaad..94b8baa 100644 --- a/Sources/BinaryParseKitMacros/Macros/ParseStruct/ParseStructField.swift +++ b/Sources/BinaryParseKitMacros/Macros/ParseStruct/ParseStructField.swift @@ -11,7 +11,7 @@ import SwiftSyntax import SwiftSyntaxBuilder import SwiftSyntaxMacros -class ParseStructField: SyntaxVisitor { +class ParseStructField: SyntaxVisitor { struct VariableInfo { let type: TypeSyntax let parseActions: [StructParseAction] @@ -24,17 +24,17 @@ class ParseStructField: SyntaxVisitor { typealias ParseVariableMapping = OrderedDictionary - private let context: C + private let context: any MacroExpansionContext private var hasParse: Bool = false - private var structFieldVisitor: MacroAttributeCollector? + private var structFieldVisitor: MacroAttributeCollector? private var existParseRestContent: Bool = false private(set) var variables: ParseVariableMapping = [:] private(set) var errors: [Diagnostic] = [] - init(context: C) { + init(context: any MacroExpansionContext) { self.context = context super.init(viewMode: .sourceAccurate) } diff --git a/Sources/BinaryParseKitMacros/Macros/Supports/MacroAttributeCollector.swift b/Sources/BinaryParseKitMacros/Macros/Supports/MacroAttributeCollector.swift index c57f9e2..e2e0bd5 100644 --- a/Sources/BinaryParseKitMacros/Macros/Supports/MacroAttributeCollector.swift +++ b/Sources/BinaryParseKitMacros/Macros/Supports/MacroAttributeCollector.swift @@ -9,7 +9,7 @@ import SwiftDiagnostics import SwiftSyntax import SwiftSyntaxMacros -class MacroAttributeCollector: SyntaxVisitor { +class MacroAttributeCollector: SyntaxVisitor { private enum MacroError: Error { case invalidParseAttribute case invalidParseRestAttribute @@ -20,7 +20,7 @@ class MacroAttributeCollector: SyntaxVisitor { typealias ParseAction = StructParseAction typealias CaseMatchAction = EnumCaseMatchAction - private let context: C + private let context: any MacroExpansionContext private(set) var parseActions: [ParseAction] = [] private(set) var hasParseRest: Bool = false private(set) var hasParse: Bool = false @@ -29,7 +29,7 @@ class MacroAttributeCollector: SyntaxVisitor { private var errors: [Diagnostic] = [] - init(context: C) { + init(context: any MacroExpansionContext) { self.context = context super.init(viewMode: .sourceAccurate) } diff --git a/Sources/BinaryParseKitMacros/Macros/Supports/ParseMacroInfo.swift b/Sources/BinaryParseKitMacros/Macros/Supports/ParseMacroInfo.swift index a4bade5..d5edbce 100644 --- a/Sources/BinaryParseKitMacros/Macros/Supports/ParseMacroInfo.swift +++ b/Sources/BinaryParseKitMacros/Macros/Supports/ParseMacroInfo.swift @@ -10,7 +10,7 @@ import SwiftDiagnostics import SwiftSyntax import SwiftSyntaxMacros -private class ParseMacroArgVisitor: SyntaxVisitor { +private class ParseMacroArgVisitor: SyntaxVisitor { var source: Syntax? var byteCountOfArgument: LabeledExprSyntax? var byteCountArgument: LabeledExprSyntax? @@ -18,8 +18,8 @@ private class ParseMacroArgVisitor: SyntaxVisitor { private var errors: [Diagnostic] = [] - private let context: C - init(context: C) { + private let context: any MacroExpansionContext + init(context: any MacroExpansionContext) { self.context = context super.init(viewMode: .sourceAccurate) } diff --git a/Tests/BinaryParseKitMacroTests/BinaryParseKitEnumTests.swift b/Tests/BinaryParseKitMacroTests/BinaryParseKitEnumTests.swift index 281e313..c273e12 100644 --- a/Tests/BinaryParseKitMacroTests/BinaryParseKitEnumTests.swift +++ b/Tests/BinaryParseKitMacroTests/BinaryParseKitEnumTests.swift @@ -5,16 +5,17 @@ // Created by Larry Zeng on 7/26/25. // @testable import BinaryParseKitMacros +import MacroTesting import SwiftSyntaxMacrosGenericTestSupport import Testing -// swiftlint:disable file_length line_length +// swiftlint:disable line_length extension BinaryParseKitMacroTests { - @Suite + @Suite(.macros(testMacros)) struct `Test Parsing Enum` { // swiftlint:disable:this type_name type_body_length @Test func `parse regular enum`() { - assertMacroExpansion( + assertMacro { """ @ParseEnum public enum TestEnum { @@ -24,8 +25,9 @@ extension BinaryParseKitMacroTests { @match(bytes: [0x01, 0x02]) case b } - """, - expandedSource: #""" + """ + } expansion: { + #""" public enum TestEnum { case a case b @@ -67,13 +69,13 @@ extension BinaryParseKitMacroTests { } } } - """#, - ) + """# + } } @Test func `parse RawRepresentable enum by matching bytes`() { - assertMacroExpansion( + assertMacro { """ @ParseEnum enum TestEnum: UInt8 { @@ -83,8 +85,9 @@ extension BinaryParseKitMacroTests { @match(byte: 0x01) case b } - """, - expandedSource: #""" + """ + } expansion: { + #""" enum TestEnum: UInt8 { case a case b @@ -126,14 +129,14 @@ extension BinaryParseKitMacroTests { } } } - """#, - ) + """# + } } /// Test parsing RawRepresentable enum by matching raw value directly @Test func `parse RawRepresentable enum by matching types`() { - assertMacroExpansion( + assertMacro { """ @ParseEnum enum TestEnum: UInt8 { @@ -143,8 +146,9 @@ extension BinaryParseKitMacroTests { @match case b } - """, - expandedSource: #""" + """ + } expansion: { + #""" enum TestEnum: UInt8 { case a case b @@ -186,13 +190,13 @@ extension BinaryParseKitMacroTests { } } } - """#, - ) + """# + } } @Test func `enum with associated value`() { - assertMacroExpansion( + assertMacro { """ @ParseEnum enum TestEnum { @@ -211,8 +215,9 @@ extension BinaryParseKitMacroTests { @parse(endianness: .little) case c(code: UInt8, value: SomeType) } - """, - expandedSource: #""" + """ + } expansion: { + #""" enum TestEnum { case a(SomeType) case b(Int, value: SomeType) @@ -287,13 +292,13 @@ extension BinaryParseKitMacroTests { } } } - """#, - ) + """# + } } @Test func `enum with match and take`() { - assertMacroExpansion( + assertMacro { """ @ParseEnum enum TestEnum { @@ -302,8 +307,9 @@ extension BinaryParseKitMacroTests { @match(bytes: [0x02, 0x03]) case b } - """, - expandedSource: #""" + """ + } expansion: { + #""" enum TestEnum { case a case b @@ -346,13 +352,13 @@ extension BinaryParseKitMacroTests { } } } - """#, - ) + """# + } } @Test func `enum with match default`() { - assertMacroExpansion( + assertMacro { """ @ParseEnum enum TestEnum { @@ -363,8 +369,9 @@ extension BinaryParseKitMacroTests { @matchDefault case c } - """, - expandedSource: #""" + """ + } expansion: { + #""" enum TestEnum { case a case b @@ -420,13 +427,13 @@ extension BinaryParseKitMacroTests { } } } - """#, - ) + """# + } } @Test func `enum with too many parse skip`() { - assertMacroExpansion( + assertMacro { """ @ParseEnum enum TestEnum { @@ -452,109 +459,56 @@ extension BinaryParseKitMacroTests { @parse(byteCount: 4, endianness: .big) case e(Int, Int), f(Int) } - """, - expandedSource: """ + """ + } diagnostics: { + """ + @ParseEnum + ┬───────── + ╰─ 🛑 Unexpected error: Enum macro parsing encountered errors enum TestEnum { + @matchAndTake(byte: 0x01) + @skip(byteCount: 2, because: "reserved") + ┬─────────────────────────────────────── + ╰─ 🛑 There are more parse/skip macros than the number of cases in the enum. + @parse(byteCount: 4, endianness: .big) + ┬───────────────────────────────────── + ╰─ 🛑 There are more parse/skip macros than the number of cases in the enum. case a + @matchAndTake(bytes: [0x02, 0x03]) + @parse(byteCount: 4, endianness: .big) + ┬───────────────────────────────────── + ╰─ 🛑 There are more parse/skip macros than the number of cases in the enum. case b + @matchAndTake(bytes: [0x02, 0x03]) + @parse(byteCount: 4, endianness: .big) + @skip(byteCount: 2, because: "reserved") + ┬─────────────────────────────────────── + ╰─ 🛑 There are more parse/skip macros than the number of cases in the enum. + @parse(byteCount: 4, endianness: .big) + ┬───────────────────────────────────── + ╰─ 🛑 There are more parse/skip macros than the number of cases in the enum. case c(Int) + @matchAndTake(bytes: [0x02, 0x03]) + @skip(byteCount: 2, because: "reserved") + @parse(byteCount: 4, endianness: .big) case d(Int) + @match + @parse(byteCount: 4, endianness: .big) + @skip(byteCount: 2, because: "reserved") + ┬─────────────────────────────────────── + ╰─ 🛑 There are more parse/skip macros than the number of cases in the enum. + @parse(byteCount: 4, endianness: .big) + ┬───────────────────────────────────── + ╰─ 🛑 There are more parse/skip macros than the number of cases in the enum. case e(Int, Int), f(Int) } - """, - diagnostics: [ - .init( - diagnostic: ParseEnumMacroError.macrosMoreThanCaseArguments, - line: 4, - column: 5, - notes: [ - .init( - note: MacrosMoreThanCaseArgumentsNote(enumCase: "a"), - line: 6, - column: 10, - ), - ], - ), - .init( - diagnostic: ParseEnumMacroError.macrosMoreThanCaseArguments, - line: 5, - column: 5, - notes: [ - .init( - note: MacrosMoreThanCaseArgumentsNote(enumCase: "a"), - line: 6, - column: 10, - ), - ], - ), - .init( - diagnostic: ParseEnumMacroError.macrosMoreThanCaseArguments, - line: 8, - column: 5, - notes: [ - .init( - note: MacrosMoreThanCaseArgumentsNote(enumCase: "b"), - line: 9, - column: 10, - ), - ], - ), - .init( - diagnostic: ParseEnumMacroError.macrosMoreThanCaseArguments, - line: 12, - column: 5, - notes: [ - .init( - note: MacrosMoreThanCaseArgumentsNote(enumCase: "c(Int)"), - line: 14, - column: 10, - ), - ], - ), - .init( - diagnostic: ParseEnumMacroError.macrosMoreThanCaseArguments, - line: 13, - column: 5, - notes: [ - .init( - note: MacrosMoreThanCaseArgumentsNote(enumCase: "c(Int)"), - line: 14, - column: 10, - ), - ], - ), - .init( - diagnostic: ParseEnumMacroError.macrosMoreThanCaseArguments, - line: 21, - column: 5, - notes: [ - .init( - note: MacrosMoreThanCaseArgumentsNote(enumCase: "f(Int)"), - line: 23, - column: 23, - ), - ], - ), - .init( - diagnostic: ParseEnumMacroError.macrosMoreThanCaseArguments, - line: 22, - column: 5, - notes: [ - .init( - note: MacrosMoreThanCaseArgumentsNote(enumCase: "f(Int)"), - line: 23, - column: 23, - ), - ], - ), - validationFailedDiagnostic, - ], - ) + """ + } } @Test func `enum with too few parse and skip`() { - assertMacroExpansion( + assertMacro { """ @ParseEnum enum TestEnum { @@ -570,44 +524,40 @@ extension BinaryParseKitMacroTests { @parse case d(Int), e(Int, Int) } - """, - expandedSource: """ + """ + } diagnostics: { + """ + @ParseEnum + ┬───────── + ╰─ 🛑 Unexpected error: Enum macro parsing encountered errors enum TestEnum { + @matchAndTake(byte: 0x01) + @skip(byteCount: 2, because: "reserved") case a(Int) + ┬── + ╰─ 🛑 The associated values in the enum case exceed the number of parse/skip macros. + @matchAndTake(bytes: [0x02, 0x03]) case b(Int) + ┬── + ╰─ 🛑 The associated values in the enum case exceed the number of parse/skip macros. + @match + @parse case c(Int, value: SomeType) + ┬────────────── + ╰─ 🛑 The associated values in the enum case exceed the number of parse/skip macros. + @match + @parse case d(Int), e(Int, Int) + ┬── + ╰─ 🛑 The associated values in the enum case exceed the number of parse/skip macros. } - """, - diagnostics: [ - .init( - diagnostic: ParseEnumMacroError.caseArgumentsMoreThanMacros, - line: 5, - column: 12, - ), - .init( - diagnostic: ParseEnumMacroError.caseArgumentsMoreThanMacros, - line: 7, - column: 12, - ), - .init( - diagnostic: ParseEnumMacroError.caseArgumentsMoreThanMacros, - line: 10, - column: 17, - ), - .init( - diagnostic: ParseEnumMacroError.caseArgumentsMoreThanMacros, - line: 13, - column: 25, - ), - validationFailedDiagnostic, - ], - ) + """ + } } @Test func `enum with match(Default) after matchDefault`() { - assertMacroExpansion( + assertMacro { """ @ParseEnum enum TestEnum { @@ -620,39 +570,32 @@ extension BinaryParseKitMacroTests { @matchDefault case d } - """, - expandedSource: """ + """ + } diagnostics: { + """ + @ParseEnum + ┬───────── + ╰─ 🛑 Unexpected error: Enum macro parsing encountered errors enum TestEnum { + @matchDefault case a + @matchAndTake(byte: 0x01) + ╰─ 🛑 The `matchDefault` case must be the last case in the enum. case b + @match(byte: 0x01) + ╰─ 🛑 The `matchDefault` case must be the last case in the enum. case c + @matchDefault + ╰─ 🛑 Only one `matchDefault` case is allowed in a enum. case d } - """, - diagnostics: [ - .init( - diagnostic: ParseEnumMacroError.defaultCaseMustBeLast, - line: 5, - column: 5, - ), - .init( - diagnostic: ParseEnumMacroError.defaultCaseMustBeLast, - line: 7, - column: 5, - ), - .init( - diagnostic: ParseEnumMacroError.onlyOneMatchDefaultAllowed, - line: 9, - column: 5, - ), - validationFailedDiagnostic, - ], - ) + """ + } } @Test func `enum with parse/skip before match`() { - assertMacroExpansion( + assertMacro { """ @ParseEnum enum TestEnum { @@ -672,60 +615,61 @@ extension BinaryParseKitMacroTests { @parse case c(Int) } - """, - expandedSource: """ + """ + } diagnostics: { + """ + @ParseEnum + ┬───────── + ╰─ 🛑 Unexpected error: Enum macro parsing encountered errors enum TestEnum { + @parse + @match + ┬───── + ╰─ 🛑 The `match` macro must proceed all `parse` and `skip` macro. + @parse case a(Int, Int) + + @skip(byteCount: 1, reason: "not used") + @parse + @matchAndTake(byte: 0x01) + ┬──────────────────────── + ╰─ 🛑 The `match` macro must proceed all `parse` and `skip` macro. + @parse case b(Int, Int) + + @skip(byteCount: 1, reason: "not used") + @match(byte: 0x01) + ┬───────────────── + ╰─ 🛑 The `match` macro must proceed all `parse` and `skip` macro. + @parse case c(Int) } - """, - diagnostics: [ - .init( - diagnostic: ParseEnumMacroError.matchMustProceedParseAndSkip, - line: 4, - column: 5, - ), - .init( - diagnostic: ParseEnumMacroError.matchMustProceedParseAndSkip, - line: 10, - column: 5, - ), - .init( - diagnostic: ParseEnumMacroError.matchMustProceedParseAndSkip, - line: 15, - column: 5, - ), - validationFailedDiagnostic, - ], - ) + """ + } } @Test func `macro ParseEnum not used with enum`() { - assertMacroExpansion( + assertMacro { """ @ParseEnum struct Test { } - """, - expandedSource: """ + """ + } diagnostics: { + """ + @ParseEnum + ┬───────── + ╰─ 🛑 Only enums are supported by this macro. struct Test { } - """, - diagnostics: [ - .init( - diagnostic: ParseEnumMacroError.onlyEnumsAreSupported, - line: 1, - column: 1, - ), - ], - ) + """ + } } @Test func `enum case missing match macro`() { - assertMacroExpansion( + assertMacro { """ @ParseEnum enum TestEnum { @@ -733,143 +677,136 @@ extension BinaryParseKitMacroTests { @match(byte: 0x01) case b } - """, - expandedSource: """ + """ + } diagnostics: { + """ + @ParseEnum + ┬───────── + ╰─ 🛑 Unexpected error: Enum macro parsing encountered errors enum TestEnum { case a + ┬───── + ╰─ 🛑 A `case` declaration must has a `match` macro. + @match(byte: 0x01) case b } - """, - diagnostics: [ - .init( - diagnostic: ParseEnumMacroError.missingCaseMatchMacro, - line: 3, - column: 5, - ), - validationFailedDiagnostic, - ], - ) + """ + } } @Test func `no comments in code generation`() { - assertMacroExpansion(""" - @ParseEnum - enum TestEnum { - @match - @parse - case a( - value: Int // some value - ) - - @match - @parse - case b( - value: // some value - Int // some value - ) - - @match - @parse - @parse - case c( - Int, // some value - value: // some value - Int // some value - ) - } - """, expandedSource: #""" - enum TestEnum { - case a( - value: Int // some value - ) - case b( - value: // some value - Int // some value - ) - case c( - Int, // some value - value: // some value - Int // some value - ) - } + assertMacro { + """ + @ParseEnum + enum TestEnum { + @match + @parse + case a( + value: Int // some value + ) - extension TestEnum: BinaryParseKit.Parsable { - init(parsing span: inout BinaryParsing.ParserSpan) throws(BinaryParsing.ThrownParsingError) { - if BinaryParseKit.__match((TestEnum.a as any BinaryParseKit.Matchable).bytesToMatch(), in: &span) { - // Parse `value` of type Int - BinaryParseKit.__assertParsable((Int).self) - let value = try Int(parsing: &span) - // construct `a` with above associated values - self = .a(value: value) - return - } - if BinaryParseKit.__match((TestEnum.b as any BinaryParseKit.Matchable).bytesToMatch(), in: &span) { - // Parse `value` of type Int - BinaryParseKit.__assertParsable((Int).self) - let value = try Int(parsing: &span) - // construct `b` with above associated values - self = .b(value: value) - return - } - if BinaryParseKit.__match((TestEnum.c as any BinaryParseKit.Matchable).bytesToMatch(), in: &span) { - // Parse `__macro_local_12TestEnum_c_0fMu_` of type Int - BinaryParseKit.__assertParsable((Int).self) - let __macro_local_12TestEnum_c_0fMu_ = try Int(parsing: &span) - // Parse `value` of type Int - BinaryParseKit.__assertParsable((Int).self) - let value = try Int(parsing: &span) - // construct `c` with above associated values - self = .c(__macro_local_12TestEnum_c_0fMu_, value: value) - return + @match + @parse + case b( + value: // some value + Int // some value + ) + + @match + @parse + @parse + case c( + Int, // some value + value: // some value + Int // some value + ) + } + """ + } expansion: { + #""" + enum TestEnum { + case a( + value: Int // some value + ) + case b( + value: // some value + Int // some value + ) + case c( + Int, // some value + value: // some value + Int // some value + ) + } + + extension TestEnum: BinaryParseKit.Parsable { + init(parsing span: inout BinaryParsing.ParserSpan) throws(BinaryParsing.ThrownParsingError) { + if BinaryParseKit.__match((TestEnum.a as any BinaryParseKit.Matchable).bytesToMatch(), in: &span) { + // Parse `value` of type Int + BinaryParseKit.__assertParsable((Int).self) + let value = try Int(parsing: &span) + // construct `a` with above associated values + self = .a(value: value) + return + } + if BinaryParseKit.__match((TestEnum.b as any BinaryParseKit.Matchable).bytesToMatch(), in: &span) { + // Parse `value` of type Int + BinaryParseKit.__assertParsable((Int).self) + let value = try Int(parsing: &span) + // construct `b` with above associated values + self = .b(value: value) + return + } + if BinaryParseKit.__match((TestEnum.c as any BinaryParseKit.Matchable).bytesToMatch(), in: &span) { + // Parse `__macro_local_12TestEnum_c_0fMu_` of type Int + BinaryParseKit.__assertParsable((Int).self) + let __macro_local_12TestEnum_c_0fMu_ = try Int(parsing: &span) + // Parse `value` of type Int + BinaryParseKit.__assertParsable((Int).self) + let value = try Int(parsing: &span) + // construct `c` with above associated values + self = .c(__macro_local_12TestEnum_c_0fMu_, value: value) + return + } + throw BinaryParseKit.BinaryParserKitError.failedToParse("Failed to find a match for TestEnum, at \(span.startPosition)") } - throw BinaryParseKit.BinaryParserKitError.failedToParse("Failed to find a match for TestEnum, at \(span.startPosition)") } - } - extension TestEnum: BinaryParseKit.Printable { - func printerIntel() throws -> PrinterIntel { - switch self { - case let .a(__macro_local_7a_valuefMu_): - return .enum( - .init( - bytes: (TestEnum.a as any BinaryParseKit.Matchable).bytesToMatch(), - parseType: .match, - fields: [.init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(__macro_local_7a_valuefMu_))], + extension TestEnum: BinaryParseKit.Printable { + func printerIntel() throws -> PrinterIntel { + switch self { + case let .a(__macro_local_7a_valuefMu_): + return .enum( + .init( + bytes: (TestEnum.a as any BinaryParseKit.Matchable).bytesToMatch(), + parseType: .match, + fields: [.init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(__macro_local_7a_valuefMu_))], + ) ) - ) - case let .b(__macro_local_7b_valuefMu_): - return .enum( - .init( - bytes: (TestEnum.b as any BinaryParseKit.Matchable).bytesToMatch(), - parseType: .match, - fields: [.init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(__macro_local_7b_valuefMu_))], + case let .b(__macro_local_7b_valuefMu_): + return .enum( + .init( + bytes: (TestEnum.b as any BinaryParseKit.Matchable).bytesToMatch(), + parseType: .match, + fields: [.init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(__macro_local_7b_valuefMu_))], + ) ) - ) - case let .c(__macro_local_9c_index_0fMu_, __macro_local_7c_valuefMu_): - return .enum( - .init( - bytes: (TestEnum.c as any BinaryParseKit.Matchable).bytesToMatch(), - parseType: .match, - fields: [.init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(__macro_local_9c_index_0fMu_)), .init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(__macro_local_7c_valuefMu_))], + case let .c(__macro_local_9c_index_0fMu_, __macro_local_7c_valuefMu_): + return .enum( + .init( + bytes: (TestEnum.c as any BinaryParseKit.Matchable).bytesToMatch(), + parseType: .match, + fields: [.init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(__macro_local_9c_index_0fMu_)), .init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(__macro_local_7c_valuefMu_))], + ) ) - ) + } } } + """# } - """#) } } } -// MARK: - Diagnostics - -private let validationFailedDiagnosticMessage = ParseEnumMacroError - .unexpectedError(description: "Enum macro parsing encountered errors") -private nonisolated(unsafe) let validationFailedDiagnostic = DiagnosticSpec( - diagnostic: validationFailedDiagnosticMessage, - line: 1, - column: 1, -) - -// swiftlint:enable file_length line_length +// swiftlint:enable line_length diff --git a/Tests/BinaryParseKitMacroTests/BinaryParseKitStructTests.swift b/Tests/BinaryParseKitMacroTests/BinaryParseKitStructTests.swift index 71a182e..60765ba 100644 --- a/Tests/BinaryParseKitMacroTests/BinaryParseKitStructTests.swift +++ b/Tests/BinaryParseKitMacroTests/BinaryParseKitStructTests.swift @@ -1,4 +1,5 @@ @testable import BinaryParseKitMacros +import MacroTesting import SwiftSyntax import SwiftSyntaxBuilder import SwiftSyntaxMacroExpansion @@ -9,11 +10,11 @@ import Testing // swiftlint:disable line_length extension BinaryParseKitMacroTests { - @Suite + @Suite(.macros(testMacros)) struct `Test Parsing Struct` { // swiftlint:disable:this type_name type_body_length @Test func successfulParseStructMacroExpansion() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @@ -51,8 +52,9 @@ extension BinaryParseKitMacroTests { set { g = newValue } } } - """#, - expandedSource: """ + """# + } expansion: { + """ public struct Header { let a: Int let b: Int32 @@ -115,113 +117,105 @@ extension BinaryParseKitMacroTests { ) } } - """, - ) + """ + } } @Test func parseStructOnClass() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public class Header { @parse let a: Int } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 @ParseStruct only supports structs. Please use a struct declaration or other macros. public class Header { + @parse let a: Int } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError.onlyStructsAreSupported, - line: 1, - column: 1, - ), - ], - ) + """ + } } @Test func parseStructOnEnum() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public enum Header { case a } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 @ParseStruct only supports structs. Please use a struct declaration or other macros. public enum Header { case a } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError.onlyStructsAreSupported, - line: 1, - column: 1, - ), - ], - ) + """ + } } @Test func variableWithoutTypeAnnotation() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @parse let a = 1 } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @parse let a = 1 + ┬──── + ╰─ 🛑 Variable declarations must have a type annotation to be parsed. } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError.variableDeclNoTypeAnnotation, - line: 4, - column: 9, - ), - parseStructTopError, - ], - ) + """ + } } @Test func variableWithoutParseAttribute() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { let a: Int } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { let a: Int + ┬───── + ╰─ 🛑 The variable declaration must have a `@parse` attribute. } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError.noParseAttributeOnVariableDecl, - line: 3, - column: 9, - ), - parseStructTopError, - ], - ) + """ + } } @Test func multipleParseRestAttributes() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @@ -230,27 +224,27 @@ extension BinaryParseKitMacroTests { @parseRest let b: Data } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @parseRest let a: Data + @parseRest let b: Data + ┬────── + ╰─ 🛑 Multiple or non-trailing `@parseRest` attributes are not allowed. Only one trailing `@parseRest` is permitted. } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError.multipleOrNonTrailingParseRest, - line: 6, - column: 9, - ), - parseStructTopError, - ], - ) + """ + } } @Test func nonTrailingParseRest() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @@ -259,34 +253,43 @@ extension BinaryParseKitMacroTests { @parse let b: Int } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @parseRest let a: Data + @parse let b: Int + ┬───── + ╰─ 🛑 Multiple or non-trailing `@parseRest` attributes are not allowed. Only one trailing `@parseRest` is permitted. } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError.multipleOrNonTrailingParseRest, - line: 6, - column: 9, - ), - parseStructTopError, - ], - ) + """ + } } @Test func emptyStructWithNoParseableFields() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { static let constant = 42 } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ╰─ ⚠️ No variables with `@parse` attribute found in the struct. Ensure at least one variable is marked for parsing. + public struct Header { + static let constant = 42 + } + """ + } expansion: { + """ public struct Header { static let constant = 42 } @@ -305,159 +308,144 @@ extension BinaryParseKitMacroTests { ) } } - """, - diagnostics: [ - noParseVarExist, - ], - ) + """ + } } @Test func invalidVariablePattern() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @parse let (a, b): (Int, Int) } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @parse let (a, b): (Int, Int) + ┬───────────────── + ╰─ 🛑 Variable declaration must be an identifier definition. } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError.notIdentifierDef, - line: 4, - column: 9, - ), - parseStructTopError, - ], - ) + """ + } } @Test func invalidParseAttributeArgument() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @parse(unknownArgument: 42) let a: Int } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @parse(unknownArgument: 42) + ┬────────────────── + │ ╰─ 🛑 Unknown argument in `@parse`: 'unknownArgument'. Please check the attribute syntax. + ┬────────────────────────── + ├─ 🛑 Fatal error: @parse argument validation failed. + ╰─ 🛑 Fatal error: Encountered errors during parsing field. let a: Int } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError.unknownParseArgument("unknownArgument"), - line: 3, - column: 12, - ), - DiagnosticSpec( - diagnostic: ParseStructMacroError.fatalError(message: "@parse argument validation failed."), - line: 3, - column: 5, - ), - specificFieldParsingError(line: 3, column: 5), - parseStructTopError, - ], - ) + """ + } } @Test func conflictingByteCountArguments() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @parse(byteCount: 4, byteCountOf: \Self.someField) let a: Int } - """#, - expandedSource: """ + """# + } diagnostics: { + #""" + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @parse(byteCount: 4, byteCountOf: \Self.someField) + ┬───────────────────────────────────────────────── + ├─ 🛑 Fatal error: Both `byteCountOf` and `byteCount` cannot be specified at the same time. + ╰─ 🛑 Fatal error: Encountered errors during parsing field. let a: Int } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError.fatalError( - message: "Both `byteCountOf` and `byteCount` cannot be specified at the same time.", - ), - line: 3, - column: 5, - ), - specificFieldParsingError(line: 3, column: 5), - parseStructTopError, - ], - ) + """# + } } @Test func invalidByteCountLiteral() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @parse(byteCount: "invalid") let a: Int } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @parse(byteCount: "invalid") + ┬─────────────────────────── + ├─ 🛑 Failed expectation: byteCount should be an integer literal. + ╰─ 🛑 Fatal error: Encountered errors during parsing field. let a: Int } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError - .failedExpectation(message: "byteCount should be an integer literal."), - line: 3, - column: 5, - ), - specificFieldParsingError(line: 3, column: 5), - parseStructTopError, - ], - ) + """ + } } @Test func invalidByteCountOfKeyPath() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @parse(byteCountOf: "notAKeyPath") let a: Int } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @parse(byteCountOf: "notAKeyPath") + ┬───────────────────────────────── + ├─ 🛑 Failed expectation: byteCountOf should be a KeyPath literal expression. + ╰─ 🛑 Fatal error: Encountered errors during parsing field. let a: Int } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError - .failedExpectation(message: "byteCountOf should be a KeyPath literal expression."), - line: 3, - column: 5, - ), - specificFieldParsingError(line: 3, column: 5), - parseStructTopError, - ], - ) + """ + } } @Test func skipWithMissingArguments() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @@ -465,29 +453,27 @@ extension BinaryParseKitMacroTests { @parse let a: Int } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @skip + ┬──── + ├─ 🛑 Failed expectation: Expected a labeled expression list for `@parseSkip` attribute, but found none. + ╰─ 🛑 Fatal error: Encountered errors during parsing field. + @parse let a: Int } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError.failedExpectation( - message: "Expected a labeled expression list for `@parseSkip` attribute, but found none.", - ), - line: 3, - column: 5, - ), - specificFieldParsingError(line: 3, column: 5), - parseStructTopError, - ], - ) + """ + } } @Test func skipWithWrongNumberOfArguments() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @@ -495,29 +481,27 @@ extension BinaryParseKitMacroTests { @parse let a: Int } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @skip(byteCount: 4) + ┬────────────────── + ├─ 🛑 Fatal error: Expected exactly two arguments for `@parseSkip` attribute, but found 1. + ╰─ 🛑 Fatal error: Encountered errors during parsing field. + @parse let a: Int } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError.fatalError( - message: "Expected exactly two arguments for `@parseSkip` attribute, but found 1.", - ), - line: 3, - column: 5, - ), - specificFieldParsingError(line: 3, column: 5), - parseStructTopError, - ], - ) + """ + } } @Test func skipWithInvalidByteCount() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @@ -525,29 +509,27 @@ extension BinaryParseKitMacroTests { @parse let a: Int } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @skip(byteCount: "invalid", reason: "test") + ┬────────────────────────────────────────── + ├─ 🛑 Failed expectation: Expected the first argument of `@parseSkip` to be an integer literal representing byte count. + ╰─ 🛑 Fatal error: Encountered errors during parsing field. + @parse let a: Int } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError.failedExpectation( - message: "Expected the first argument of `@parseSkip` to be an integer literal representing byte count.", - ), - line: 3, - column: 5, - ), - specificFieldParsingError(line: 3, column: 5), - parseStructTopError, - ], - ) + """ + } } @Test func computedPropertyWithParse() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @@ -557,57 +539,53 @@ extension BinaryParseKitMacroTests { set { } } } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @parse var a: Int { + ╰─ 🛑 The variable declaration with accessor(s) (`get` and `set`) cannot be parsed. get { 42 } set { } } } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError.parseAccessorVariableDecl, - line: 4, - column: 9, - ), - parseStructTopError, - ], - ) + """ + } } @Test func byteCountParseConvertInParse() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @parse(byteCount: 0xFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF) var a: Int } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @parse(byteCount: 0xFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF) + ┬──────────────────────────────────────────────────────────────── + ├─ 🛑 Failed expectation: byteCount should be convertible to Int. + ╰─ 🛑 Fatal error: Encountered errors during parsing field. var a: Int } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError - .failedExpectation(message: "byteCount should be convertible to Int."), - line: 3, - column: 5, - ), - specificFieldParsingError(line: 3, column: 5), - parseStructTopError, - ], - ) + """ + } } @Test func byteCountParseConvertInSkip() { - assertMacroExpansion( + assertMacro { #""" @ParseStruct public struct Header { @@ -615,100 +593,81 @@ extension BinaryParseKitMacroTests { @parse var a: Int } - """#, - expandedSource: """ + """# + } diagnostics: { + """ + @ParseStruct + ┬─────────── + ╰─ 🛑 Fatal error: Parsing struct's fields has encountered an error. public struct Header { + @skip(byteCount: 0xFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF, because: "test bad byte count") + ┬─────────────────────────────────────────────────────────────────────────────────────────────── + ├─ 🛑 Failed expectation: byteCount should be convertible to Int. + ╰─ 🛑 Fatal error: Encountered errors during parsing field. + @parse var a: Int } - """, - diagnostics: [ - DiagnosticSpec( - diagnostic: ParseStructMacroError - .failedExpectation(message: "byteCount should be convertible to Int."), - line: 3, - column: 5, - ), - specificFieldParsingError(line: 3, column: 5), - parseStructTopError, - ], - ) + """ + } } @Test func `no comments and spaces in code generation`() { - assertMacroExpansion(""" - @ParseStruct - struct Header { - @parse - var a: Int // some comments - - @parse - var b: // some comments - Int // some comments - - @parse - var // some comments - c: // some comments - Int // some comments - } - """, expandedSource: """ - struct Header { - var a: Int // some comments - var b: // some comments - Int // some comments - var // some comments - c: // some comments - Int // some comments - } + assertMacro { + """ + @ParseStruct + struct Header { + @parse + var a: Int // some comments - extension Header: BinaryParseKit.Parsable { - init(parsing span: inout BinaryParsing.ParserSpan) throws(BinaryParsing.ThrownParsingError) { - // Parse `a` of type Int - BinaryParseKit.__assertParsable((Int).self) - self.a = try Int(parsing: &span) - // Parse `b` of type Int - BinaryParseKit.__assertParsable((Int).self) - self.b = try Int(parsing: &span) - // Parse `c` of type Int - BinaryParseKit.__assertParsable((Int).self) - self.c = try Int(parsing: &span) + @parse + var b: // some comments + Int // some comments + + @parse + var // some comments + c: // some comments + Int // some comments + } + """ + } expansion: { + """ + struct Header { + var a: Int // some comments + var b: // some comments + Int // some comments + var // some comments + c: // some comments + Int // some comments + } + + extension Header: BinaryParseKit.Parsable { + init(parsing span: inout BinaryParsing.ParserSpan) throws(BinaryParsing.ThrownParsingError) { + // Parse `a` of type Int + BinaryParseKit.__assertParsable((Int).self) + self.a = try Int(parsing: &span) + // Parse `b` of type Int + BinaryParseKit.__assertParsable((Int).self) + self.b = try Int(parsing: &span) + // Parse `c` of type Int + BinaryParseKit.__assertParsable((Int).self) + self.c = try Int(parsing: &span) + } } - } - extension Header: BinaryParseKit.Printable { - func printerIntel() throws -> PrinterIntel { - return .struct( - .init( - fields: [.init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(a)), .init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(b)), .init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(c))] + extension Header: BinaryParseKit.Printable { + func printerIntel() throws -> PrinterIntel { + return .struct( + .init( + fields: [.init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(a)), .init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(b)), .init(byteCount: nil, endianness: nil, intel: try BinaryParseKit.__getPrinterIntel(c))] + ) ) - ) + } } + """ } - """) } } } -// MARK: - Diagnostic - -private nonisolated(unsafe) let parseStructTopError = DiagnosticSpec( - diagnostic: ParseStructMacroError.fatalError(message: "Parsing struct's fields has encountered an error."), - line: 1, - column: 1, -) - -private func specificFieldParsingError(line: Int, column: Int) -> DiagnosticSpec { - .init( - diagnostic: ParseStructMacroError.fatalError(message: "Encountered errors during parsing field."), - line: line, - column: column, - ) -} - -private nonisolated(unsafe) let noParseVarExist = DiagnosticSpec( - diagnostic: ParseStructMacroError.emptyParse, - line: 1, - column: 1, -) - // swiftlint:enable line_length diff --git a/Tests/BinaryParseKitMacroTests/Misc.swift b/Tests/BinaryParseKitMacroTests/Misc.swift index 852bb54..7428ca9 100644 --- a/Tests/BinaryParseKitMacroTests/Misc.swift +++ b/Tests/BinaryParseKitMacroTests/Misc.swift @@ -16,7 +16,7 @@ import Testing #if canImport(BinaryParseKitMacros) import BinaryParseKitMacros - private let testMacros: [String: Macro.Type] = [ + let testMacros: [String: Macro.Type] = [ "ParseStruct": ConstructStructParseMacro.self, "parse": EmptyPeerMacro.self, "skip": EmptyPeerMacro.self, @@ -26,52 +26,11 @@ import Testing "matchDefault": EmptyPeerMacro.self, "matchAndTake": EmptyPeerMacro.self, ] - private let testMacroSpec = testMacros.mapValues { MacroSpec(type: $0) } private let shouldRunMacroTest = true #else - private let testMacroSpec = [String: MacroSpec]() + let testMacros: [String: Macro.Type] = [:] private let shouldRunMacroTest = false #endif -private let macroFailureHandler = { @Sendable (failureSpec: TestFailureSpec) in - _ = Issue.record( - Comment(stringLiteral: failureSpec.message), - sourceLocation: failureSpec.location.sourceLocation, - ) -} - -func assertMacroExpansion( - _ originalSource: String, - expandedSource expectedExpandedSource: String, - diagnostics: [DiagnosticSpec] = [], - macroSpecs: [String: MacroSpec] = testMacroSpec, - applyFixIts: [String]? = nil, - fixedSource expectedFixedSource: String? = nil, - testModuleName: String = "TestModule", - testFileName: String = "test.swift", - indentationWidth: Trivia = .spaces(4), - fileID: StaticString = #fileID, - filePath: StaticString = #filePath, - line: UInt = #line, - column: UInt = #column, -) { - SwiftSyntaxMacrosGenericTestSupport.assertMacroExpansion( - originalSource, - expandedSource: expectedExpandedSource, - diagnostics: diagnostics, - macroSpecs: macroSpecs, - applyFixIts: applyFixIts, - fixedSource: expectedFixedSource, - testModuleName: testModuleName, - testFileName: testFileName, - indentationWidth: indentationWidth, - failureHandler: macroFailureHandler, - fileID: fileID, - filePath: filePath, - line: line, - column: column, - ) -} - @Suite(.disabled(if: !shouldRunMacroTest, "macros are not supported and cannot be imported for testing")) struct BinaryParseKitMacroTests {}