From 2dc1c261de5ef188585c710a802c38ebf42830b0 Mon Sep 17 00:00:00 2001 From: Adam Cmiel Date: Tue, 15 Apr 2025 13:20:02 -0400 Subject: [PATCH] [BasicMacroExpansionContext] attributes not found in basic expansion without source file --- .../PeerMacroTests.swift | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/Tests/SwiftSyntaxMacroExpansionTest/PeerMacroTests.swift b/Tests/SwiftSyntaxMacroExpansionTest/PeerMacroTests.swift index 0a9eaebcf6c..172d5ba0a6b 100644 --- a/Tests/SwiftSyntaxMacroExpansionTest/PeerMacroTests.swift +++ b/Tests/SwiftSyntaxMacroExpansionTest/PeerMacroTests.swift @@ -276,4 +276,54 @@ final class PeerMacroTests: XCTestCase { indentationWidth: indentationWidth ) } + + func testCanDetectAdjacentAttributesInContext() { + enum FoundObjCAttribute: String, Error, CustomDebugStringConvertible { + case noMethod + case noAttribute + case notFound + case found + var debugDescription: String { rawValue } + } + + struct FindObjCAttribute: PeerMacro { + static func expansion( + of node: AttributeSyntax, + providingPeersOf declaration: some DeclSyntaxProtocol, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + guard let methodDecl = declaration.as(FunctionDeclSyntax.self) else { + throw FoundObjCAttribute.noMethod + } + + guard let attribute = methodDecl.attributes.first(where: { + $0.as(AttributeSyntax.self)?.attributeName == "objc" + }) else { + throw FoundObjCAttribute.noAttribute + } + + guard context.location(of: attribute) != nil else { + throw FoundObjCAttribute.notFound + } + + return [] + } + } + assertMacroExpansion( + """ + @objc class Foo { + @objc @findObjCAttribute + func memberFunction() {} + } + """, + expandedSource: """ + @objc class Foo { + @objc + func memberFunction() {} + } + """, + diagnostics: [], + macros: ["findObjCAttribute": FindObjCAttribute.self], + ) + } }