diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 0000000..1906563 --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,27 @@ +name: Format + +on: + push: + branches: + - main + +concurrency: + group: format-${{ github.ref }} + cancel-in-progress: true + +jobs: + swift_format: + name: swift-format + runs-on: macos-15 + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + - name: Select Xcode 16.2 + run: sudo xcode-select -s /Applications/Xcode_16.2.app + - name: Format + run: make format + - uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: Run swift-format + branch: 'main' diff --git a/Sources/Sharing/Shared.swift b/Sources/Sharing/Shared.swift index fd75f57..48f765b 100644 --- a/Sources/Sharing/Shared.swift +++ b/Sources/Sharing/Shared.swift @@ -223,16 +223,25 @@ public struct Shared { reference = newValue.reference } } - + /// Returns a read-only shared reference to the resulting value of a given closure. /// /// - Returns: A new read-only shared reference. public func read( - _ body: @escaping @Sendable(Value) -> Member + _ body: @escaping @Sendable (Value) -> Member ) -> SharedReader { SharedReader(self).read(body) } + @available( + *, + deprecated, + message: "Use dynamic member lookup instead ('$shared.member', not '$shared.read(\\.member)')" + ) + public func read(_ keyPath: KeyPath) -> SharedReader { + self[dynamicMember: keyPath] + } + /// Returns a shared reference to the resulting value of a given key path. /// /// You don't call this subscript directly. Instead, Swift calls it for you when you access a diff --git a/Sources/Sharing/SharedKeys/AppStorageKey.swift b/Sources/Sharing/SharedKeys/AppStorageKey.swift index f44283d..67560a9 100644 --- a/Sources/Sharing/SharedKeys/AppStorageKey.swift +++ b/Sources/Sharing/SharedKeys/AppStorageKey.swift @@ -559,20 +559,20 @@ } } -extension UserDefaults { - public static var inMemory: UserDefaults { - let suiteName: String - // NB: Due to a bug in iOS 16 and lower, UserDefaults does not observe changes when using - // file-based suites. Go back to using temporary directory always when we drop iOS 16 - // support. - if #unavailable(iOS 17, macOS 14, tvOS 17, watchOS 10, visionOS 1) { - suiteName = "co.pointfree.Sharing.\(UUID().uuidString)" - } else { - suiteName = "\(NSTemporaryDirectory())co.pointfree.Sharing.\(UUID().uuidString)" - } - return UserDefaults(suiteName: suiteName)! + extension UserDefaults { + public static var inMemory: UserDefaults { + let suiteName: String + // NB: Due to a bug in iOS 16 and lower, UserDefaults does not observe changes when using + // file-based suites. Go back to using temporary directory always when we drop iOS 16 + // support. + if #unavailable(iOS 17, macOS 14, tvOS 17, watchOS 10, visionOS 1) { + suiteName = "co.pointfree.Sharing.\(UUID().uuidString)" + } else { + suiteName = "\(NSTemporaryDirectory())co.pointfree.Sharing.\(UUID().uuidString)" + } + return UserDefaults(suiteName: suiteName)! + } } -} private enum AppStorageKeyFormatWarningEnabledKey: DependencyKey { static let liveValue = true diff --git a/Sources/Sharing/SharedReader.swift b/Sources/Sharing/SharedReader.swift index 6615219..7c98d99 100644 --- a/Sources/Sharing/SharedReader.swift +++ b/Sources/Sharing/SharedReader.swift @@ -155,7 +155,7 @@ public struct SharedReader { reference = newValue.reference } } - + /// Returns a read-only shared reference to the resulting value of a given closure. /// /// - Returns: A new shared reader. @@ -170,6 +170,15 @@ public struct SharedReader { return open(reference) } + @available( + *, + deprecated, + message: "Use dynamic member lookup instead ('$shared.member', not '$shared.read(\\.member)')" + ) + public func read(_ keyPath: KeyPath) -> SharedReader { + self[dynamicMember: keyPath] + } + /// Returns a read-only shared reference to the resulting value of a given key path. /// /// You don't call this subscript directly. Instead, Swift calls it for you when you access a diff --git a/Tests/SharingTests/ContinuationTests.swift b/Tests/SharingTests/ContinuationTests.swift index 9de23f1..0dfd2a5 100644 --- a/Tests/SharingTests/ContinuationTests.swift +++ b/Tests/SharingTests/ContinuationTests.swift @@ -1,5 +1,5 @@ -import Testing import Sharing +import Testing @Suite struct ContinuationTests { @Test func dontResumeLoadContinuation() async throws { diff --git a/Tests/SharingTests/EquatableTests.swift b/Tests/SharingTests/EquatableTests.swift index 2103101..33a70ac 100644 --- a/Tests/SharingTests/EquatableTests.swift +++ b/Tests/SharingTests/EquatableTests.swift @@ -32,7 +32,7 @@ struct EquatableTests { #expect(lhs == rhs) #expect($lhs == $rhs) } - + @Test func mapReader() { @Shared(value: 0) var base: Int @SharedReader var lhs: Int @@ -41,7 +41,7 @@ struct EquatableTests { _rhs = $base.read { $0 * 3 } #expect(lhs == rhs) #expect($lhs == $rhs) - + $base.withLock { $0 += 1 } #expect(lhs != rhs) #expect($lhs != $rhs) diff --git a/Tests/SharingTests/ErrorThrowingTests.swift b/Tests/SharingTests/ErrorThrowingTests.swift index 1509214..9f22c1e 100644 --- a/Tests/SharingTests/ErrorThrowingTests.swift +++ b/Tests/SharingTests/ErrorThrowingTests.swift @@ -43,7 +43,7 @@ import Testing @SharedReader(Key()) var count = 0 #expect($count.loadError != nil) } - + @Test func userInitiatedLoadError() async { struct LoadError: Error {} struct Key: Hashable, Sendable, SharedReaderKey { @@ -62,9 +62,9 @@ import Testing SharedSubscription {} } } - + @SharedReader(Key()) var value = 0 - + await #expect(throws: LoadError.self) { try await $value.load() } diff --git a/Tests/SharingTests/InMemoryTests.swift b/Tests/SharingTests/InMemoryTests.swift index 0cc8bff..808dc9f 100644 --- a/Tests/SharingTests/InMemoryTests.swift +++ b/Tests/SharingTests/InMemoryTests.swift @@ -86,7 +86,8 @@ import Testing @Shared(.inMemory("nestedOptionalCount")) var nestedOptionalCount: Int?? = .some(.none) #expect(nestedOptionalCount == .some(.none)) - @SharedReader(.inMemory("nestedOptionalCountReader")) var nestedOptionalCountReader: Int?? = .some(.none) + @SharedReader(.inMemory("nestedOptionalCountReader")) var nestedOptionalCountReader: Int?? = + .some(.none) #expect(nestedOptionalCountReader == .some(.none)) } diff --git a/Tests/SharingTests/SharedChangeTrackerTests.swift b/Tests/SharingTests/SharedChangeTrackerTests.swift index 247fc48..2854095 100644 --- a/Tests/SharingTests/SharedChangeTrackerTests.swift +++ b/Tests/SharingTests/SharedChangeTrackerTests.swift @@ -98,7 +98,7 @@ import Testing $count.withLock { $0 = 1 } #expect($count == $count) - #expect(counts.withLock(\.self) == [0 ,1]) + #expect(counts.withLock(\.self) == [0, 1]) } } diff --git a/Tests/SharingTests/SharedTests.swift b/Tests/SharingTests/SharedTests.swift index c9cbbf7..0262420 100644 --- a/Tests/SharingTests/SharedTests.swift +++ b/Tests/SharingTests/SharedTests.swift @@ -87,7 +87,7 @@ import Testing #expect(id == 42) } - + @Test func mapReader() { @Shared(value: 0) var count @SharedReader var isZero: Bool