@@ -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,15 @@ 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 =
477+ if let decl = node as? ( DeclSyntaxProtocol & WithOptionalCodeBlockSyntax ) ,
478+ decl. body == nil {
479+ " "
480+ } else {
481+ " "
482+ }
477483 let indentedSource =
478- leadingWhitespace + expanded. indented ( by: decl . indentationOfFirstLine) . drop ( while: { $0. isWhitespace } )
484+ leadingWhitespace + expanded. indented ( by: node . indentationOfFirstLine) . drop ( while: { $0. isWhitespace } )
479485 return " \( raw: indentedSource) "
480486}
481487
@@ -733,6 +739,19 @@ private class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
733739 return AttributeRemover ( removingWhere: { attributesToRemove. contains ( $0) } ) . rewrite ( visitedNode)
734740 }
735741
742+ if var closureSyntax = node. as ( ClosureExprSyntax . self) {
743+ closureSyntax = visitClosureBodyMacros ( closureSyntax)
744+
745+ // Visit the node, disabling the `visitAny` handling.
746+ skipVisitAnyHandling. insert ( Syntax ( closureSyntax) )
747+ let visitedNode = self . visit ( closureSyntax) . cast ( ClosureExprSyntax . self)
748+ skipVisitAnyHandling. remove ( Syntax ( closureSyntax) )
749+
750+ let attributesToRemove = self . macroAttributes ( attachedTo: visitedNode) . map ( \. attributeNode)
751+
752+ return AttributeRemover ( removingWhere: { attributesToRemove. contains ( $0) } ) . rewrite ( visitedNode)
753+ }
754+
736755 return nil
737756 }
738757
@@ -802,6 +821,41 @@ private class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
802821 return node. with ( \. body, body. with ( \. statements, preamble + body. statements) )
803822 }
804823
824+ func visitClosureBodyMacros(
825+ _ node: ClosureExprSyntax
826+ ) -> ClosureExprSyntax {
827+ // Expand body macro.
828+ let expandedBodies = expandMacros (
829+ attachedTo: node,
830+ ofType: BodyMacro . Type. self
831+ ) { attributeNode, definition, _ in
832+ expandBodyMacro (
833+ definition: definition,
834+ attributeNode: attributeNode,
835+ attachedTo: node,
836+ in: contextGenerator ( Syntax ( node) ) ,
837+ indentationWidth: indentationWidth
838+ ) . map { [ $0] }
839+ }
840+
841+ // Dig out the body.
842+ let body : CodeBlockSyntax
843+ switch expandedBodies. count {
844+ case 0 :
845+ // Nothing changes
846+ return node
847+
848+ case 1 :
849+ body = expandedBodies [ 0 ]
850+
851+ default :
852+ contextGenerator ( Syntax ( node) ) . addDiagnostics ( from: MacroExpansionError . moreThanOneBodyMacro, node: node)
853+ body = expandedBodies [ 0 ]
854+ }
855+
856+ return node. with ( \. statements, body. statements)
857+ }
858+
805859 override func visit( _ node: CodeBlockItemListSyntax ) -> CodeBlockItemListSyntax {
806860 var newItems : [ CodeBlockItemSyntax ] = [ ]
807861 func addResult( _ node: CodeBlockItemSyntax ) {
@@ -1006,9 +1060,16 @@ extension MacroApplication {
10061060 ///
10071061 /// The macros must be registered in `macroSystem`.
10081062 private func macroAttributes(
1009- attachedTo decl: DeclSyntax
1063+ attachedTo decl: some SyntaxProtocol
10101064 ) -> [ ( attributeNode: AttributeSyntax , spec: MacroSpec ) ] {
1011- guard let attributedNode = decl. asProtocol ( WithAttributesSyntax . self) else {
1065+ let attributedNode : ( any WithAttributesSyntax ) ?
1066+ if let closure = decl. as ( ClosureExprSyntax . self) {
1067+ attributedNode = closure. signature? . asProtocol ( WithAttributesSyntax . self)
1068+ } else {
1069+ attributedNode = decl. asProtocol ( WithAttributesSyntax . self)
1070+ }
1071+
1072+ guard let attributedNode else {
10121073 return [ ]
10131074 }
10141075
@@ -1029,7 +1090,7 @@ extension MacroApplication {
10291090 ///
10301091 /// The macros must be registered in `macroSystem`.
10311092 private func macroAttributes< MacroType> (
1032- attachedTo decl: DeclSyntax ,
1093+ attachedTo decl: some SyntaxProtocol ,
10331094 ofType: MacroType . Type
10341095 ) -> [ ( attributeNode: AttributeSyntax , definition: MacroType , conformanceList: InheritedTypeListSyntax ) ] {
10351096 return macroAttributes ( attachedTo: decl)
@@ -1049,7 +1110,7 @@ extension MacroApplication {
10491110 ExpandedNodeCollection: Sequence < ExpandedNode > ,
10501111 MacroType
10511112 > (
1052- attachedTo decl: DeclSyntax ,
1113+ attachedTo decl: some SyntaxProtocol ,
10531114 ofType: MacroType . Type ,
10541115 expandMacro:
10551116 (
0 commit comments