@@ -200,6 +200,21 @@ public struct AllLexicalContextsMacro: DeclarationMacro {
200200 }
201201}
202202
203+ public struct LexicalContextDescriptionMacro : ExpressionMacro {
204+ public static func expansion(
205+ of node: some FreestandingMacroExpansionSyntax ,
206+ in context: some MacroExpansionContext
207+ ) throws -> ExprSyntax {
208+ let descriptions = context. lexicalContext. reduce ( into: " " ) { descriptions, syntax in
209+ descriptions += " \( syntax. trimmed) \n "
210+ }
211+ return """
212+ \" \" \"
213+ \( raw: descriptions) \" \" \"
214+ """
215+ }
216+ }
217+
203218final class LexicalContextTests : XCTestCase {
204219 private let indentationWidth : Trivia = . spaces( 2 )
205220
@@ -505,5 +520,49 @@ final class LexicalContextTests: XCTestCase {
505520 // Test closures separately, because they don't fit as declaration macros.
506521 let closure : ExprSyntax = " { (a, b) in print(a + b) } "
507522 XCTAssertEqual ( closure. asMacroLexicalContext ( ) !. description, " { (a, b) in } " )
523+
524+ // Test freestanding macros separately, because since the context contains
525+ // the full body of the macro, including each decl from the context as a new
526+ // decl in the expansion results in a cycle. So we instead use a macro that
527+ // generates a description of the lexical context.
528+ assertMacroExpansion (
529+ """
530+ #M(a: 1, b: 2) { c in
531+ struct S {
532+ let arg: C
533+ var contextDescription: String {
534+ #lexicalContextDescription
535+ }
536+ }
537+ return S(arg: c)
538+ }
539+ """ ,
540+ expandedSource: #"""
541+ #M(a: 1, b: 2) { c in
542+ struct S {
543+ let arg: C
544+ var contextDescription: String {
545+ """
546+ contextDescription: String
547+ struct S {}
548+ { c in
549+ }
550+ #M(a: 1, b: 2) { c in
551+ struct S {
552+ let arg: C
553+ var contextDescription: String {
554+ #lexicalContextDescription
555+ }
556+ }
557+ return S(arg: c)
558+ }
559+ """
560+ }
561+ }
562+ return S(arg: c)
563+ }
564+ """# ,
565+ macros: [ " lexicalContextDescription " : LexicalContextDescriptionMacro . self]
566+ )
508567 }
509568}
0 commit comments