@@ -444,7 +444,7 @@ private func expandPreambleMacro(
444444private func expandBodyMacro(
445445 definition: BodyMacro . Type ,
446446 attributeNode: AttributeSyntax ,
447- attachedTo decl : some DeclSyntaxProtocol & WithOptionalCodeBlockSyntax ,
447+ attachedTo node : some SyntaxProtocol ,
448448 in context: some MacroExpansionContext ,
449449 indentationWidth: Trivia
450450) -> CodeBlockSyntax ? {
@@ -456,7 +456,7 @@ private func expandBodyMacro(
456456 in: context,
457457 foldingWith: . standardOperators
458458 ) ,
459- declarationNode: DeclSyntax ( decl . detach ( in: context) ) ,
459+ declarationNode: Syntax ( node . detach ( in: context) ) ,
460460 parentDeclNode: nil ,
461461 extendedType: nil ,
462462 conformanceList: nil ,
@@ -473,9 +473,16 @@ private func expandBodyMacro(
473473 // Remove any indentation from the first line using `drop(while:)` and then
474474 // prepend a space when it's being introduced on a declaration that has no
475475 // body yet.
476- let leadingWhitespace = decl. body == nil ? " " : " "
476+ let leadingWhitespace : String
477+ if let decl = node as? ( DeclSyntaxProtocol & WithOptionalCodeBlockSyntax ) ,
478+ decl. body == nil
479+ {
480+ leadingWhitespace = " "
481+ } else {
482+ leadingWhitespace = " "
483+ }
477484 let indentedSource =
478- leadingWhitespace + expanded. indented ( by: decl . indentationOfFirstLine) . drop ( while: { $0. isWhitespace } )
485+ leadingWhitespace + expanded. indented ( by: node . indentationOfFirstLine) . drop ( while: { $0. isWhitespace } )
479486 return " \( raw: indentedSource) "
480487}
481488
@@ -733,6 +740,19 @@ private class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
733740 return AttributeRemover ( removingWhere: { attributesToRemove. contains ( $0) } ) . rewrite ( visitedNode)
734741 }
735742
743+ if var closureSyntax = node. as ( ClosureExprSyntax . self) {
744+ closureSyntax = visitClosureBodyMacros ( closureSyntax)
745+
746+ // Visit the node, disabling the `visitAny` handling.
747+ skipVisitAnyHandling. insert ( Syntax ( closureSyntax) )
748+ let visitedNode = self . visit ( closureSyntax) . cast ( ClosureExprSyntax . self)
749+ skipVisitAnyHandling. remove ( Syntax ( closureSyntax) )
750+
751+ let attributesToRemove = self . macroAttributes ( attachedTo: visitedNode) . map ( \. attributeNode)
752+
753+ return AttributeRemover ( removingWhere: { attributesToRemove. contains ( $0) } ) . rewrite ( visitedNode)
754+ }
755+
736756 return nil
737757 }
738758
@@ -802,6 +822,41 @@ private class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
802822 return node. with ( \. body, body. with ( \. statements, preamble + body. statements) )
803823 }
804824
825+ func visitClosureBodyMacros(
826+ _ node: ClosureExprSyntax
827+ ) -> ClosureExprSyntax {
828+ // Expand body macro.
829+ let expandedBodies = expandMacros (
830+ attachedTo: node,
831+ ofType: BodyMacro . Type. self
832+ ) { attributeNode, definition, _ in
833+ expandBodyMacro (
834+ definition: definition,
835+ attributeNode: attributeNode,
836+ attachedTo: node,
837+ in: contextGenerator ( Syntax ( node) ) ,
838+ indentationWidth: indentationWidth
839+ ) . map { [ $0] }
840+ }
841+
842+ // Dig out the body.
843+ let body : CodeBlockSyntax
844+ switch expandedBodies. count {
845+ case 0 :
846+ // Nothing changes
847+ return node
848+
849+ case 1 :
850+ body = expandedBodies [ 0 ]
851+
852+ default :
853+ contextGenerator ( Syntax ( node) ) . addDiagnostics ( from: MacroExpansionError . moreThanOneBodyMacro, node: node)
854+ body = expandedBodies [ 0 ]
855+ }
856+
857+ return node. with ( \. statements, body. statements)
858+ }
859+
805860 override func visit( _ node: CodeBlockItemListSyntax ) -> CodeBlockItemListSyntax {
806861 var newItems : [ CodeBlockItemSyntax ] = [ ]
807862 func addResult( _ node: CodeBlockItemSyntax ) {
@@ -1006,9 +1061,16 @@ extension MacroApplication {
10061061 ///
10071062 /// The macros must be registered in `macroSystem`.
10081063 private func macroAttributes(
1009- attachedTo decl: DeclSyntax
1064+ attachedTo decl: some SyntaxProtocol
10101065 ) -> [ ( attributeNode: AttributeSyntax , spec: MacroSpec ) ] {
1011- guard let attributedNode = decl. asProtocol ( WithAttributesSyntax . self) else {
1066+ let attributedNode : ( any WithAttributesSyntax ) ?
1067+ if let closure = decl. as ( ClosureExprSyntax . self) {
1068+ attributedNode = closure. signature? . asProtocol ( WithAttributesSyntax . self)
1069+ } else {
1070+ attributedNode = decl. asProtocol ( WithAttributesSyntax . self)
1071+ }
1072+
1073+ guard let attributedNode else {
10121074 return [ ]
10131075 }
10141076
@@ -1029,7 +1091,7 @@ extension MacroApplication {
10291091 ///
10301092 /// The macros must be registered in `macroSystem`.
10311093 private func macroAttributes< MacroType> (
1032- attachedTo decl: DeclSyntax ,
1094+ attachedTo decl: some SyntaxProtocol ,
10331095 ofType: MacroType . Type
10341096 ) -> [ ( attributeNode: AttributeSyntax , definition: MacroType , conformanceList: InheritedTypeListSyntax ) ] {
10351097 return macroAttributes ( attachedTo: decl)
@@ -1049,7 +1111,7 @@ extension MacroApplication {
10491111 ExpandedNodeCollection: Sequence < ExpandedNode > ,
10501112 MacroType
10511113 > (
1052- attachedTo decl: DeclSyntax ,
1114+ attachedTo decl: some SyntaxProtocol ,
10531115 ofType: MacroType . Type ,
10541116 expandMacro:
10551117 (
0 commit comments