Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e2b159e
Update swift.yml
drekka Nov 17, 2024
ef8a6c2
Update swift.yml
drekka Nov 18, 2024
e861577
Update swift.yml
drekka Nov 18, 2024
5e04eb8
Update swift.yml
drekka Nov 18, 2024
91fecad
Removing all file header comments
drekka Nov 18, 2024
891829e
wip
drekka Nov 18, 2024
384e3c9
Converting to Swift Testing
drekka Nov 19, 2024
45eed2d
Update swift.yml
drekka Nov 19, 2024
718c520
Update swift.yml
drekka Nov 19, 2024
e036149
Update swift.yml
drekka Nov 19, 2024
fbbc72a
Update swift.yml
drekka Nov 19, 2024
72e4429
Update swift.yml
drekka Nov 19, 2024
a26480c
Update swift.yml
drekka Nov 20, 2024
96b6525
Switching from Nimble to Swift Testing
drekka Nov 20, 2024
5d39100
Merge branch 'develop' of https://github.com/drekka/DayType into develop
drekka Nov 20, 2024
feff7a2
Moving protocol conformance and fixing tests
drekka Nov 20, 2024
5610fbc
Update swift.yml
drekka Nov 20, 2024
eceef57
Update swift.yml
drekka Nov 20, 2024
579f9e3
Replacing epoch factor with boolean.
drekka Nov 23, 2024
c320f0c
Merge branch 'develop' of https://github.com/drekka/DayType into develop
drekka Nov 23, 2024
93fdb1f
WiP
drekka Dec 6, 2024
68069e3
Moving files
drekka Dec 8, 2024
9c9d53d
Refactoring property wrappers
drekka Apr 10, 2025
bfb3f75
New property wrapper for DayString
drekka May 11, 2025
7fb5ca9
Adjusting function calls.
drekka May 11, 2025
58ff334
Adding new epoch implementation
drekka May 12, 2025
14f7707
ISO8601 wrappers
drekka May 12, 2025
c116a30
Updating read me.
drekka May 13, 2025
273ea69
Merge branch 'main' into develop
drekka May 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/swift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ jobs:
- run: swift test --enable-code-coverage
- uses: drekka/swift-coverage-action@v1
with:
coverage: 90
show-all-files: true
98 changes: 98 additions & 0 deletions .swiftpm/xcode/xcshareddata/xcschemes/DayType-Package.xcscheme
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DayType"
BuildableName = "DayType"
BlueprintName = "DayType"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DayTypeMacros"
BuildableName = "DayTypeMacros"
BlueprintName = "DayTypeMacros"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:DayType-Package.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DayTypeTests"
BuildableName = "DayTypeTests"
BlueprintName = "DayTypeTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DayType"
BuildableName = "DayType"
BlueprintName = "DayType"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
67 changes: 67 additions & 0 deletions .swiftpm/xcode/xcshareddata/xcschemes/DayTypeMacros.xcscheme
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DayTypeMacros"
BuildableName = "DayTypeMacros"
BlueprintName = "DayTypeMacros"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DayTypeMacros"
BuildableName = "DayTypeMacros"
BlueprintName = "DayTypeMacros"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
24 changes: 24 additions & 0 deletions DayType-Package.xctestplan
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"configurations" : [
{
"id" : "F28B9C65-0AA9-4599-8E55-40AEEF5A8B41",
"name" : "Test Scheme Action",
"options" : {

}
}
],
"defaultOptions" : {

},
"testTargets" : [
{
"target" : {
"containerPath" : "container:",
"identifier" : "DayTypeTests",
"name" : "DayTypeTests"
}
}
],
"version" : 1
}
56 changes: 56 additions & 0 deletions Macros/Implementations/EpochPropertyWrapperMacro.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import SwiftDiagnostics
import SwiftSyntax
import SwiftSyntaxMacros

