Skip to content

Commit

Permalink
feat: add ability to set default values
Browse files Browse the repository at this point in the history
  • Loading branch information
elihwyma committed Nov 24, 2024
1 parent caec5c1 commit 22aa359
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 17 deletions.
4 changes: 2 additions & 2 deletions Sources/PugiSwift/Decoding/MacroDefinitions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
import Foundation

@attached(peer)
public macro Attribute(codingKey: String? = nil) = #externalMacro(module: "PugiSwiftMacros",
public macro Attribute(codingKey: String? = nil, default: Sendable? = nil) = #externalMacro(module: "PugiSwiftMacros",
type: "AttributeMacro")
@attached(peer)
public macro Element(codingKey: String? = nil, childrenCodingKey: String? = nil) = #externalMacro(module: "PugiSwiftMacros",
public macro Element(codingKey: String? = nil, childrenCodingKey: String? = nil, default: Sendable? = nil) = #externalMacro(module: "PugiSwiftMacros",
type: "ElementMacro")

@attached(extension, conformances: XMLDecodable, names: arbitrary)
Expand Down
4 changes: 3 additions & 1 deletion Sources/PugiSwiftDemo/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@ import PugiSwift
}

@Node struct Record {

let name: String
let list: Int?
@Element(default: 5) let list: Int
let color: Colours

}

@Node struct Records {
Expand Down
68 changes: 54 additions & 14 deletions Sources/PugiSwiftMacros/NodeMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public struct NodeMacro: ExtensionMacro {

var codingKey = propertyName
var childrenCodingKey: String? = nil
var defaultValue: String? = nil
var attribute = false

// Get the codingKey
Expand All @@ -82,20 +83,31 @@ public struct NodeMacro: ExtensionMacro {
if let _childCodingKey = expressions.first(where: { $0.label == "childrenCodingKey" }) {
childrenCodingKey = _childCodingKey.expr.asStringLiteral!.value!
}
if let _defaultValue = expressions.first(where: { $0.label == "default" }) {
defaultValue = _defaultValue.expr._syntax.description
}
}
if let xmlAttribute {
attribute = true
let expressions = xmlAttribute.attribute?.asMacroAttribute?.arguments ?? []
if let _codingKey = expressions.first(where: { $0.label == "codingKey" }) {
codingKey = _codingKey.expr.asStringLiteral!.value!
}
if let _defaultValue = expressions.first(where: { $0.label == "default" }) {
defaultValue = _defaultValue.expr._syntax.description
}
}

var optional = false
if case .optional = type {
optional = true
}

var optionalReplacement = "nil"
if let defaultValue {
optionalReplacement = defaultValue
}

if optional {
if attribute {
#if DEBUG
Expand All @@ -105,21 +117,21 @@ public struct NodeMacro: ExtensionMacro {
do {
self.\(raw: propertyName) = try .init(from: \(raw: nodeHelperName))
} catch {
self.\(raw: propertyName) = nil
self.\(raw: propertyName) = \(raw: optionalReplacement)
print("[🐞] Parsing error in \(raw: propertyName): \\(error.localizedDescription)")
}
} else {
self.\(raw: propertyName) = nil
self.\(raw: propertyName) = \(raw: optionalReplacement)
}
"""
)
#else
let code = CodeBlockItemSyntax(
"""
if let \(raw: nodeHelperName) = node.attribute(name: "\(raw: codingKey)") {
self.\(raw: propertyName) = try? .init(from: \(raw: nodeHelperName))
self.\(raw: propertyName) = (try? .init(from: \(raw: nodeHelperName))) ?? \(raw: optionalReplacement)
} else {
self.\(raw: propertyName) = nil
self.\(raw: propertyName) = \(raw: optionalReplacement)
}
"""
)
Expand Down Expand Up @@ -158,21 +170,21 @@ public struct NodeMacro: ExtensionMacro {
do {
self.\(raw: propertyName) = try .init(from: \(raw: nodeHelperName))
} catch {
self.\(raw: propertyName) = nil
self.\(raw: propertyName) = \(raw: optionalReplacement)
print("[🐞] Parsing error in \(raw: propertyName): \\(error.localizedDescription)")
}
} else {
self.\(raw: propertyName) = nil
self.\(raw: propertyName) = \(raw: optionalReplacement)
}
"""
)
#else
let code = CodeBlockItemSyntax(
"""
if let \(raw: nodeHelperName) = node.child(name: "\(raw: codingKey)") {
self.\(raw: propertyName) = try? .init(from: \(raw: nodeHelperName))
self.\(raw: propertyName) = (try? .init(from: \(raw: nodeHelperName))) ?? \(raw: optionalReplacement)
} else {
self.\(raw: propertyName) = nil
self.\(raw: propertyName) = \(raw: optionalReplacement)
}
"""
)
Expand Down Expand Up @@ -202,15 +214,43 @@ public struct NodeMacro: ExtensionMacro {
)
return [code]
}
let createHelper: CodeBlockItemSyntax
if attribute {
createHelper = CodeBlockItemSyntax("guard let \(raw: nodeHelperName) = node.attribute(name: \"\(raw: codingKey)\") else { throw .attributeNotFound(codingKey: \"\(raw: codingKey)\") }")

if let defaultValue {
if attribute {
let codeBlock = CodeBlockItemSyntax(
"""
if let \(raw: nodeHelperName) = node.attribute(name: \"\(raw: codingKey)\") {
self.\(raw: propertyName) = try .init(from: \(raw: nodeHelperName))
} else {
self.\(raw: propertyName) = \(raw: defaultValue)
}
"""
)
return [codeBlock]
} else {
let codeBlock = CodeBlockItemSyntax(
"""
if let \(raw: nodeHelperName) = node.child(name: \"\(raw: codingKey)\") {
self.\(raw: propertyName) = try .init(from: \(raw: nodeHelperName))
} else {
self.\(raw: propertyName) = \(raw: defaultValue)
}
"""
)
return [codeBlock]
}
} else {
createHelper = CodeBlockItemSyntax("guard let \(raw: nodeHelperName) = node.child(name: \"\(raw: codingKey)\") else { throw .keyNotFound(codingKey: \"\(raw: codingKey)\") }")
let createHelper: CodeBlockItemSyntax
if attribute {
createHelper = CodeBlockItemSyntax("guard let \(raw: nodeHelperName) = node.attribute(name: \"\(raw: codingKey)\") else { throw .attributeNotFound(codingKey: \"\(raw: codingKey)\") }")
} else {
createHelper = CodeBlockItemSyntax("guard let \(raw: nodeHelperName) = node.child(name: \"\(raw: codingKey)\") else { throw .keyNotFound(codingKey: \"\(raw: codingKey)\") }")
}
let assign = CodeBlockItemSyntax("self.\(raw: propertyName) = try .init(from: \(raw: nodeHelperName))")

return [createHelper, assign]
}
let assign = CodeBlockItemSyntax("self.\(raw: propertyName) = try .init(from: \(raw: nodeHelperName))")

return [createHelper, assign]
}
}

Expand Down

0 comments on commit 22aa359

Please sign in to comment.