diff --git a/Package.resolved b/Package.resolved index e1726f757..be678cf5a 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,96 +1,96 @@ { - "originHash": "5c5d4c39ca2ea45eb263e32ea7d8eff96d43a9ae3eca4026534ddd9423f303b8", - "pins": [ + "originHash" : "ec9e997bed87527379922584201be46e70c2efdf78de999abb9cb1425fcee9a0", + "pins" : [ { - "identity": "swift-case-paths", - "kind": "remoteSourceControl", - "location": "https://github.com/pointfreeco/swift-case-paths", - "state": { - "revision": "1197e80bc7e4b177051b6869ef93d8ac3ad677da", - "version": "1.8.0" + "identity" : "swift-case-paths", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-case-paths", + "state" : { + "revision" : "cb4cba6a8a46a86db0d37dbe09935ead6b24c91a", + "version" : "1.10.0" } }, { - "identity": "swift-custom-dump", - "kind": "remoteSourceControl", - "location": "https://github.com/pointfreeco/swift-custom-dump", - "state": { - "revision": "a8cd6c976f335ed361dcecddb0dc39ebda51bc3e", - "version": "1.6.1" + "identity" : "swift-custom-dump", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-custom-dump", + "state" : { + "revision" : "a8cd6c976f335ed361dcecddb0dc39ebda51bc3e", + "version" : "1.6.1" } }, { - "identity": "swift-docc-plugin", - "kind": "remoteSourceControl", - "location": "https://github.com/swiftlang/swift-docc-plugin", - "state": { - "revision": "647c708be89f834fa6a6d4945442793a77ddf5b6", - "version": "1.5.0" + "identity" : "swift-docc-plugin", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swiftlang/swift-docc-plugin", + "state" : { + "revision" : "647c708be89f834fa6a6d4945442793a77ddf5b6", + "version" : "1.5.0" } }, { - "identity": "swift-docc-symbolkit", - "kind": "remoteSourceControl", - "location": "https://github.com/swiftlang/swift-docc-symbolkit", - "state": { - "revision": "b45d1f2ed151d057b54504d653e0da5552844e34", - "version": "1.0.0" + "identity" : "swift-docc-symbolkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swiftlang/swift-docc-symbolkit", + "state" : { + "revision" : "b45d1f2ed151d057b54504d653e0da5552844e34", + "version" : "1.0.0" } }, { - "identity": "swift-issue-reporting", - "kind": "remoteSourceControl", - "location": "https://github.com/pointfreeco/swift-issue-reporting", - "state": { - "revision": "71c7c9a761d1ca6ed4ccb6ced040fe1c1a39e8e7", - "version": "2.1.0" + "identity" : "swift-issue-reporting", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-issue-reporting", + "state" : { + "revision" : "71c7c9a761d1ca6ed4ccb6ced040fe1c1a39e8e7", + "version" : "2.1.0" } }, { - "identity": "swift-macro-testing", - "kind": "remoteSourceControl", - "location": "https://github.com/pointfreeco/swift-macro-testing", - "state": { - "revision": "2e494c632d510715c96a694ff25e2a8d4ac3f64b", - "version": "0.6.5" + "identity" : "swift-macro-testing", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-macro-testing", + "state" : { + "revision" : "0b6bd11ea72e07eec539f2f000efad0b363a90cc", + "version" : "0.7.0" } }, { - "identity": "swift-perception", - "kind": "remoteSourceControl", - "location": "https://github.com/pointfreeco/swift-perception", - "state": { - "revision": "25ac73741c3436605d61eceb5207e896973918e7", - "version": "2.0.10" + "identity" : "swift-perception", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-perception", + "state" : { + "revision" : "25ac73741c3436605d61eceb5207e896973918e7", + "version" : "2.0.10" } }, { - "identity": "swift-snapshot-testing", - "kind": "remoteSourceControl", - "location": "https://github.com/pointfreeco/swift-snapshot-testing", - "state": { - "revision": "ad5e3190cc63dc288f28546f9c6827efc1e9d495", - "version": "1.19.2" + "identity" : "swift-snapshot-testing", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-snapshot-testing", + "state" : { + "revision" : "59a99c458de4d2dee580529b61b4f78dca7b7fa6", + "version" : "1.19.4" } }, { - "identity": "swift-syntax", - "kind": "remoteSourceControl", - "location": "https://github.com/swiftlang/swift-syntax", - "state": { - "revision": "79e4b74a295b6eb74a8b585e3a39d29e70c1dbd1", - "version": "603.0.2" + "identity" : "swift-syntax", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swiftlang/swift-syntax", + "state" : { + "revision" : "79e4b74a295b6eb74a8b585e3a39d29e70c1dbd1", + "version" : "603.0.2" } }, { - "identity": "xctest-dynamic-overlay", - "kind": "remoteSourceControl", - "location": "https://github.com/pointfreeco/xctest-dynamic-overlay", - "state": { - "revision": "7bbd97af585672a3dcdf6575ad37b339ad41b579", - "version": "1.13.0" + "identity" : "xctest-dynamic-overlay", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", + "state" : { + "revision" : "d9308ad679143c26a30dec52daefe82f54af2b82", + "version" : "1.13.1" } } ], - "version": 3 + "version" : 3 } diff --git a/Package.swift b/Package.swift index 9df3e2c77..73bdffa3a 100644 --- a/Package.swift +++ b/Package.swift @@ -58,12 +58,12 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.8.0"), + .package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.10.0"), .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.2"), .package(url: "https://github.com/pointfreeco/swift-issue-reporting", from: "2.1.0"), - .package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.6.0"), .package(url: "https://github.com/pointfreeco/swift-perception", "1.3.4"..<"3.0.0"), - .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.8.0"), + .package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.7.0"), + .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.10.1"), .package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.0.0"), .package(url: "https://github.com/swiftlang/swift-syntax", "509.0.0"..<"605.0.0"), ], diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift index a5c0afcbb..e8bc9c1cb 100644 --- a/Package@swift-6.0.swift +++ b/Package@swift-6.0.swift @@ -31,11 +31,11 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.8.0"), + .package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.10.0"), .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.2"), .package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.6.0"), .package(url: "https://github.com/pointfreeco/swift-perception", "1.3.4"..<"3.0.0"), - .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.8.0"), + .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.10.1"), .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.13.0"), .package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.0.0"), .package(url: "https://github.com/swiftlang/swift-syntax", "509.0.0"..<"605.0.0"), diff --git a/Package@swift-6.1.swift b/Package@swift-6.1.swift index 10790aa65..6c58c81eb 100644 --- a/Package@swift-6.1.swift +++ b/Package@swift-6.1.swift @@ -58,11 +58,11 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.8.0"), + .package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.10.0"), .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.2"), .package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.6.0"), .package(url: "https://github.com/pointfreeco/swift-perception", "1.3.4"..<"3.0.0"), - .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.8.0"), + .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.10.1"), .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.13.0"), .package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.0.0"), .package(url: "https://github.com/swiftlang/swift-syntax", "509.0.0"..<"605.0.0"), diff --git a/Package@swift-6.2.swift b/Package@swift-6.2.swift index 0ad5ff8a1..e604d590c 100644 --- a/Package@swift-6.2.swift +++ b/Package@swift-6.2.swift @@ -58,11 +58,11 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.8.0"), + .package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.10.0"), .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.2"), .package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.6.0"), .package(url: "https://github.com/pointfreeco/swift-perception", "1.3.4"..<"3.0.0"), - .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.8.0"), + .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.10.1"), .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.13.0"), .package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.0.0"), .package(url: "https://github.com/swiftlang/swift-syntax", "509.0.0"..<"605.0.0"), diff --git a/Sources/SwiftNavigation/CaseBindable.swift b/Sources/SwiftNavigation/CaseBindable.swift index c6208304f..3457d96bc 100644 --- a/Sources/SwiftNavigation/CaseBindable.swift +++ b/Sources/SwiftNavigation/CaseBindable.swift @@ -30,6 +30,7 @@ member, names: named(AllCasePaths), named(allCasePaths), + named(caseName), named(_$Element), named(UIBindingEnumeration), named(BindingEnumeration), @@ -123,7 +124,7 @@ extension UIBinding where Value: CasePathable { public func _$case( - _ keyPath: KeyPath> + _ keyPath: KeyPath> ) -> UIBinding { self[dynamicMember: keyPath]! } @@ -241,7 +242,7 @@ extension SwiftUI.Binding where Value: CasePathable { public func _$case( - _ keyPath: KeyPath> + _ keyPath: KeyPath> ) -> SwiftUI.Binding { SwiftUI.Binding(_unwrapping: self[_case: keyPath])! } @@ -256,7 +257,7 @@ extension CasePathable { fileprivate subscript( - _case keyPath: KeyPath> + _case keyPath: KeyPath> ) -> Member? { get { Self.allCasePaths[keyPath: keyPath].extract(from: self) } set { diff --git a/Sources/SwiftNavigation/Traits/CasePaths.swift b/Sources/SwiftNavigation/Traits/CasePaths.swift index 5970c7394..31afa1f05 100644 --- a/Sources/SwiftNavigation/Traits/CasePaths.swift +++ b/Sources/SwiftNavigation/Traits/CasePaths.swift @@ -8,7 +8,7 @@ /// - Returns: A new binding. @_disfavoredOverload public subscript( - dynamicMember keyPath: KeyPath> + dynamicMember keyPath: KeyPath> ) -> UIBinding? where Value: CasePathable { func open(_ location: some _UIBinding) -> UIBinding { @@ -25,7 +25,7 @@ /// - Parameter keyPath: A case key path to a specific associated value. /// - Returns: A new binding. public subscript( - dynamicMember keyPath: KeyPath> + dynamicMember keyPath: KeyPath> ) -> UIBinding where Value == V? { func open(_ location: some _UIBinding) -> UIBinding { @@ -42,26 +42,24 @@ /// - Parameter keyPath: A case key path to a case with no associated value. /// - Returns: A new binding. public subscript( - dynamicMember keyPath: KeyPath> + dynamicMember keyPath: KeyPath> ) -> UIBinding where Value == V? { UIBinding(self[dynamicMember: keyPath]) } } - private final class _UIBindingEnumToOptionalCase: _UIBinding - where Base.Value: CasePathable { + private final class _UIBindingEnumToOptionalCase: _UIBinding + where Base.Value: CasePathable, Path.Root == Base.Value { let base: Base - let keyPath: _SendableKeyPath> - let casePath: AnyCasePath - init( - base: Base, keyPath: _SendableKeyPath> - ) { + let keyPath: _SendableKeyPath + nonisolated(unsafe) let casePath: Path + init(base: Base, keyPath: _SendableKeyPath) { self.base = base self.keyPath = keyPath self.casePath = Base.Value.allCasePaths[keyPath: keyPath] } - var wrappedValue: Case? { + var wrappedValue: Path.Value? { get { casePath.extract(from: base.wrappedValue) } @@ -81,17 +79,17 @@ } private final class _UIBindingOptionalEnumToCase< - Base: _UIBinding, Enum: CasePathable, Case - >: _UIBinding { + Base: _UIBinding, Path: CasePath + >: _UIBinding where Path.Root: CasePathable { let base: Base - let keyPath: _SendableKeyPath> - let casePath: AnyCasePath - init(base: Base, keyPath: _SendableKeyPath>) { + let keyPath: _SendableKeyPath + nonisolated(unsafe) let casePath: Path + init(base: Base, keyPath: _SendableKeyPath) { self.base = base self.keyPath = keyPath - self.casePath = Enum.allCasePaths[keyPath: keyPath] + self.casePath = Path.Root.allCasePaths[keyPath: keyPath] } - var wrappedValue: Case? { + var wrappedValue: Path.Value? { get { base.wrappedValue.flatMap(casePath.extract(from:)) } diff --git a/Sources/SwiftNavigationMacros/CaseBindableMacro.swift b/Sources/SwiftNavigationMacros/CaseBindableMacro.swift index 80b8c15bb..60b935a09 100644 --- a/Sources/SwiftNavigationMacros/CaseBindableMacro.swift +++ b/Sources/SwiftNavigationMacros/CaseBindableMacro.swift @@ -33,6 +33,11 @@ enumDecl.inheritanceClause?.inheritedTypes.contains { ["CaseBindable", "\(moduleName).CaseBindable"].contains($0.type.trimmedDescription) } ?? false + || extensions.contains { + $0.inheritanceClause?.inheritedTypes.contains { + $0.type.trimmedDescription.hasSuffix("CaseBindable") + } ?? false + } if !conformsToCaseBindable { let caseBindableExtension: DeclSyntax = """ \(declaration.attributes.availability)extension \(type.trimmed): \ diff --git a/Sources/SwiftUINavigation/Traits/CasePaths.swift b/Sources/SwiftUINavigation/Traits/CasePaths.swift index ff7237369..4c7df5092 100644 --- a/Sources/SwiftUINavigation/Traits/CasePaths.swift +++ b/Sources/SwiftUINavigation/Traits/CasePaths.swift @@ -11,7 +11,7 @@ /// - Parameter keyPath: A case key path to a specific associated value. /// - Returns: A new binding. public subscript( - dynamicMember keyPath: KeyPath> + dynamicMember keyPath: KeyPath> ) -> Binding? where Value: CasePathable { Binding(unwrapping: self[keyPath]) @@ -24,7 +24,7 @@ /// - Parameter keyPath: A case key path to a specific associated value. /// - Returns: A new binding. public subscript( - dynamicMember keyPath: KeyPath> + dynamicMember keyPath: KeyPath> ) -> Binding where Value == Enum? { self[keyPath] @@ -39,7 +39,7 @@ /// - Parameter keyPath: A case key path to a specific associated value. /// - Returns: A new binding. public subscript( - dynamicMember keyPath: KeyPath> + dynamicMember keyPath: KeyPath> ) -> Binding where Value == Enum? { Binding(self[keyPath]) @@ -48,7 +48,7 @@ extension CasePathable { fileprivate subscript( - keyPath: KeyPath> + keyPath: KeyPath> ) -> Member? { get { Self.allCasePaths[keyPath: keyPath].extract(from: self) @@ -62,7 +62,7 @@ extension Optional where Wrapped: CasePathable { fileprivate subscript( - keyPath: KeyPath> + keyPath: KeyPath> ) -> Member? { get { self.flatMap(Wrapped.allCasePaths[keyPath: keyPath].extract(from:)) diff --git a/SwiftNavigation.xcworkspace/xcshareddata/swiftpm/Package.resolved b/SwiftNavigation.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6a95c0f11..e8e2a2bd3 100644 --- a/SwiftNavigation.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/SwiftNavigation.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "6ae399cd9f48f7a1439d7ea7b8ba4803830f408f9917ef1138f51c4f48f58fa2", + "originHash" : "556faf476a22c66a001c9e0e2869bdf97eab5490bd68796c4d4263a81098fdc2", "pins" : [ { "identity" : "combine-schedulers", @@ -15,8 +15,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-case-paths", "state" : { - "revision" : "1197e80bc7e4b177051b6869ef93d8ac3ad677da", - "version" : "1.8.0" + "branch" : "macro-spec", + "revision" : "cdfbedad1014028667110642217fc731495be0ad" } }, { @@ -91,13 +91,22 @@ "version" : "1.1.1" } }, + { + "identity" : "swift-issue-reporting", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-issue-reporting", + "state" : { + "revision" : "71c7c9a761d1ca6ed4ccb6ced040fe1c1a39e8e7", + "version" : "2.1.0" + } + }, { "identity" : "swift-macro-testing", "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-macro-testing", "state" : { - "revision" : "2e494c632d510715c96a694ff25e2a8d4ac3f64b", - "version" : "0.6.5" + "revision" : "0b6bd11ea72e07eec539f2f000efad0b363a90cc", + "version" : "0.7.0" } }, { diff --git a/Tests/SwiftNavigationMacrosTests/CaseBindableMacroTests.swift b/Tests/SwiftNavigationMacrosTests/CaseBindableMacroTests.swift index be41c20d9..9b8b873df 100644 --- a/Tests/SwiftNavigationMacrosTests/CaseBindableMacroTests.swift +++ b/Tests/SwiftNavigationMacrosTests/CaseBindableMacroTests.swift @@ -3,13 +3,21 @@ import MacroTesting import SnapshotTesting import SwiftNavigationMacros + import SwiftSyntaxBuilder + import SwiftSyntaxMacroExpansion import Testing @Suite( .macros( [ - CaseBindableMacro.self, - CasePathableMacro.self, + "CaseBindable": MacroSpec( + type: CaseBindableMacro.self, + conformances: ["CasePathable", "CasePathIterable", "CaseBindable"] + ), + "CasePathable": MacroSpec( + type: CasePathableMacro.self, + conformances: ["CasePathable", "CasePathIterable"] + ), ], record: .failed ) @@ -144,10 +152,7 @@ #endif } - extension Status: CasePaths.CasePathable, CasePaths.CasePathIterable { - } - - extension Status: SwiftNavigation.CaseBindable { + extension Status: CasePathable, CasePathIterable, CaseBindable { } """# } @@ -243,7 +248,7 @@ #endif } - extension Status: CasePaths.CasePathable, CasePaths.CasePathIterable { + extension Status: CasePathable, CasePathIterable { } extension Status: SwiftNavigation.CaseBindable {