diff --git a/Sources/SwiftSyntaxMacroExpansion/MacroExpansion.swift b/Sources/SwiftSyntaxMacroExpansion/MacroExpansion.swift index 7e241879195..18af9926cce 100644 --- a/Sources/SwiftSyntaxMacroExpansion/MacroExpansion.swift +++ b/Sources/SwiftSyntaxMacroExpansion/MacroExpansion.swift @@ -46,8 +46,10 @@ public func expandFreestandingMacro( var rewritten = try declMacroDef.expansion(of: node, in: context) // Copy attributes and modifiers to the generated decls. if let expansionDecl = node.as(MacroExpansionDeclSyntax.self) { + let attributes = declMacroDef.propagateFreestandingMacroAttributes ? expansionDecl.attributes : nil + let modifiers = declMacroDef.propagateFreestandingMacroModifiers ? expansionDecl.modifiers : nil rewritten = rewritten.map { - $0.applying(attributes: expansionDecl.attributes, modifiers: expansionDecl.modifiers) + $0.applying(attributes: attributes, modifiers: modifiers) } } expandedSyntax = Syntax( diff --git a/Sources/SwiftSyntaxMacros/MacroProtocols/DeclarationMacro.swift b/Sources/SwiftSyntaxMacros/MacroProtocols/DeclarationMacro.swift index cd5c788342d..a7a58fd0603 100644 --- a/Sources/SwiftSyntaxMacros/MacroProtocols/DeclarationMacro.swift +++ b/Sources/SwiftSyntaxMacros/MacroProtocols/DeclarationMacro.swift @@ -20,4 +20,16 @@ public protocol DeclarationMacro: FreestandingMacro { of node: Node, in context: Context ) throws -> [DeclSyntax] + + /// Whether to copy attributes on the expansion syntax to expanded declarations, + /// 'true' by default. + static var propagateFreestandingMacroAttributes: Bool { get } + /// Whether to copy modifiers on the expansion syntax to expanded declarations, + /// 'true' by default. + static var propagateFreestandingMacroModifiers: Bool { get } +} + +public extension DeclarationMacro { + static var propagateFreestandingMacroAttributes: Bool { true } + static var propagateFreestandingMacroModifiers: Bool { true } } diff --git a/Sources/SwiftSyntaxMacros/MacroSystem.swift b/Sources/SwiftSyntaxMacros/MacroSystem.swift index 37bc20f41e0..e40457a8dea 100644 --- a/Sources/SwiftSyntaxMacros/MacroSystem.swift +++ b/Sources/SwiftSyntaxMacros/MacroSystem.swift @@ -141,8 +141,10 @@ class MacroApplication: SyntaxRewriter { in: context ) if let declExpansion = expansion.as(MacroExpansionDeclSyntax.self) { + let attributes = macro.propagateFreestandingMacroAttributes ? declExpansion.attributes : nil + let modifiers = macro.propagateFreestandingMacroModifiers ? declExpansion.modifiers : nil expandedItemList = expandedItemList.map { - $0.applying(attributes: declExpansion.attributes, modifiers: declExpansion.modifiers) + $0.applying(attributes: attributes, modifiers: modifiers) } } newItems.append( @@ -198,8 +200,10 @@ class MacroApplication: SyntaxRewriter { of: declExpansion, in: context ) + let attributes = freestandingMacro.propagateFreestandingMacroAttributes ? declExpansion.attributes : nil + let modifiers = freestandingMacro.propagateFreestandingMacroModifiers ? declExpansion.modifiers : nil expandedList = expandedList.map { - $0.applying(attributes: declExpansion.attributes, modifiers: declExpansion.modifiers) + $0.applying(attributes: attributes, modifiers: modifiers) } newItems.append( diff --git a/Tests/SwiftSyntaxMacrosTest/MacroSystemTests.swift b/Tests/SwiftSyntaxMacrosTest/MacroSystemTests.swift index ea0dbe610c1..31f0758c544 100644 --- a/Tests/SwiftSyntaxMacrosTest/MacroSystemTests.swift +++ b/Tests/SwiftSyntaxMacrosTest/MacroSystemTests.swift @@ -672,6 +672,30 @@ public struct DeclsFromStringsMacro: DeclarationMacro { } } +public struct DeclsFromStringsMacroNoAttrs: DeclarationMacro { + public static var propagateFreestandingMacroAttributes: Bool { false } + public static var propagateFreestandingMacroModifiers: Bool { false } + + public static func expansion( + of node: some FreestandingMacroExpansionSyntax, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + var strings: [String] = [] + for arg in node.argumentList { + guard + let value = arg.expression.as(StringLiteralExprSyntax.self)?.representedLiteralValue + else { + continue + } + strings.append(value) + } + + return strings.map { + "\(raw: $0)" + } + } +} + // MARK: Tests /// The set of test macros we use here. @@ -1114,5 +1138,22 @@ final class MacroSystemTests: XCTestCase { macros: ["decls": DeclsFromStringsMacro.self], indentationWidth: indentationWidth ) + + assertMacroExpansion( + #""" + @attribute + @otherAttribute(x: 1) + public #decls("@moreAttibute var global = 42", + "private func foo() {}") + """#, + expandedSource: #""" + @moreAttibute var global = 42 + private func foo() { + } + """#, + macros: ["decls": DeclsFromStringsMacroNoAttrs.self], + indentationWidth: indentationWidth + ) + } }