Skip to content

Commit

Permalink
Added new codable for StringOrDouble
Browse files Browse the repository at this point in the history
  • Loading branch information
christiancabarrocas committed Oct 23, 2024
1 parent 51bb99c commit c937fed
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Sources/SageSwiftKit/CodableMacros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public macro CustomCodable(nestedProperty: String? = nil) = #externalMacro(modul
@attached(peer)
public macro StringOrInt() = #externalMacro(module: "SageSwiftKitMacros", type: "StringOrInt")

@attached(peer)
public macro StringOrDouble() = #externalMacro(module: "SageSwiftKitMacros", type: "StringOrDouble")

@attached(peer)
public macro StringToDouble() = #externalMacro(module: "SageSwiftKitMacros", type: "StringToDouble")

Expand Down
3 changes: 3 additions & 0 deletions Sources/SageSwiftKitClient/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ struct PlayingObject {

@StringOrInt
var value: String?

@StringOrDouble
var sum: String?

@CustomURL
var createdOn: URL?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ enum DecodingAttribute: Identifiable, Equatable {
case date(AttributeSyntax)
case url(AttributeSyntax)
case stringOrInt(AttributeSyntax)
case stringOrDouble(AttributeSyntax)
case stringToDouble(AttributeSyntax)

var id: String {
Expand All @@ -23,6 +24,8 @@ enum DecodingAttribute: Identifiable, Equatable {
return String(describing: CustomURL.self)
case .stringOrInt:
return String(describing: StringOrInt.self)
case .stringOrDouble:
return String(describing: StringOrDouble.self)
case .stringToDouble:
return String(describing: StringToDouble.self)
}
Expand All @@ -38,6 +41,8 @@ enum DecodingAttribute: Identifiable, Equatable {
return attributeSyntax
case .stringOrInt(let attributeSyntax):
return attributeSyntax
case .stringOrDouble(let attributeSyntax):
return attributeSyntax
case .stringToDouble(let attributeSyntax):
return attributeSyntax
}
Expand Down Expand Up @@ -87,6 +92,10 @@ struct DecodeVariableBuild {
return .stringOrInt(variableAttribute)
}

if variableAttribute.adapter.name == String(describing: StringOrDouble.self) {
return .stringOrDouble(variableAttribute)
}

if variableAttribute.adapter.name == String(describing: StringToDouble.self) {
return .stringToDouble(variableAttribute)
}
Expand All @@ -112,6 +121,10 @@ struct DecodeVariableBuild {
return buildStringOrInt(attribute: attribute)
}

if let attribute = variableDecodingAttributes.getAttribute(macro: StringOrDouble.self)?.attribute {
return buildStringOrDouble(attribute: attribute)
}

if let attribute = variableDecodingAttributes.getAttribute(macro: StringToDouble.self)?.attribute {
return buildStringToDouble(attribute: attribute)
}
Expand Down Expand Up @@ -207,6 +220,41 @@ struct DecodeVariableBuild {
return .init(otherBuilder: ifBuilder)
}

func buildStringOrDouble(attribute: AttributeSyntax) -> CodeBlockItemSyntaxBuilder {
guard type == "String" else {
return buildBasicDecode()
}

let conditionalName = "tmp"+varName.capitalized

let ifBody: [CodeBlockItemSyntaxBuilder] = [
.init(code: "\(varName) = \(conditionalName)")
]

let elseIfBody: [CodeBlockItemSyntaxBuilder] = [
.init(code: "\(varName) = String(\(conditionalName))")
]

let elseBody: [CodeBlockItemSyntaxBuilder] = [
.init(code: "\(varName) = nil")
]

let elseIfBuilder = IfExprSyntaxBuilder(
condition: "if let \(conditionalName) = try? container.decode(Double.self, forKey: .\(varName))",
body: elseIfBody,
elseBody: elseBody
)
let elseIfCode = CodeBlockItemSyntaxBuilder.init(otherBuilder: elseIfBuilder)

let ifBuilder = IfExprSyntaxBuilder(
condition: "if let \(conditionalName) = try? container.decode(String.self, forKey: .\(varName))",
body: ifBody,
elseBody: [elseIfCode]
)

return .init(otherBuilder: ifBuilder)
}

func buildStringToDouble(attribute: AttributeSyntax) -> CodeBlockItemSyntaxBuilder {

guard type == "Double" else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct CobableMacros: CompilerPlugin {
CustomDate.self,
CustomURL.self,
StringOrInt.self,
StringOrDouble.self,
StringToDouble.self
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ public enum StringOrInt: PeerMacro {
}
}

public enum StringOrDouble: PeerMacro {
public static func expansion(of node: SwiftSyntax.AttributeSyntax, providingPeersOf declaration: some SwiftSyntax.DeclSyntaxProtocol, in context: some SwiftSyntaxMacros.MacroExpansionContext) throws -> [SwiftSyntax.DeclSyntax] {
[]
}
}

public enum StringToDouble: PeerMacro {
public static func expansion(of node: SwiftSyntax.AttributeSyntax, providingPeersOf declaration: some SwiftSyntax.DeclSyntaxProtocol, in context: some SwiftSyntaxMacros.MacroExpansionContext) throws -> [SwiftSyntax.DeclSyntax] {
[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,50 @@ final class CustomDecodableTests: XCTestCase {
)
#else
throw XCTSkip("macros are only supported when running tests for the host platform")
#endif
}

func testStringOrDouble() throws {
#if canImport(SageSwiftKitMacros)
assertMacroExpansion(
"""
@CustomCodable
struct PlayingObject {
@StringOrDouble
var value: String
}
""",
expandedSource: """
struct PlayingObject {
var value: String
enum CodingKeys: String, CodingKey {
case value
}
public init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let tmpValue = try? container.decode(String.self, forKey: .value) {
value = tmpValue
} else {
if let tmpValue = try? container.decode(Double.self, forKey: .value) {
value = String(tmpValue)
} else {
value = nil
}
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(value, forKey: .value)
}
}
""",
macros: codableMacros
)
#else
throw XCTSkip("macros are only supported when running tests for the host platform")
#endif
}
}

0 comments on commit c937fed

Please sign in to comment.