diff --git a/Sources/KarrotCodableKit/PolymorphicCodable/Interface/PolymorphicCodableStrategyProviding.swift b/Sources/KarrotCodableKit/PolymorphicCodable/Interface/PolymorphicCodableStrategyProviding.swift index e69c323..7129e1e 100644 --- a/Sources/KarrotCodableKit/PolymorphicCodable/Interface/PolymorphicCodableStrategyProviding.swift +++ b/Sources/KarrotCodableKit/PolymorphicCodable/Interface/PolymorphicCodableStrategyProviding.swift @@ -25,7 +25,7 @@ import Foundation when no matching type is found. The default value for this property is `nil`. */ @attached(peer, names: suffixed(CodableStrategy)) -@attached(extension, names: arbitrary) +@attached(member, names: arbitrary) public macro PolymorphicCodableStrategyProviding( identifierCodingKey: String = "type", matchingTypes: [PolymorphicDecodableType.Type], diff --git a/Sources/KarrotCodableKitMacros/PolymorphicCodableMacros/PolymorphicCodableStrategyMacro.swift b/Sources/KarrotCodableKitMacros/PolymorphicCodableMacros/PolymorphicCodableStrategyMacro.swift index c6ac28f..03cd6a3 100644 --- a/Sources/KarrotCodableKitMacros/PolymorphicCodableMacros/PolymorphicCodableStrategyMacro.swift +++ b/Sources/KarrotCodableKitMacros/PolymorphicCodableMacros/PolymorphicCodableStrategyMacro.swift @@ -10,16 +10,45 @@ import SwiftSyntax import SwiftSyntaxBuilder import SwiftSyntaxMacros -public struct PolymorphicCodableStrategyProvidingMacro: PeerMacro { +public struct PolymorphicCodableStrategyProvidingMacro {} + +// MARK: - MemberMacro + +extension PolymorphicCodableStrategyProvidingMacro: MemberMacro { public static func expansion( of node: AttributeSyntax, - providingPeersOf declaration: some DeclSyntaxProtocol, + providingMembersOf declaration: some DeclGroupSyntax, in context: some MacroExpansionContext ) throws -> [DeclSyntax] { guard let protocolDecl = declaration.as(ProtocolDeclSyntax.self) else { throw CodableKitError.message("Macro must be attached to a protocol.") } + let identifier = protocolDecl.name.text + let strategyStructName = "\(identifier)CodableStrategy" + + return [ + DeclSyntax("typealias Polymorphic = PolymorphicValue<\(raw: strategyStructName)>"), + DeclSyntax("typealias OptionalPolymorphic = OptionalPolymorphicValue<\(raw: strategyStructName)>"), + DeclSyntax("typealias LossyOptionalPolymorphic = LossyOptionalPolymorphicValue<\(raw: strategyStructName)>"), + DeclSyntax("typealias PolymorphicArray = PolymorphicArrayValue<\(raw: strategyStructName)>"), + DeclSyntax("typealias OptionalPolymorphicArray = OptionalPolymorphicArrayValue<\(raw: strategyStructName)>"), + DeclSyntax("typealias PolymorphicLossyArray = PolymorphicLossyArrayValue<\(raw: strategyStructName)>"), + DeclSyntax("typealias DefaultEmptyPolymorphicArray = DefaultEmptyPolymorphicArrayValue<\(raw: strategyStructName)>"), + ] + } +} + +// MARK: - PeerMacro + +extension PolymorphicCodableStrategyProvidingMacro: PeerMacro { + public static func expansion( + of node: AttributeSyntax, + providingPeersOf declaration: some DeclSyntaxProtocol, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + guard let protocolDecl = declaration.as(ProtocolDeclSyntax.self) else { return [] } + guard let arguments = node.arguments?.as(LabeledExprListSyntax.self), let matchingTypes = SyntaxHelper.findArgument(named: "matchingTypes", in: arguments) @@ -80,39 +109,3 @@ public struct PolymorphicCodableStrategyProvidingMacro: PeerMacro { return protocolDecl.accessLevel.rawValue + " " } } - -extension PolymorphicCodableStrategyProvidingMacro: 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] { - guard let protocolDecl = declaration.as(ProtocolDeclSyntax.self) else { return [] } - - let accessModifier = accessModifier(from: protocolDecl) - let identifier = protocolDecl.name.text - let strategyStructName = "\(identifier)CodableStrategy" - - return [ - try ExtensionDeclSyntax( - """ - extension \(raw: identifier) { - \(raw: accessModifier)typealias Polymorphic = PolymorphicValue<\(raw: strategyStructName)> - \(raw: accessModifier)typealias OptionalPolymorphic = OptionalPolymorphicValue<\(raw: strategyStructName)> - \(raw: accessModifier)typealias LossyOptionalPolymorphic = LossyOptionalPolymorphicValue<\( - raw: strategyStructName - )> - \(raw: accessModifier)typealias PolymorphicArray = PolymorphicArrayValue<\(raw: strategyStructName)> - \(raw: accessModifier)typealias OptionalPolymorphicArray = OptionalPolymorphicArrayValue<\(raw: strategyStructName)> - \(raw: accessModifier)typealias PolymorphicLossyArray = PolymorphicLossyArrayValue<\(raw: strategyStructName)> - \(raw: accessModifier)typealias DefaultEmptyPolymorphicArray = DefaultEmptyPolymorphicArrayValue<\( - raw: strategyStructName - )> - } - """ - ), - ] - } -} diff --git a/Tests/KarrotCodableMacrosTests/PolymorphicCodableMacrosTests/PolymorphicCodableStrategyProvidingMacroTests.swift b/Tests/KarrotCodableMacrosTests/PolymorphicCodableMacrosTests/PolymorphicCodableStrategyProvidingMacroTests.swift index bd3236d..160b066 100644 --- a/Tests/KarrotCodableMacrosTests/PolymorphicCodableMacrosTests/PolymorphicCodableStrategyProvidingMacroTests.swift +++ b/Tests/KarrotCodableMacrosTests/PolymorphicCodableMacrosTests/PolymorphicCodableStrategyProvidingMacroTests.swift @@ -45,11 +45,24 @@ final class PolymorphicCodableStrategyProvidingMacroTests: XCTestCase { """, // when expandedSource: """ - public protocol Notice: Codable { var type: String { get } var title: String? { get } var description: String { get } + + typealias Polymorphic = PolymorphicValue + + typealias OptionalPolymorphic = OptionalPolymorphicValue + + typealias LossyOptionalPolymorphic = LossyOptionalPolymorphicValue + + typealias PolymorphicArray = PolymorphicArrayValue + + typealias OptionalPolymorphicArray = OptionalPolymorphicArrayValue + + typealias PolymorphicLossyArray = PolymorphicLossyArrayValue + + typealias DefaultEmptyPolymorphicArray = DefaultEmptyPolymorphicArrayValue } public struct NoticeCodableStrategy: PolymorphicCodableStrategy { @@ -72,16 +85,6 @@ final class PolymorphicCodableStrategyProvidingMacroTests: XCTestCase { ) } } - - extension Notice { - public typealias Polymorphic = PolymorphicValue - public typealias OptionalPolymorphic = OptionalPolymorphicValue - public typealias LossyOptionalPolymorphic = LossyOptionalPolymorphicValue - public typealias PolymorphicArray = PolymorphicArrayValue - public typealias OptionalPolymorphicArray = OptionalPolymorphicArrayValue - public typealias PolymorphicLossyArray = PolymorphicLossyArrayValue - public typealias DefaultEmptyPolymorphicArray = DefaultEmptyPolymorphicArrayValue - } """, macros: testMacros, indentationWidth: .spaces(2) @@ -114,6 +117,20 @@ final class PolymorphicCodableStrategyProvidingMacroTests: XCTestCase { var type: String { get } var title: String? { get } var description: String { get } + + typealias Polymorphic = PolymorphicValue + + typealias OptionalPolymorphic = OptionalPolymorphicValue + + typealias LossyOptionalPolymorphic = LossyOptionalPolymorphicValue + + typealias PolymorphicArray = PolymorphicArrayValue + + typealias OptionalPolymorphicArray = OptionalPolymorphicArrayValue + + typealias PolymorphicLossyArray = PolymorphicLossyArrayValue + + typealias DefaultEmptyPolymorphicArray = DefaultEmptyPolymorphicArrayValue } public struct NoticeCodableStrategy: PolymorphicCodableStrategy { @@ -136,16 +153,6 @@ final class PolymorphicCodableStrategyProvidingMacroTests: XCTestCase { ) } } - - extension Notice { - public typealias Polymorphic = PolymorphicValue - public typealias OptionalPolymorphic = OptionalPolymorphicValue - public typealias LossyOptionalPolymorphic = LossyOptionalPolymorphicValue - public typealias PolymorphicArray = PolymorphicArrayValue - public typealias OptionalPolymorphicArray = OptionalPolymorphicArrayValue - public typealias PolymorphicLossyArray = PolymorphicLossyArrayValue - public typealias DefaultEmptyPolymorphicArray = DefaultEmptyPolymorphicArrayValue - } """, macros: testMacros, indentationWidth: .spaces(2) @@ -216,15 +223,19 @@ final class PolymorphicCodableStrategyProvidingMacroTests: XCTestCase { var type: String var title: String? var description: String - } - extension Notice { typealias Polymorphic = PolymorphicValue + typealias OptionalPolymorphic = OptionalPolymorphicValue + typealias LossyOptionalPolymorphic = LossyOptionalPolymorphicValue + typealias PolymorphicArray = PolymorphicArrayValue + typealias OptionalPolymorphicArray = OptionalPolymorphicArrayValue + typealias PolymorphicLossyArray = PolymorphicLossyArrayValue + typealias DefaultEmptyPolymorphicArray = DefaultEmptyPolymorphicArrayValue } """,