Space Omission in Macro-Expanded Code Using `TryExprSyntax` or `AwaitExprSyntax` within String Interpolation
Matejkob opened this issue · 2 comments
Description
When using TryExprSyntax
or AwaitExprSyntax
in a macro expansion context, the resulting code omits the space between the try
(or await
) keyword and the subsequent expression when these are incorporated via string interpolation.
Steps to Reproduce
-
Define a macro expansion that produces an expression using
TryExprSyntax
, as demonstrated in the following code snippet:public static func expansion( of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext ) -> ExprSyntax { let tryExpression = ExprSyntax(TryExprSyntax(expression: ExprSyntax("foo()"))) return tryExpression }
This code correctly expands to
try foo()
with a space betweentry
andfoo()
. -
Use the resulting
tryExpression
within another expression using string interpolation:public static func expansion( of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext ) -> ExprSyntax { let tryExpression = ExprSyntax(TryExprSyntax(expression: ExprSyntax("foo()"))) let ifExpression: ExprSyntax = """ if true { \(tryExpression) } """ return ifExpression }
The expected expansion would be:
if true { try foo() }
However, the actual expansion is:
if true { tryfoo() }
Notice the missing space between
try
andfoo()
.
Expected Behavior:
The macro expansion should maintain the space between the try
keyword and the subsequent expression, even when used within string interpolation.
Actual Behavior:
The space between the try
keyword and the expression is omitted in the macro-expanded code when used within string interpolation. The same issue is suspected to occur with AwaitExprSyntax
.
Tracked in Apple’s issue tracker as rdar://118271505
This is expected behavior. Building up a string interpolation inserts the source code of the subtree and then re-parses it. ?Since tryExpression
is not formatted, it doesn’t have a space between try
and foo
and you thus end up inserting tryfoo()
in the string interpolation.
To fix this, build up the subtree using a result builder or format the subexpression i.e. either
- Use
SwiftSyntaxBuilder
to build the if expression
IfExprSyntax("if true") {
tryExpression
}
\(tryExpression, format: BasicFormat())
\(tryExpression.formatted())
I would recommend approach (1).