struct EpochPropertyWrapperMacro: MemberMacro {

static func expansion(
of node: AttributeSyntax,
providingMembersOf _: some DeclGroupSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {

guard let typeName = node.arguments?.stringArgumentValue("typeName"),
let milliseconds = node.arguments?.argumentValue("milliseconds") else {
context.diagnose(Diagnostic(
node: node, message: MacroExpansionErrorMessage("typeName or milliseconds argument not supplied. Passed arguments \(node.arguments?.description ?? "")")
))
return []
}

let withNullableImplementation = (node.arguments?.argumentValue("withNullableImplementation") ?? "true") == "true"

return [
DeclSyntax(stringLiteral: propertyWrapper(name: typeName, milliseconds: milliseconds, withNullableImplementation: withNullableImplementation)),
]
}

private static func propertyWrapper(name: String, milliseconds: String, withNullableImplementation: Bool) -> String {
let writeNulls = withNullableImplementation ? "false" : "true"
return """
@propertyWrapper
public struct \(name): Codable {

\(withNullableImplementation ? propertyWrapper(name: "Nullable", milliseconds: milliseconds, withNullableImplementation: false) : "")

public var wrappedValue: DayType

// We need to expose these values so keyed containers can access them.
let writeNulls = \(writeNulls)
let milliseconds = \(milliseconds)

public init(wrappedValue: DayType) {
self.wrappedValue = wrappedValue
}

public init(from decoder: Decoder) throws {
wrappedValue = try DayType.decode(using: decoder, milliseconds: \(milliseconds))
}

public func encode(to encoder: Encoder) throws {
try wrappedValue.encode(using: encoder, milliseconds: \(milliseconds), writeNulls: writeNulls)
}
}
"""
}
}
59 changes: 59 additions & 0 deletions Macros/Implementations/FormattedStringPropertyWrapperMacro.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import SwiftDiagnostics
import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftSyntaxMacros

/// Adds a static embedeed type for encoding and decoding using a passed formatter.
struct FormattedStringPropertyWrapperMacro: MemberMacro {

static func expansion(
of node: AttributeSyntax,
providingMembersOf _: some DeclGroupSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {

guard let typeName = node.arguments?.stringArgumentValue("name"),
let formatter = node.arguments?.argumentValue("formatter")
else {
context.diagnose(Diagnostic(
node: node, message: MacroExpansionErrorMessage("typeName, formatter or writeNulls argument not supplied. Passed arguments: \(node.arguments?.description ?? "")")
))
return []
}

let withNullableImplementation = (node.arguments?.argumentValue("withNullableImplementation") ?? "true") == "true"

return [
DeclSyntax(stringLiteral: propertyWrapper(name: typeName, formatter: formatter, withNullableImplementation: withNullableImplementation)),
]
}

private static func propertyWrapper(name: String, formatter: String, withNullableImplementation: Bool) -> String {
let writeNulls = withNullableImplementation ? "false" : "true"
return """
@propertyWrapper
public struct \(name): Codable {

\(withNullableImplementation ? propertyWrapper(name: "Nullable", formatter: formatter, withNullableImplementation: false) : "")

public var wrappedValue: DayType

// We need to expose these values so keyed containers can access them.
let formatter = \(formatter)
let writeNulls = \(writeNulls)

public init(wrappedValue: DayType) {
self.wrappedValue = wrappedValue
}

public init(from decoder: Decoder) throws {
wrappedValue = try DayType.decode(from: decoder, formatter: \(formatter))
}

public func encode(to encoder: Encoder) throws {
try wrappedValue.encode(into: encoder, formatter: \(formatter), writeNulls: \(writeNulls))
}
}
"""
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import SwiftDiagnostics
import SwiftSyntax
import SwiftSyntaxMacros

struct KeyedContainerDecodeMissingDayStringMacro: MemberMacro {

static func expansion(
of node: AttributeSyntax,
providingMembersOf owningType: some DeclGroupSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {

guard owningType.as(ExtensionDeclSyntax.self)?.extendedType.trimmedDescription == "KeyedDecodingContainer" else {
context.diagnose(Diagnostic(
node: node, message: MacroExpansionErrorMessage("Can only be used on a KeyedDecodingContainer: \(owningType.as(ExtensionDeclSyntax.self)?.extendedType.trimmedDescription ?? "")")
))
return []
}

guard let decodableType = node.arguments?.typeArgumentValue("type") else {
context.diagnose(Diagnostic(
node: node, message: MacroExpansionErrorMessage("Unable to determine passed type argument from: \(node.arguments?.description ?? "")")
))
return []
}

return [
"""
public func decode(_ type: \(raw: decodableType).Type, forKey key: Key) throws -> \(raw: decodableType) {
try decodeIfPresent(type, forKey: key) ?? .init(wrappedValue: nil)
}
""",
]
}
}
35 changes: 35 additions & 0 deletions Macros/Implementations/KeyedContainerDecodeMissingEpochMacro.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import SwiftDiagnostics
import SwiftSyntax
import SwiftSyntaxMacros

struct KeyedContainerDecodeMissingEpochMacro: MemberMacro {

static func expansion(
of node: AttributeSyntax,
providingMembersOf owningType: some DeclGroupSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {

guard owningType.as(ExtensionDeclSyntax.self)?.extendedType.trimmedDescription == "KeyedDecodingContainer" else {
context.diagnose(Diagnostic(
node: node, message: MacroExpansionErrorMessage("Can only be used on a KeyedDecodingContainer: \(owningType.as(ExtensionDeclSyntax.self)?.extendedType.trimmedDescription ?? "")")
))
return []
}

guard let decodableType = node.arguments?.typeArgumentValue("type") else {
context.diagnose(Diagnostic(
node: node, message: MacroExpansionErrorMessage("Unable to determine passed type argument from: \(node.arguments?.description ?? "")")
))
return []
}

return [
"""
public func decode(_ type: \(raw: decodableType).Type, forKey key: Key) throws -> \(raw: decodableType) {
try decodeIfPresent(type, forKey: key) ?? .init(wrappedValue: nil)
}
""",
]
}
}
Loading