@@ -444,7 +444,7 @@ private func expandPreambleMacro(
444
444
private func expandBodyMacro(
445
445
definition: BodyMacro . Type ,
446
446
attributeNode: AttributeSyntax ,
447
- attachedTo decl : some DeclSyntaxProtocol & WithOptionalCodeBlockSyntax ,
447
+ attachedTo node : some SyntaxProtocol ,
448
448
in context: some MacroExpansionContext ,
449
449
indentationWidth: Trivia
450
450
) -> CodeBlockSyntax ? {
@@ -456,7 +456,7 @@ private func expandBodyMacro(
456
456
in: context,
457
457
foldingWith: . standardOperators
458
458
) ,
459
- declarationNode: DeclSyntax ( decl . detach ( in: context) ) ,
459
+ declarationNode: Syntax ( node . detach ( in: context) ) ,
460
460
parentDeclNode: nil ,
461
461
extendedType: nil ,
462
462
conformanceList: nil ,
@@ -473,9 +473,16 @@ private func expandBodyMacro(
473
473
// Remove any indentation from the first line using `drop(while:)` and then
474
474
// prepend a space when it's being introduced on a declaration that has no
475
475
// 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
+ }
477
484
let indentedSource =
478
- leadingWhitespace + expanded. indented ( by: decl . indentationOfFirstLine) . drop ( while: { $0. isWhitespace } )
485
+ leadingWhitespace + expanded. indented ( by: node . indentationOfFirstLine) . drop ( while: { $0. isWhitespace } )
479
486
return " \( raw: indentedSource) "
480
487
}
481
488
@@ -733,6 +740,19 @@ private class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
733
740
return AttributeRemover ( removingWhere: { attributesToRemove. contains ( $0) } ) . rewrite ( visitedNode)
734
741
}
735
742
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
+
736
756
return nil
737
757
}
738
758
@@ -802,6 +822,41 @@ private class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
802
822
return node. with ( \. body, body. with ( \. statements, preamble + body. statements) )
803
823
}
804
824
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
+
805
860
override func visit( _ node: CodeBlockItemListSyntax ) -> CodeBlockItemListSyntax {
806
861
var newItems : [ CodeBlockItemSyntax ] = [ ]
807
862
func addResult( _ node: CodeBlockItemSyntax ) {
@@ -1006,9 +1061,16 @@ extension MacroApplication {
1006
1061
///
1007
1062
/// The macros must be registered in `macroSystem`.
1008
1063
private func macroAttributes(
1009
- attachedTo decl: DeclSyntax
1064
+ attachedTo decl: some SyntaxProtocol
1010
1065
) -> [ ( 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 {
1012
1074
return [ ]
1013
1075
}
1014
1076
@@ -1029,7 +1091,7 @@ extension MacroApplication {
1029
1091
///
1030
1092
/// The macros must be registered in `macroSystem`.
1031
1093
private func macroAttributes< MacroType> (
1032
- attachedTo decl: DeclSyntax ,
1094
+ attachedTo decl: some SyntaxProtocol ,
1033
1095
ofType: MacroType . Type
1034
1096
) -> [ ( attributeNode: AttributeSyntax , definition: MacroType , conformanceList: InheritedTypeListSyntax ) ] {
1035
1097
return macroAttributes ( attachedTo: decl)
@@ -1049,7 +1111,7 @@ extension MacroApplication {
1049
1111
ExpandedNodeCollection: Sequence < ExpandedNode > ,
1050
1112
MacroType
1051
1113
> (
1052
- attachedTo decl: DeclSyntax ,
1114
+ attachedTo decl: some SyntaxProtocol ,
1053
1115
ofType: MacroType . Type ,
1054
1116
expandMacro:
1055
1117
(
0 commit comments