From 32f57055bdc19ec353fc2ced84a2f21818155b2c Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 4 Aug 2023 16:30:56 -0700 Subject: [PATCH] [SE-0407] Add missingConformancesTo argument to MemberMacro expansion operation Stage in an entrypoint for member macros that allows them to learn about which conformances that they've asked about are "missing", meaning that they are not present on the type (ignoring those that would be generated by an extension macro). This information is equivalent to the information provided to extension macros, although the member macro itself cannot create the conformance. --- .../MacroExpansion.swift | 19 +++----- .../MacroProtocols/MemberMacro.swift | 45 +++++++++++++++++++ 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/Sources/SwiftSyntaxMacroExpansion/MacroExpansion.swift b/Sources/SwiftSyntaxMacroExpansion/MacroExpansion.swift index efcb6bdb34a..5156ec815a0 100644 --- a/Sources/SwiftSyntaxMacroExpansion/MacroExpansion.swift +++ b/Sources/SwiftSyntaxMacroExpansion/MacroExpansion.swift @@ -238,19 +238,12 @@ public func expandAttachedMacroWithoutCollapsing throw MacroExpansionError.declarationNotDeclGroup } - // Local function to expand a member macro once we've opened up - // the existential. - func expandMemberMacro( - _ node: some DeclGroupSyntax - ) throws -> [DeclSyntax] { - return try attachedMacro.expansion( - of: attributeNode, - providingMembersOf: node, - in: context - ) - } - - let members = try _openExistential(declGroup, do: expandMemberMacro) + let members = try attachedMacro.expansion( + of: attributeNode, + providingMembersOf: declGroup, + conformingTo: conformanceList?.map(\.typeName) ?? [], + in: context + ) // Form a buffer of member declarations to return to the caller. return members.map { $0.formattedExpansion(definition.formatMode) } diff --git a/Sources/SwiftSyntaxMacros/MacroProtocols/MemberMacro.swift b/Sources/SwiftSyntaxMacros/MacroProtocols/MemberMacro.swift index 78942e3123e..e5673bacc35 100644 --- a/Sources/SwiftSyntaxMacros/MacroProtocols/MemberMacro.swift +++ b/Sources/SwiftSyntaxMacros/MacroProtocols/MemberMacro.swift @@ -23,9 +23,54 @@ public protocol MemberMacro: AttachedMacro { /// /// - Returns: the set of member declarations introduced by this macro, which /// are nested inside the `attachedTo` declaration. + @available(*, deprecated, message: "Use expansion(of:providingMembersOf:conformingTo:in:") static func expansion( of node: AttributeSyntax, providingMembersOf declaration: some DeclGroupSyntax, in context: some MacroExpansionContext ) throws -> [DeclSyntax] + + /// Expand an attached declaration macro to produce a set of members. + /// + /// - Parameters: + /// - node: The custom attribute describing the attached macro. + /// - declaration: The declaration the macro attribute is attached to. + /// - conformingTo: The set of protocols that were declared + /// in the set of conformances for the macro and to which the declaration + /// does not explicitly conform. The member macro itself cannot declare + /// conformances to these protocols (only an extension macro can do that), + /// but can provide supporting declarations, such as a required + /// initializer or stored property, that cannot be written in an + /// extension. + /// - context: The context in which to perform the macro expansion. + /// + /// - Returns: the set of member declarations introduced by this macro, which + /// are nested inside the `attachedTo` declaration. + static func expansion( + of node: AttributeSyntax, + providingMembersOf declaration: some DeclGroupSyntax, + conformingTo protocols: [TypeSyntax], + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] +} + +public extension MemberMacro { + /// Default implementation supplies no conformances. + static func expansion( + of node: AttributeSyntax, + providingMembersOf declaration: some DeclGroupSyntax, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + return try expansion(of: node, providingMembersOf: declaration, conformingTo: [], in: context) + } + + /// Default implementation that ignores the unhandled conformances. + static func expansion( + of node: AttributeSyntax, + providingMembersOf declaration: some DeclGroupSyntax, + conformingTo protocols: [TypeSyntax], + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + return try expansion(of: node, providingMembersOf: declaration, in: context) + } }