@@ -125,36 +125,41 @@ class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
125125 override func visit( _ node: CodeBlockItemListSyntax ) -> CodeBlockItemListSyntax {
126126 var newItems : [ CodeBlockItemSyntax ] = [ ]
127127 for item in node {
128- // Expand declaration macros that were parsed as macro expansion
129- // expressions in this context.
130- if case let . expr( exprItem) = item. item,
131- let exprExpansion = exprItem. as ( MacroExpansionExprSyntax . self) ,
132- let macro = macroSystem. macros [ exprExpansion. macro. text]
128+ if let expansion = item. item. asProtocol ( FreestandingMacroExpansionSyntax . self) ,
129+ let macro = macroSystem. macros [ expansion. macro. text]
133130 {
134- do {
131+ func _expand ( expansion : some FreestandingMacroExpansionSyntax ) throws {
135132 if let macro = macro as? CodeItemMacro . Type {
136133 let expandedItemList = try macro. expansion (
137- of: exprExpansion ,
134+ of: expansion ,
138135 in: context
139136 )
140137 newItems. append ( contentsOf: expandedItemList)
141138 } else if let macro = macro as? DeclarationMacro . Type {
142- let expandedItemList = try macro. expansion (
143- of: exprExpansion ,
139+ var expandedItemList = try macro. expansion (
140+ of: expansion ,
144141 in: context
145142 )
143+ if let declExpansion = expansion. as ( MacroExpansionDeclSyntax . self) {
144+ expandedItemList = expandedItemList. map {
145+ $0. applying ( attributes: declExpansion. attributes, modifiers: declExpansion. modifiers)
146+ }
147+ }
146148 newItems. append (
147149 contentsOf: expandedItemList. map {
148150 CodeBlockItemSyntax ( item: . decl( $0) )
149151 }
150152 )
151153 } else if let macro = macro as? ExpressionMacro . Type {
152154 let expandedExpr = try macro. expansion (
153- of: exprExpansion ,
155+ of: expansion ,
154156 in: context
155157 )
156158 newItems. append ( CodeBlockItemSyntax ( item: . init( expandedExpr) ) )
157159 }
160+ }
161+ do {
162+ try _openExistential ( expansion, do: _expand)
158163 } catch {
159164 context. addDiagnostics ( from: error, node: node)
160165 }
@@ -189,10 +194,13 @@ class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
189194 let freestandingMacro = macro as? DeclarationMacro . Type
190195 {
191196 do {
192- let expandedList = try freestandingMacro. expansion (
197+ var expandedList = try freestandingMacro. expansion (
193198 of: declExpansion,
194199 in: context
195200 )
201+ expandedList = expandedList. map {
202+ $0. applying ( attributes: declExpansion. attributes, modifiers: declExpansion. modifiers)
203+ }
196204
197205 newItems. append (
198206 contentsOf: expandedList. map { decl in
@@ -468,6 +476,44 @@ extension MacroApplication {
468476 }
469477}
470478
479+ extension DeclSyntax {
480+ /// Returns this node with `attributes` and `modifiers` prepended to the
481+ /// node’s attributes and modifiers, respectively. If the node doesn’t contain
482+ /// attributes or modifiers, `attributes` or `modifiers` are ignored and not
483+ /// applied.
484+ @_spi ( MacroExpansion)
485+ public func applying(
486+ attributes: AttributeListSyntax ? ,
487+ modifiers: ModifierListSyntax ?
488+ ) -> DeclSyntax {
489+ func _combine< C: SyntaxCollection > ( _ left: C , _ right: C ? ) -> C ? {
490+ guard let right = right else { return left }
491+ var elems : [ C . Element ] = [ ]
492+ elems. append ( contentsOf: left)
493+ elems. append ( contentsOf: right)
494+ return C ( elems)
495+ }
496+ var node = self
497+ if let attributes = attributes,
498+ let withAttrs = node. asProtocol ( WithAttributesSyntax . self)
499+ {
500+ node = withAttrs. with (
501+ \. attributes,
502+ _combine ( attributes, withAttrs. attributes)
503+ ) . cast ( DeclSyntax . self)
504+ }
505+ if let modifiers = modifiers,
506+ let withModifiers = node. asProtocol ( WithModifiersSyntax . self)
507+ {
508+ node = withModifiers. with (
509+ \. modifiers,
510+ _combine ( modifiers, withModifiers. modifiers)
511+ ) . cast ( DeclSyntax . self)
512+ }
513+ return node
514+ }
515+ }
516+
471517extension SyntaxProtocol {
472518 /// Expand all uses of the given set of macros within this syntax
473519 /// node.
0 commit comments