-
Notifications
You must be signed in to change notification settings - Fork 453
Description
Description
MacroApplication
currently applies the member attribute macro, then expands peer macros on the resulting modified node (MacroApplication.visit(MemberBlockSyntax)
). This can result in slightly different behavior to the expansion in the compiler, as the peer macro there will receive the original (unmodified) member. This usually doesn't matter too much in practice, but can if the macro isn't handling trivia correctly.
Consider a member attribute macro (@someMemberMacro
) that adds an attribute for a peer macro, which then adds a peer to copy the original member with some small modifications (renaming the member and adding an extra attribute, without trivia handling).
@someMemberMacro
struct Foo {
@someAttribute // some trailing comment
let foo: Int
}
MacroApplication
will first apply the member macro, resulting in:
struct Foo {
@someAttribute
@somePeerMacro // some trailing comment
let foo: Int
}
Then the peer:
struct Foo {
@someAttribute // some trailing comment
let foo: Int
@someAttribute
@extraAttribute
let _foo: Int
}
Note the move of the trailing comment to @somePeerMacro
, which is then removed after the expansion of said peer macro.
This differs from the compiler itself, which will have @somePeerMacro
in a separate buffer, then passing the original decl to the expansion. That would then result in (with this buggy macro implementation):
@someAttribute // some trailing comment@extraAttribute let _foo: Int
So from the swift-syntax side, everything seems "fine", but that's not actually the case - this can lead to a fair amount of confusion for macro authors.
See also: swiftlang/swift#84145
Steps to Reproduce
No response