From d68d337b47000bf1a916226702facb968fa5751d Mon Sep 17 00:00:00 2001 From: Casper Zandbergen Date: Thu, 24 Jul 2025 20:54:27 +0200 Subject: [PATCH 1/4] enum inferred raw value --- Sources/MacroToolkit/DeclGroup/Enum.swift | 13 ++- Sources/MacroToolkit/EnumCase.swift | 42 ++++++---- Sources/MacroToolkit/EnumCaseValue.swift | 1 + .../EnumRawRepresentableType.swift | 21 +++++ Tests/MacroToolkitTests/DeclGroupTests.swift | 80 +++++++++++++++++++ 5 files changed, 141 insertions(+), 16 deletions(-) create mode 100644 Sources/MacroToolkit/EnumRawRepresentableType.swift diff --git a/Sources/MacroToolkit/DeclGroup/Enum.swift b/Sources/MacroToolkit/DeclGroup/Enum.swift index c1c7e3f..5c184c0 100644 --- a/Sources/MacroToolkit/DeclGroup/Enum.swift +++ b/Sources/MacroToolkit/DeclGroup/Enum.swift @@ -10,6 +10,10 @@ public struct Enum: DeclGroupProtocol, RepresentableBySyntax { _syntax.name.withoutTrivia().text } + public var rawRepresentableType: EnumRawRepresentableType? { + EnumRawRepresentableType(possibleRawType: _syntax.inheritanceClause?.inheritedTypes.first) + } + /// Initializes an `Enum` instance with the given syntax node. /// /// - Parameter syntax: The syntax node representing the `enum` declaration. @@ -19,12 +23,17 @@ public struct Enum: DeclGroupProtocol, RepresentableBySyntax { /// The `enum`'s cases. public var cases: [EnumCase] { - _syntax.memberBlock.members + var lastSeen: EnumCase? + return _syntax.memberBlock.members .compactMap { member in member.decl.as(EnumCaseDeclSyntax.self) } .flatMap { syntax in - syntax.elements.map(EnumCase.init) + syntax.elements.map { + let next = EnumCase($0, rawRepresentableType: rawRepresentableType, precedingCase: lastSeen) + lastSeen = next + return next + } } } } diff --git a/Sources/MacroToolkit/EnumCase.swift b/Sources/MacroToolkit/EnumCase.swift index ff68dc7..4071fb3 100644 --- a/Sources/MacroToolkit/EnumCase.swift +++ b/Sources/MacroToolkit/EnumCase.swift @@ -4,27 +4,41 @@ import SwiftSyntax public struct EnumCase { public var _syntax: EnumCaseElementSyntax - public init(_ syntax: EnumCaseElementSyntax) { + public init(_ syntax: EnumCaseElementSyntax, rawRepresentableType: EnumRawRepresentableType? = nil, precedingCase: EnumCase? = nil) { _syntax = syntax + value = { + if let rawValue = _syntax.rawValue { + return .rawValue(rawValue) + } else if let associatedValue = _syntax.parameterClause { + let parameters = Array(associatedValue.parameters) + .map(EnumCaseAssociatedValueParameter.init) + return .associatedValue(parameters) + } else if let rawRepresentableType { + switch rawRepresentableType { + case .string: return .inferredRawValue(.init(value: "\"\(raw: _syntax.name.text)\"" as ExprSyntax)) + case .character: return nil // Characters cannot be inferred + case .number: + // Raw representable conformance is only synthesized when using integer literals (eg 1), + // not float literals (eg 1.0). + let previousValue: Int? = switch precedingCase?.value { + case .rawValue(let v), .inferredRawValue(let v): IntegerLiteral(v.value)?.value + default: nil + } + return .inferredRawValue(.init(value: "\(raw: (previousValue ?? -1) + 1)" as ExprSyntax)) + } + } else { + return nil + } + }() } /// The case's name public var identifier: String { _syntax.name.withoutTrivia().description } - - /// The value associated with the enum case (either associated or raw). - public var value: EnumCaseValue? { - if let rawValue = _syntax.rawValue { - return .rawValue(rawValue) - } else if let associatedValue = _syntax.parameterClause { - let parameters = Array(associatedValue.parameters) - .map(EnumCaseAssociatedValueParameter.init) - return .associatedValue(parameters) - } else { - return nil - } - } + + /// The value associated with the enum case (either associated, raw or inferred). + public var value: EnumCaseValue? public func withoutValue() -> Self { EnumCase(_syntax.with(\.rawValue, nil).with(\.parameterClause, nil)) diff --git a/Sources/MacroToolkit/EnumCaseValue.swift b/Sources/MacroToolkit/EnumCaseValue.swift index f213877..a362a83 100644 --- a/Sources/MacroToolkit/EnumCaseValue.swift +++ b/Sources/MacroToolkit/EnumCaseValue.swift @@ -4,4 +4,5 @@ import SwiftSyntax public enum EnumCaseValue { case associatedValue([EnumCaseAssociatedValueParameter]) case rawValue(InitializerClauseSyntax) + case inferredRawValue(InitializerClauseSyntax) } diff --git a/Sources/MacroToolkit/EnumRawRepresentableType.swift b/Sources/MacroToolkit/EnumRawRepresentableType.swift new file mode 100644 index 0000000..d827f62 --- /dev/null +++ b/Sources/MacroToolkit/EnumRawRepresentableType.swift @@ -0,0 +1,21 @@ +import SwiftSyntax + +/// Enum raw values can be strings, characters, or any of the integer or floating-point number types. +public enum EnumRawRepresentableType { + case string + case character + case number + + init?(possibleRawType syntax: InheritedTypeSyntax?) { + switch syntax?.type.as(IdentifierTypeSyntax.self)?.name.text { + case "String": self = .string + case "Character": self = .character + case "Int", "Int8", "Int16", "Int32", "Int64", "Int128", + "UInt", "UInt8", "UInt16", "UInt32", "UInt64", "UInt128", + "Float", "Float16", "Float32", "Float64", + "Double", "CGFloat", "NSNumber": + self = .number + default: return nil + } + } +} diff --git a/Tests/MacroToolkitTests/DeclGroupTests.swift b/Tests/MacroToolkitTests/DeclGroupTests.swift index 6d22fa2..20942dc 100644 --- a/Tests/MacroToolkitTests/DeclGroupTests.swift +++ b/Tests/MacroToolkitTests/DeclGroupTests.swift @@ -160,4 +160,84 @@ final class DeclGroupTests: XCTestCase { XCTAssertEqual(testClass.accessLevel, .public) XCTAssertEqual(testClass.declarationContext, nil) } + + func testEnumRawTypeInferredValueString() throws { + let decl: DeclSyntax = """ + enum TestEnum: String { case caseOne, caseTwo, caseThree = "case3" } + """ + let enumDecl = decl.as(EnumDeclSyntax.self)! + let testEnum = Enum(enumDecl) + + XCTAssertEqual(testEnum.identifier, "TestEnum") + XCTAssertEqual(testEnum.members.count, 1) + XCTAssertEqual(testEnum.cases.count, 3) + XCTAssertEqual(testEnum.rawRepresentableType, .string) + let literals = testEnum.cases.map { + switch $0.value { + case .rawValue(let i), .inferredRawValue(let i): return StringLiteral(i.value)?.value + default: return nil + } + } + XCTAssertEqual(literals, ["caseOne", "caseTwo", "case3"]) + } + + func testEnumRawTypeInferredValueInt() throws { + let decl: DeclSyntax = """ + enum TestEnum: Int { case caseOne = 1, caseTwo, caseThree } + """ + let enumDecl = decl.as(EnumDeclSyntax.self)! + let testEnum = Enum(enumDecl) + + XCTAssertEqual(testEnum.identifier, "TestEnum") + XCTAssertEqual(testEnum.members.count, 1) + XCTAssertEqual(testEnum.cases.count, 3) + XCTAssertEqual(testEnum.rawRepresentableType, .number) + let literals = testEnum.cases.map { + switch $0.value { + case .rawValue(let i), .inferredRawValue(let i): return IntegerLiteral(i.value)?.value + default: return nil + } + } + XCTAssertEqual(literals, [1, 2, 3]) + } + + func testEnumRawTypeInferredValueNegativeInt() throws { + let decl: DeclSyntax = """ + enum TestEnum: Int { case a = -1, b, c } + """ + let enumDecl = decl.as(EnumDeclSyntax.self)! + let testEnum = Enum(enumDecl) + + XCTAssertEqual(testEnum.identifier, "TestEnum") + XCTAssertEqual(testEnum.members.count, 1) + XCTAssertEqual(testEnum.cases.count, 3) + XCTAssertEqual(testEnum.rawRepresentableType, .number) + let literals = testEnum.cases.map { + switch $0.value { + case .rawValue(let i), .inferredRawValue(let i): return IntegerLiteral(i.value)?.value + default: return nil + } + } + XCTAssertEqual(literals, [-1, 0, 1]) + } + + func testEnumRawTypeInferredValueDouble() throws { + let decl: DeclSyntax = """ + enum TestEnum: Double { case caseOne = 1, caseTwo, caseThree } + """ + let enumDecl = decl.as(EnumDeclSyntax.self)! + let testEnum = Enum(enumDecl) + + XCTAssertEqual(testEnum.identifier, "TestEnum") + XCTAssertEqual(testEnum.members.count, 1) + XCTAssertEqual(testEnum.cases.count, 3) + XCTAssertEqual(testEnum.rawRepresentableType, .number) + let literals = testEnum.cases.map { + switch $0.value { + case .rawValue(let i), .inferredRawValue(let i): return IntegerLiteral(i.value)?.value + default: return nil + } + } + XCTAssertEqual(literals, [1, 2, 3]) + } } From f8d1856c869cb336002bb1a06db56a108e19fe5e Mon Sep 17 00:00:00 2001 From: Casper Zandbergen Date: Sun, 27 Jul 2025 12:23:22 +0200 Subject: [PATCH 2/4] applied feedback and added more convenience properties and tests --- Sources/MacroToolkit/EnumCase.swift | 63 +++++++++++------ .../EnumRawRepresentableType.swift | 16 ++--- Tests/MacroToolkitTests/DeclGroupTests.swift | 70 +++++++++++-------- 3 files changed, 89 insertions(+), 60 deletions(-) diff --git a/Sources/MacroToolkit/EnumCase.swift b/Sources/MacroToolkit/EnumCase.swift index 4071fb3..6103811 100644 --- a/Sources/MacroToolkit/EnumCase.swift +++ b/Sources/MacroToolkit/EnumCase.swift @@ -6,30 +6,24 @@ public struct EnumCase { public init(_ syntax: EnumCaseElementSyntax, rawRepresentableType: EnumRawRepresentableType? = nil, precedingCase: EnumCase? = nil) { _syntax = syntax - value = { - if let rawValue = _syntax.rawValue { - return .rawValue(rawValue) - } else if let associatedValue = _syntax.parameterClause { - let parameters = Array(associatedValue.parameters) - .map(EnumCaseAssociatedValueParameter.init) - return .associatedValue(parameters) - } else if let rawRepresentableType { - switch rawRepresentableType { - case .string: return .inferredRawValue(.init(value: "\"\(raw: _syntax.name.text)\"" as ExprSyntax)) - case .character: return nil // Characters cannot be inferred - case .number: - // Raw representable conformance is only synthesized when using integer literals (eg 1), - // not float literals (eg 1.0). - let previousValue: Int? = switch precedingCase?.value { - case .rawValue(let v), .inferredRawValue(let v): IntegerLiteral(v.value)?.value - default: nil - } - return .inferredRawValue(.init(value: "\(raw: (previousValue ?? -1) + 1)" as ExprSyntax)) - } - } else { - return nil + value = if let rawValue = _syntax.rawValue { + .rawValue(rawValue) + } else if let associatedValue = _syntax.parameterClause { + .associatedValue(Array(associatedValue.parameters).map(EnumCaseAssociatedValueParameter.init)) + } else if let rawRepresentableType { + switch rawRepresentableType { + case .string: .inferredRawValue(.init(value: "\"\(raw: _syntax.name.text)\"" as ExprSyntax)) + case .character: .none // Characters cannot be inferred + case .number: .inferredRawValue(.init(value: "\(raw: (previousValue() ?? -1) + 1)" as ExprSyntax)) } - }() + } else { + nil + } + + /// Raw representable conformance is only synthesized when using integer literals (eg 1), not float literals (eg 1.0). + func previousValue() -> Int? { + precedingCase?.rawValue.flatMap(IntegerLiteral.init)?.value + } } /// The case's name @@ -39,6 +33,29 @@ public struct EnumCase { /// The value associated with the enum case (either associated, raw or inferred). public var value: EnumCaseValue? + + /// Helper that gets the associated values from `EnumCase.value` or returns an empty array. + public var associatedValues: [EnumCaseAssociatedValueParameter] { + switch value { + case .associatedValue(let values): values + default: [] + } + } + + /// Helper that gets the raw or inferred raw value from `EnumCase.value` or returns nil. + public var rawValue: ExprSyntax? { + switch value { + case .rawValue(let initializer), .inferredRawValue(let initializer): initializer.value + default: nil + } + } + + /// Helper that gets the raw or inferred raw value text, eg "value", 1, or 1.0. + public var rawValueText: String? { + rawValue.flatMap(StringLiteral.init)?.value.map { "\"\($0)\"" } ?? + rawValue.flatMap(IntegerLiteral.init)?.value.description ?? + rawValue.flatMap(FloatLiteral.init)?.value.description + } public func withoutValue() -> Self { EnumCase(_syntax.with(\.rawValue, nil).with(\.parameterClause, nil)) diff --git a/Sources/MacroToolkit/EnumRawRepresentableType.swift b/Sources/MacroToolkit/EnumRawRepresentableType.swift index d827f62..19a7f73 100644 --- a/Sources/MacroToolkit/EnumRawRepresentableType.swift +++ b/Sources/MacroToolkit/EnumRawRepresentableType.swift @@ -8,14 +8,14 @@ public enum EnumRawRepresentableType { init?(possibleRawType syntax: InheritedTypeSyntax?) { switch syntax?.type.as(IdentifierTypeSyntax.self)?.name.text { - case "String": self = .string - case "Character": self = .character - case "Int", "Int8", "Int16", "Int32", "Int64", "Int128", - "UInt", "UInt8", "UInt16", "UInt32", "UInt64", "UInt128", - "Float", "Float16", "Float32", "Float64", - "Double", "CGFloat", "NSNumber": - self = .number - default: return nil + case "String": self = .string + case "Character": self = .character + case "Int", "Int8", "Int16", "Int32", "Int64", "Int128", + "UInt", "UInt8", "UInt16", "UInt32", "UInt64", "UInt128", + "Float", "Float16", "Float32", "Float64", + "Double", "CGFloat", "NSNumber": + self = .number + default: return nil } } } diff --git a/Tests/MacroToolkitTests/DeclGroupTests.swift b/Tests/MacroToolkitTests/DeclGroupTests.swift index 20942dc..18c2438 100644 --- a/Tests/MacroToolkitTests/DeclGroupTests.swift +++ b/Tests/MacroToolkitTests/DeclGroupTests.swift @@ -172,13 +172,7 @@ final class DeclGroupTests: XCTestCase { XCTAssertEqual(testEnum.members.count, 1) XCTAssertEqual(testEnum.cases.count, 3) XCTAssertEqual(testEnum.rawRepresentableType, .string) - let literals = testEnum.cases.map { - switch $0.value { - case .rawValue(let i), .inferredRawValue(let i): return StringLiteral(i.value)?.value - default: return nil - } - } - XCTAssertEqual(literals, ["caseOne", "caseTwo", "case3"]) + XCTAssertEqual(testEnum.cases.map(\.rawValueText), [#""caseOne""#, #""caseTwo""#, #""case3""#]) } func testEnumRawTypeInferredValueInt() throws { @@ -192,13 +186,7 @@ final class DeclGroupTests: XCTestCase { XCTAssertEqual(testEnum.members.count, 1) XCTAssertEqual(testEnum.cases.count, 3) XCTAssertEqual(testEnum.rawRepresentableType, .number) - let literals = testEnum.cases.map { - switch $0.value { - case .rawValue(let i), .inferredRawValue(let i): return IntegerLiteral(i.value)?.value - default: return nil - } - } - XCTAssertEqual(literals, [1, 2, 3]) + XCTAssertEqual(testEnum.cases.map(\.rawValueText), ["1", "2", "3"]) } func testEnumRawTypeInferredValueNegativeInt() throws { @@ -212,18 +200,12 @@ final class DeclGroupTests: XCTestCase { XCTAssertEqual(testEnum.members.count, 1) XCTAssertEqual(testEnum.cases.count, 3) XCTAssertEqual(testEnum.rawRepresentableType, .number) - let literals = testEnum.cases.map { - switch $0.value { - case .rawValue(let i), .inferredRawValue(let i): return IntegerLiteral(i.value)?.value - default: return nil - } - } - XCTAssertEqual(literals, [-1, 0, 1]) + XCTAssertEqual(testEnum.cases.map(\.rawValueText), ["-1", "0", "1"]) } - func testEnumRawTypeInferredValueDouble() throws { + func testEnumRawTypeInferredValueIntMiddle() throws { let decl: DeclSyntax = """ - enum TestEnum: Double { case caseOne = 1, caseTwo, caseThree } + enum TestEnum: Int { case a, b = 5, c } """ let enumDecl = decl.as(EnumDeclSyntax.self)! let testEnum = Enum(enumDecl) @@ -232,12 +214,42 @@ final class DeclGroupTests: XCTestCase { XCTAssertEqual(testEnum.members.count, 1) XCTAssertEqual(testEnum.cases.count, 3) XCTAssertEqual(testEnum.rawRepresentableType, .number) - let literals = testEnum.cases.map { - switch $0.value { - case .rawValue(let i), .inferredRawValue(let i): return IntegerLiteral(i.value)?.value - default: return nil + XCTAssertEqual(testEnum.cases.map(\.rawValueText), ["0", "5", "6"]) + } + + func testEnumRawTypeInferredValueDouble() throws { + let decl: DeclSyntax = """ + enum TestEnum: Double { + case caseOne = 1 + case caseTwo + case caseThree } - } - XCTAssertEqual(literals, [1, 2, 3]) + """ + let enumDecl = decl.as(EnumDeclSyntax.self)! + let testEnum = Enum(enumDecl) + + XCTAssertEqual(testEnum.identifier, "TestEnum") + XCTAssertEqual(testEnum.members.count, 3) + XCTAssertEqual(testEnum.cases.count, 3) + XCTAssertEqual(testEnum.rawRepresentableType, .number) + XCTAssertEqual(testEnum.cases.map(\.rawValueText), ["1", "2", "3"]) + } + + func testEnumRawTypeInferredValueDoubleLiteral() throws { + let decl: DeclSyntax = """ + enum TestEnum: Double { + case caseOne = 1.1 + case caseTwo = 1.2 + case caseThree = 1.3 + } + """ + let enumDecl = decl.as(EnumDeclSyntax.self)! + let testEnum = Enum(enumDecl) + + XCTAssertEqual(testEnum.identifier, "TestEnum") + XCTAssertEqual(testEnum.members.count, 3) + XCTAssertEqual(testEnum.cases.count, 3) + XCTAssertEqual(testEnum.rawRepresentableType, .number) + XCTAssertEqual(testEnum.cases.map(\.rawValueText), ["1.1", "1.2", "1.3"]) } } From b05e9811f251a63b848cb103bc95eb45a77440fd Mon Sep 17 00:00:00 2001 From: Casper Zandbergen Date: Sun, 27 Jul 2025 12:44:26 +0200 Subject: [PATCH 3/4] distinct integer and float type for enum raw representable type --- Sources/MacroToolkit/EnumCase.swift | 4 ++-- .../EnumRawRepresentableType.swift | 23 +++++++++++-------- Tests/MacroToolkitTests/DeclGroupTests.swift | 12 +++++----- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Sources/MacroToolkit/EnumCase.swift b/Sources/MacroToolkit/EnumCase.swift index 6103811..534ec68 100644 --- a/Sources/MacroToolkit/EnumCase.swift +++ b/Sources/MacroToolkit/EnumCase.swift @@ -13,8 +13,8 @@ public struct EnumCase { } else if let rawRepresentableType { switch rawRepresentableType { case .string: .inferredRawValue(.init(value: "\"\(raw: _syntax.name.text)\"" as ExprSyntax)) - case .character: .none // Characters cannot be inferred - case .number: .inferredRawValue(.init(value: "\(raw: (previousValue() ?? -1) + 1)" as ExprSyntax)) + case .character: nil // Characters cannot be inferred + case .integer, .float: .inferredRawValue(.init(value: "\(raw: (previousValue() ?? -1) + 1)" as ExprSyntax)) } } else { nil diff --git a/Sources/MacroToolkit/EnumRawRepresentableType.swift b/Sources/MacroToolkit/EnumRawRepresentableType.swift index 19a7f73..baef13e 100644 --- a/Sources/MacroToolkit/EnumRawRepresentableType.swift +++ b/Sources/MacroToolkit/EnumRawRepresentableType.swift @@ -2,19 +2,24 @@ import SwiftSyntax /// Enum raw values can be strings, characters, or any of the integer or floating-point number types. public enum EnumRawRepresentableType { - case string - case character - case number + case string(syntax: IdentifierTypeSyntax) + case character(syntax: IdentifierTypeSyntax) + case integer(syntax: IdentifierTypeSyntax) + case float(syntax: IdentifierTypeSyntax) init?(possibleRawType syntax: InheritedTypeSyntax?) { - switch syntax?.type.as(IdentifierTypeSyntax.self)?.name.text { - case "String": self = .string - case "Character": self = .character + guard let type = syntax?.type.as(IdentifierTypeSyntax.self) else { return nil } + switch type.name.text { + case "String", "NSString": + self = .string(syntax: type) + case "Character": + self = .character(syntax: type) case "Int", "Int8", "Int16", "Int32", "Int64", "Int128", - "UInt", "UInt8", "UInt16", "UInt32", "UInt64", "UInt128", - "Float", "Float16", "Float32", "Float64", + "UInt", "UInt8", "UInt16", "UInt32", "UInt64", "UInt128": + self = .integer(syntax: type) + case "Float", "Float16", "Float32", "Float64", "Double", "CGFloat", "NSNumber": - self = .number + self = .float(syntax: type) default: return nil } } diff --git a/Tests/MacroToolkitTests/DeclGroupTests.swift b/Tests/MacroToolkitTests/DeclGroupTests.swift index 18c2438..838e69d 100644 --- a/Tests/MacroToolkitTests/DeclGroupTests.swift +++ b/Tests/MacroToolkitTests/DeclGroupTests.swift @@ -171,7 +171,7 @@ final class DeclGroupTests: XCTestCase { XCTAssertEqual(testEnum.identifier, "TestEnum") XCTAssertEqual(testEnum.members.count, 1) XCTAssertEqual(testEnum.cases.count, 3) - XCTAssertEqual(testEnum.rawRepresentableType, .string) + guard case .string = testEnum.rawRepresentableType else { return XCTFail() } XCTAssertEqual(testEnum.cases.map(\.rawValueText), [#""caseOne""#, #""caseTwo""#, #""case3""#]) } @@ -185,7 +185,7 @@ final class DeclGroupTests: XCTestCase { XCTAssertEqual(testEnum.identifier, "TestEnum") XCTAssertEqual(testEnum.members.count, 1) XCTAssertEqual(testEnum.cases.count, 3) - XCTAssertEqual(testEnum.rawRepresentableType, .number) + guard case .integer = testEnum.rawRepresentableType else { return XCTFail() } XCTAssertEqual(testEnum.cases.map(\.rawValueText), ["1", "2", "3"]) } @@ -199,7 +199,7 @@ final class DeclGroupTests: XCTestCase { XCTAssertEqual(testEnum.identifier, "TestEnum") XCTAssertEqual(testEnum.members.count, 1) XCTAssertEqual(testEnum.cases.count, 3) - XCTAssertEqual(testEnum.rawRepresentableType, .number) + guard case .integer = testEnum.rawRepresentableType else { return XCTFail() } XCTAssertEqual(testEnum.cases.map(\.rawValueText), ["-1", "0", "1"]) } @@ -213,7 +213,7 @@ final class DeclGroupTests: XCTestCase { XCTAssertEqual(testEnum.identifier, "TestEnum") XCTAssertEqual(testEnum.members.count, 1) XCTAssertEqual(testEnum.cases.count, 3) - XCTAssertEqual(testEnum.rawRepresentableType, .number) + guard case .integer = testEnum.rawRepresentableType else { return XCTFail() } XCTAssertEqual(testEnum.cases.map(\.rawValueText), ["0", "5", "6"]) } @@ -231,7 +231,7 @@ final class DeclGroupTests: XCTestCase { XCTAssertEqual(testEnum.identifier, "TestEnum") XCTAssertEqual(testEnum.members.count, 3) XCTAssertEqual(testEnum.cases.count, 3) - XCTAssertEqual(testEnum.rawRepresentableType, .number) + guard case .float = testEnum.rawRepresentableType else { return XCTFail() } XCTAssertEqual(testEnum.cases.map(\.rawValueText), ["1", "2", "3"]) } @@ -249,7 +249,7 @@ final class DeclGroupTests: XCTestCase { XCTAssertEqual(testEnum.identifier, "TestEnum") XCTAssertEqual(testEnum.members.count, 3) XCTAssertEqual(testEnum.cases.count, 3) - XCTAssertEqual(testEnum.rawRepresentableType, .number) + guard case .float = testEnum.rawRepresentableType else { return XCTFail() } XCTAssertEqual(testEnum.cases.map(\.rawValueText), ["1.1", "1.2", "1.3"]) } } From 42f9e9a55a99f9c624068872af4d1dc0d85e2697 Mon Sep 17 00:00:00 2001 From: Casper Zandbergen Date: Sun, 27 Jul 2025 12:45:59 +0200 Subject: [PATCH 4/4] rename case --- Sources/MacroToolkit/EnumCase.swift | 2 +- Sources/MacroToolkit/EnumRawRepresentableType.swift | 4 ++-- Tests/MacroToolkitTests/DeclGroupTests.swift | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/MacroToolkit/EnumCase.swift b/Sources/MacroToolkit/EnumCase.swift index 534ec68..825ee89 100644 --- a/Sources/MacroToolkit/EnumCase.swift +++ b/Sources/MacroToolkit/EnumCase.swift @@ -14,7 +14,7 @@ public struct EnumCase { switch rawRepresentableType { case .string: .inferredRawValue(.init(value: "\"\(raw: _syntax.name.text)\"" as ExprSyntax)) case .character: nil // Characters cannot be inferred - case .integer, .float: .inferredRawValue(.init(value: "\(raw: (previousValue() ?? -1) + 1)" as ExprSyntax)) + case .integer, .floatingPoint: .inferredRawValue(.init(value: "\(raw: (previousValue() ?? -1) + 1)" as ExprSyntax)) } } else { nil diff --git a/Sources/MacroToolkit/EnumRawRepresentableType.swift b/Sources/MacroToolkit/EnumRawRepresentableType.swift index baef13e..6b9d8e1 100644 --- a/Sources/MacroToolkit/EnumRawRepresentableType.swift +++ b/Sources/MacroToolkit/EnumRawRepresentableType.swift @@ -5,7 +5,7 @@ public enum EnumRawRepresentableType { case string(syntax: IdentifierTypeSyntax) case character(syntax: IdentifierTypeSyntax) case integer(syntax: IdentifierTypeSyntax) - case float(syntax: IdentifierTypeSyntax) + case floatingPoint(syntax: IdentifierTypeSyntax) init?(possibleRawType syntax: InheritedTypeSyntax?) { guard let type = syntax?.type.as(IdentifierTypeSyntax.self) else { return nil } @@ -19,7 +19,7 @@ public enum EnumRawRepresentableType { self = .integer(syntax: type) case "Float", "Float16", "Float32", "Float64", "Double", "CGFloat", "NSNumber": - self = .float(syntax: type) + self = .floatingPoint(syntax: type) default: return nil } } diff --git a/Tests/MacroToolkitTests/DeclGroupTests.swift b/Tests/MacroToolkitTests/DeclGroupTests.swift index 838e69d..30f5b42 100644 --- a/Tests/MacroToolkitTests/DeclGroupTests.swift +++ b/Tests/MacroToolkitTests/DeclGroupTests.swift @@ -231,7 +231,7 @@ final class DeclGroupTests: XCTestCase { XCTAssertEqual(testEnum.identifier, "TestEnum") XCTAssertEqual(testEnum.members.count, 3) XCTAssertEqual(testEnum.cases.count, 3) - guard case .float = testEnum.rawRepresentableType else { return XCTFail() } + guard case .floatingPoint = testEnum.rawRepresentableType else { return XCTFail() } XCTAssertEqual(testEnum.cases.map(\.rawValueText), ["1", "2", "3"]) } @@ -249,7 +249,7 @@ final class DeclGroupTests: XCTestCase { XCTAssertEqual(testEnum.identifier, "TestEnum") XCTAssertEqual(testEnum.members.count, 3) XCTAssertEqual(testEnum.cases.count, 3) - guard case .float = testEnum.rawRepresentableType else { return XCTFail() } + guard case .floatingPoint = testEnum.rawRepresentableType else { return XCTFail() } XCTAssertEqual(testEnum.cases.map(\.rawValueText), ["1.1", "1.2", "1.3"]) } }