@@ -240,6 +240,52 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
240
240
return . visitChildren
241
241
}
242
242
243
+ override func visit( _ node: MacroDeclSyntax ) -> SyntaxVisitorContinueKind {
244
+ // Macro declarations have a syntax that combines the best parts of types and functions while
245
+ // adding their own unique flavor, so we have to copy and adapt the relevant parts of those
246
+ // `arrange*` functions here.
247
+ before ( node. firstToken ( viewMode: . sourceAccurate) , tokens: . open)
248
+
249
+ arrangeAttributeList ( node. attributes)
250
+
251
+ let hasArguments = !node. signature. input. parameterList. isEmpty
252
+
253
+ // Prioritize keeping ") -> <return_type>" together. We can only do this if the macro has
254
+ // arguments.
255
+ if hasArguments && config. prioritizeKeepingFunctionOutputTogether {
256
+ // Due to visitation order, the matching .open break is added in ParameterClauseSyntax.
257
+ after ( node. signature. lastToken ( viewMode: . sourceAccurate) , tokens: . close)
258
+ }
259
+
260
+ let mustBreak = node. signature. output != nil || node. definition != nil
261
+ arrangeParameterClause ( node. signature. input, forcesBreakBeforeRightParen: mustBreak)
262
+
263
+ // Prioritize keeping "<modifiers> macro <name>(" together. Also include the ")" if the
264
+ // parameter list is empty.
265
+ let firstTokenAfterAttributes =
266
+ node. modifiers? . firstToken ( viewMode: . sourceAccurate) ?? node. macroKeyword
267
+ before ( firstTokenAfterAttributes, tokens: . open)
268
+ after ( node. macroKeyword, tokens: . break)
269
+ if hasArguments || node. genericParameterClause != nil {
270
+ after ( node. signature. input. leftParen, tokens: . close)
271
+ } else {
272
+ after ( node. signature. input. rightParen, tokens: . close)
273
+ }
274
+
275
+ if let genericWhereClause = node. genericWhereClause {
276
+ before ( genericWhereClause. firstToken ( viewMode: . sourceAccurate) , tokens: . break( . same) , . open)
277
+ after ( genericWhereClause. lastToken ( viewMode: . sourceAccurate) , tokens: . close)
278
+ }
279
+ if let definition = node. definition {
280
+ // Start the group *after* the `=` so that it all wraps onto its own line if it doesn't fit.
281
+ after ( definition. equal, tokens: . open)
282
+ after ( definition. lastToken ( viewMode: . sourceAccurate) , tokens: . close)
283
+ }
284
+
285
+ after ( node. lastToken ( viewMode: . sourceAccurate) , tokens: . close)
286
+ return . visitChildren
287
+ }
288
+
243
289
/// Applies formatting tokens to the tokens in the given type declaration node (i.e., a class,
244
290
/// struct, enum, protocol, or extension).
245
291
private func arrangeTypeDeclBlock(
0 commit comments