Files
swift-mirror/test/ConstExtraction/Inputs/Macros.swift
Artem Chikin f5f0c0043d [Compile Time Constant Extraction] Query nominal type conformances to get at the protocols, instead of getAllProtocols.
As it stands, for extension macros which add protocol conformances, the list of protocols specified on the macro's 'conformances:' parameter gets added in its entirety to the list of a nominal type's protocols in 'ConformanceLookupTable::addMacroGeneratedProtocols'. Whereas the macro itself, may only add *some* of the specified conformances. This means that `getAllProtocols` may contain a super-set of protocols captured in `getAllConformances`, some of which may not actually be generated by the macro.

This change narrowly fixes ConstExtract to query actual generated conformances. Though, potentially we should make 'ConformanceLookupTable::addMacroGeneratedProtocols' behave in a way that reflects the protocols the macro actually adds the conformances to, instead of the ones it may add conformances to.

Resolves rdar://130316531
2024-06-25 12:29:29 -07:00

180 lines
4.7 KiB
Swift

import SwiftDiagnostics
import SwiftOperators
import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftSyntaxMacros
public struct AddStructDeclMacro: DeclarationMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
return [
"""
@AddExtension
struct MacroAddedStruct {
var macroAddedStructMember = 1
}
"""
]
}
}
public struct AddVarDeclMacro: DeclarationMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
return [
"""
static let macroAddedVar = 2
"""
]
}
}
public struct AddExtensionMacro: ExtensionMacro {
public static func expansion(
of node: AttributeSyntax,
attachedTo declaration: some DeclGroupSyntax,
providingExtensionsOf type: some TypeSyntaxProtocol,
conformingTo protocols: [TypeSyntax],
in context: some MacroExpansionContext
) throws -> [ExtensionDeclSyntax] {
let typeName = declaration.declGroupName
return protocols.map {
("""
extension \(typeName): \($0) {
struct _Extension_\($0): \($0) {
var nested = 8
}
}
""" as DeclSyntax)
.cast(ExtensionDeclSyntax.self)
} + [
("""
extension \(typeName) {
static let _extension_\(typeName) = 3
}
""" as DeclSyntax).cast(ExtensionDeclSyntax.self)
]
}
}
public struct AddSpecificExtensionMacro: ExtensionMacro {
public static func expansion(
of node: AttributeSyntax,
attachedTo declaration: some DeclGroupSyntax,
providingExtensionsOf type: some TypeSyntaxProtocol,
conformingTo protocols: [TypeSyntax],
in context: some MacroExpansionContext
) throws -> [ExtensionDeclSyntax] {
var extensions = [ExtensionDeclSyntax]()
let protocolNames = Set(protocols.compactMap { $0.as(IdentifierTypeSyntax.self)?.name.text })
if protocolNames.contains("MyProto") {
extensions.append(try ExtensionDeclSyntax("extension \(type.trimmed): MyProto") { })
}
return extensions
}
}
public struct AddPeerVarMacro: PeerMacro {
public static func expansion(
of node: AttributeSyntax,
providingPeersOf declaration: some DeclSyntaxProtocol,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
let name = declaration.declName
return [
"""
static var _peer_\(name) = 4
"""
]
}
}
public struct AddMemberMacro: MemberMacro {
public static func expansion(
of node: AttributeSyntax,
providingMembersOf declaration: some DeclGroupSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
let typeName = declaration.declGroupName
return [
"""
static let _member_\(typeName) = 5
"""
]
}
}
public struct AddMemberAttributeMacro: MemberAttributeMacro {
public static func expansion(
of node: AttributeSyntax,
attachedTo declaration: some DeclGroupSyntax,
providingAttributesFor member: some DeclSyntaxProtocol,
in context: some MacroExpansionContext
) throws -> [AttributeSyntax] {
if member.isProtocol(DeclGroupSyntax.self) {
return ["@AddExtension"]
}
return ["@AddPeerVar"]
}
}
public struct GetterMacro: AccessorMacro {
public static func expansion(
of node: AttributeSyntax,
providingAccessorsOf declaration: some DeclSyntaxProtocol,
in context: some MacroExpansionContext
) throws -> [AccessorDeclSyntax] {
return ["get { 6 }"]
}
}
public struct AddPeerStructMacro: PeerMacro {
public static func expansion(
of node: AttributeSyntax,
providingPeersOf declaration: some DeclSyntaxProtocol,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
let name = declaration.declName
return [
"""
@AddExtension
@AddMemberVar
struct _Peer_\(name) {
#AddMacroAddedVar
@AddPeerVar
var peerMacroVar = 7
}
"""
]
}
}
extension DeclGroupSyntax {
var declGroupName: TokenSyntax {
if let structDecl = self.as(StructDeclSyntax.self) {
return structDecl.name.trimmed
}
fatalError("Not implemented")
}
}
extension DeclSyntaxProtocol {
var declName: TokenSyntax {
if let varDecl = self.as(VariableDeclSyntax.self),
let first = varDecl.bindings.first,
let pattern = first.pattern.as(IdentifierPatternSyntax.self) {
return pattern.identifier.trimmed
} else if let funcDecl = self.as(FunctionDeclSyntax.self) {
return funcDecl.name.trimmed
} else if let structDecl = self.as(StructDeclSyntax.self) {
return structDecl.name.trimmed
}
fatalError("Not implemented")
}
}