@@ -14,6 +14,7 @@ import SwiftBasicFormat
1414import SwiftDiagnostics
1515import SwiftSyntax
1616import SwiftSyntaxMacros
17+ import SwiftSyntaxMacroExpansion
1718
1819extension CompilerPluginMessageHandler {
1920 /// Get concrete macro type from a pair of module name and type name.
@@ -35,7 +36,7 @@ extension CompilerPluginMessageHandler {
3536 expansionDiscriminator: discriminator
3637 )
3738
38- let expandedSource : String
39+ let expandedSource : String ?
3940 do {
4041 guard let macroSyntax = syntax. asProtocol ( FreestandingMacroExpansionSyntax . self) else {
4142 throw MacroExpansionError . freestandingMacroSyntaxIsNotMacro
@@ -44,34 +45,14 @@ extension CompilerPluginMessageHandler {
4445 throw MacroExpansionError . macroTypeNotFound
4546 }
4647
47- switch macroDefinition {
48- case let exprMacroDef as ExpressionMacro . Type :
49- func _expand( node: some FreestandingMacroExpansionSyntax ) throws -> ExprSyntax {
50- try exprMacroDef. expansion ( of: node, in: context)
51- }
52- let rewritten = try _openExistential ( macroSyntax, do: _expand)
53- expandedSource = rewritten. formattedExpansion ( macroDefinition. formatMode)
54-
55- case let declMacroDef as DeclarationMacro . Type :
56- func _expand( node: some FreestandingMacroExpansionSyntax ) throws -> [ DeclSyntax ] {
57- try declMacroDef. expansion ( of: node, in: context)
58- }
59- let rewritten = try _openExistential ( macroSyntax, do: _expand)
60- expandedSource = CodeBlockItemListSyntax ( rewritten. map { CodeBlockItemSyntax ( item: . decl( $0) ) } ) . formattedExpansion ( macroDefinition. formatMode)
61-
62- case let codeItemMacroDef as CodeItemMacro . Type :
63- func _expand( node: some FreestandingMacroExpansionSyntax ) throws -> [ CodeBlockItemSyntax ] {
64- try codeItemMacroDef. expansion ( of: node, in: context)
65- }
66- let rewritten = try _openExistential ( macroSyntax, do: _expand)
67- expandedSource = CodeBlockItemListSyntax ( rewritten) . formattedExpansion ( macroDefinition. formatMode)
68-
69- default :
70- throw MacroExpansionError . unmathedMacroRole
71- }
48+ expandedSource = SwiftSyntaxMacroExpansion . expandFreestandingMacro (
49+ definition: macroDefinition,
50+ node: macroSyntax,
51+ in: context
52+ )
7253 } catch {
7354 context. addDiagnostics ( from: error, node: syntax)
74- expandedSource = " "
55+ expandedSource = nil
7556 }
7657
7758 let diagnostics = context. diagnostics. map {
@@ -99,132 +80,25 @@ extension CompilerPluginMessageHandler {
9980
10081 let attributeNode = sourceManager. add ( attributeSyntax) . cast ( AttributeSyntax . self)
10182 let declarationNode = sourceManager. add ( declSyntax) . cast ( DeclSyntax . self)
83+ let parentDeclNode = parentDeclSyntax. map { sourceManager. add ( $0) . cast ( DeclSyntax . self) }
10284
103- let expandedSources : [ String ]
85+ let expandedSources : [ String ] ?
10486 do {
10587 guard let macroDefinition = resolveMacro ( macro) else {
10688 throw MacroExpansionError . macroTypeNotFound
10789 }
10890
109- switch ( macroDefinition, macroRole) {
110- case ( let attachedMacro as AccessorMacro . Type , . accessor) :
111- let accessors = try attachedMacro. expansion (
112- of: attributeNode,
113- providingAccessorsOf: declarationNode,
114- in: context
115- )
116- expandedSources = accessors. map {
117- $0. formattedExpansion ( macroDefinition. formatMode)
118- }
119-
120- case ( let attachedMacro as MemberAttributeMacro . Type , . memberAttribute) :
121- guard
122- let parentDeclSyntax = parentDeclSyntax,
123- let parentDeclGroup = sourceManager. add ( parentDeclSyntax) . asProtocol ( DeclGroupSyntax . self)
124- else {
125- // Compiler error: 'parentDecl' is mandatory for MemberAttributeMacro.
126- throw MacroExpansionError . invalidExpansionMessage
127- }
128-
129- // Local function to expand a member atribute macro once we've opened up
130- // the existential.
131- func expandMemberAttributeMacro(
132- _ node: some DeclGroupSyntax
133- ) throws -> [ AttributeSyntax ] {
134- return try attachedMacro. expansion (
135- of: attributeNode,
136- attachedTo: node,
137- providingAttributesFor: declarationNode,
138- in: context
139- )
140- }
141-
142- let attributes = try _openExistential (
143- parentDeclGroup,
144- do: expandMemberAttributeMacro
145- )
146-
147- // Form a buffer containing an attribute list to return to the caller.
148- expandedSources = attributes. map {
149- $0. formattedExpansion ( macroDefinition. formatMode)
150- }
151-
152- case ( let attachedMacro as MemberMacro . Type , . member) :
153- guard let declGroup = declarationNode. asProtocol ( DeclGroupSyntax . self)
154- else {
155- // Compiler error: declNode for member macro must be DeclGroupSyntax.
156- throw MacroExpansionError . invalidExpansionMessage
157- }
158-
159- // Local function to expand a member macro once we've opened up
160- // the existential.
161- func expandMemberMacro(
162- _ node: some DeclGroupSyntax
163- ) throws -> [ DeclSyntax ] {
164- return try attachedMacro. expansion (
165- of: attributeNode,
166- providingMembersOf: node,
167- in: context
168- )
169- }
170-
171- let members = try _openExistential ( declGroup, do: expandMemberMacro)
172-
173- // Form a buffer of member declarations to return to the caller.
174- expandedSources = members. map { $0. formattedExpansion ( macroDefinition. formatMode) }
175-
176- case ( let attachedMacro as PeerMacro . Type , . peer) :
177- let peers = try attachedMacro. expansion (
178- of: attributeNode,
179- providingPeersOf: declarationNode,
180- in: context
181- )
182-
183- // Form a buffer of peer declarations to return to the caller.
184- expandedSources = peers. map {
185- $0. formattedExpansion ( macroDefinition. formatMode)
186- }
187-
188- case ( let attachedMacro as ConformanceMacro . Type , . conformance) :
189- guard
190- let declGroup = declarationNode. asProtocol ( DeclGroupSyntax . self) ,
191- let identified = declarationNode. asProtocol ( IdentifiedDeclSyntax . self)
192- else {
193- // Compiler error: type mismatch.
194- throw MacroExpansionError . invalidExpansionMessage
195- }
196-
197- // Local function to expand a conformance macro once we've opened up
198- // the existential.
199- func expandConformanceMacro(
200- _ node: some DeclGroupSyntax
201- ) throws -> [ ( TypeSyntax , GenericWhereClauseSyntax ? ) ] {
202- return try attachedMacro. expansion (
203- of: attributeNode,
204- providingConformancesOf: node,
205- in: context
206- )
207- }
208-
209- let conformances = try _openExistential (
210- declGroup,
211- do: expandConformanceMacro
212- )
213-
214- // Form a buffer of extension declarations to return to the caller.
215- expandedSources = conformances. map { typeSyntax, whereClause in
216- let typeName = identified. identifier. trimmedDescription
217- let protocolName = typeSyntax. trimmedDescription
218- let whereClause = whereClause? . trimmedDescription ?? " "
219- return " extension \( typeName) : \( protocolName) \( whereClause) {} "
220- }
221-
222- default :
223- throw MacroExpansionError . unmathedMacroRole
224- }
91+ expandedSources = SwiftSyntaxMacroExpansion . expandAttachedMacro (
92+ definition: macroDefinition,
93+ macroRole: MacroRole ( messageMacroRole: macroRole) ,
94+ attributeNode: attributeNode,
95+ declarationNode: declarationNode,
96+ parentDeclNode: parentDeclNode,
97+ in: context
98+ )
22599 } catch {
226100 context. addDiagnostics ( from: error, node: attributeNode)
227- expandedSources = [ ]
101+ expandedSources = nil
228102 }
229103
230104 let diagnostics = context. diagnostics. map {
@@ -236,17 +110,17 @@ extension CompilerPluginMessageHandler {
236110 }
237111}
238112
239- fileprivate extension SyntaxProtocol {
240- /// Perform a format if required and then trim any leading/trailing
241- /// whitespace.
242- func formattedExpansion( _ mode: FormatMode ) -> String {
243- let formatted : Syntax
244- switch mode {
245- case . auto:
246- formatted = self . formatted ( )
247- case . disabled:
248- formatted = Syntax ( self )
113+ private extension MacroRole {
114+ init ( messageMacroRole: PluginMessage . MacroRole ) {
115+ switch messageMacroRole {
116+ case . expression: self = . expression
117+ case . declaration: self = . declaration
118+ case . accessor: self = . accessor
119+ case . memberAttribute: self = . memberAttribute
120+ case . member: self = . member
121+ case . peer: self = . peer
122+ case . conformance: self = . conformance
123+ case . codeItem: self = . codeItem
249124 }
250- return formatted. trimmedDescription ( matching: { $0. isWhitespace } )
251125 }
252126}
0 commit comments