Files
swift-composable-architectu…/Sources/ComposableArchitecture/Internal/NavigationID.swift
Stephen Celis 57e804f1cc Macro bonanza (#2553)
* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Silence test warnings

* wip

* wip

* wip

* update a bunch of docs

* wip

* wip

* fix

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Kill integration tests for now

* wip

* wip

* wip

* wip

* updating docs for @Reducer macro

* replaced more Reducer protocols with @Reducer

* Fixed some broken docc references

* wip

* Some @Reducer docs

* more docs

* convert some old styles to new style

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* bump

* update tutorials to use body

* update tutorials to use DML on destination state enum

* Add diagnostic

* wip

* updated a few more tests

* wip

* wip

* Add another gotcha

* wip

* wip

* wip

* fixes

* wip

* wip

* wip

* wip

* wip

* fix

* wip

* remove for now

* wip

* wip

* updated some docs

* migration guides

* more migration guide

* fix ci

* fix

* soft deprecate all apis using AnyCasePath

* wip

* Fix

* fix tests

* swift-format 509 compatibility

* wip

* wip

* Update Sources/ComposableArchitecture/Macros.swift

Co-authored-by: Mateusz Bąk <bakmatthew@icloud.com>

* wip

* wip

* update optional state case study

* remove initializer

* Don't use @State for BasicsView integration demo

* fix tests

* remove reduce diagnostics for now

* diagnose error not warning

* Update Sources/ComposableArchitecture/Macros.swift

Co-authored-by: Jesse Tipton <jesse@jessetipton.com>

* wip

* move integration tests to cron

* Revert "move integration tests to cron"

This reverts commit f9bdf2f04b.

* disable flakey tests on CI

* wip

* wip

* Revert "Revert "move integration tests to cron""

This reverts commit 66aafa7327.

* fix

* wip

* fix

---------

Co-authored-by: Brandon Williams <mbrandonw@hey.com>
Co-authored-by: Mateusz Bąk <bakmatthew@icloud.com>
Co-authored-by: Brandon Williams <135203+mbrandonw@users.noreply.github.com>
Co-authored-by: Jesse Tipton <jesse@jessetipton.com>
2023-11-13 12:57:35 -08:00

133 lines
3.4 KiB
Swift

@_spi(Reflection) import CasePaths
extension DependencyValues {
var navigationIDPath: NavigationIDPath {
get { self[NavigationIDPathKey.self] }
set { self[NavigationIDPathKey.self] = newValue }
}
}
private enum NavigationIDPathKey: DependencyKey {
static let liveValue = NavigationIDPath()
static let testValue = NavigationIDPath()
}
@usableFromInline
struct NavigationIDPath: Hashable, Sendable {
fileprivate var path: [NavigationID]
init(path: [NavigationID] = []) {
self.path = path
}
var prefixes: [NavigationIDPath] {
(0...self.path.count).map { index in
NavigationIDPath(path: Array(self.path.dropFirst(index)))
}
}
func appending(_ element: NavigationID) -> Self {
.init(path: self.path + [element])
}
public var id: Self { self }
}
struct NavigationID: Hashable, @unchecked Sendable {
private let kind: Kind
private let identifier: AnyHashableSendable?
private let tag: UInt32?
enum Kind: Hashable, @unchecked Sendable {
case casePath(root: Any.Type, value: Any.Type)
case keyPath(AnyKeyPath)
static func == (lhs: Self, rhs: Self) -> Bool {
switch (lhs, rhs) {
case let (.casePath(lhsRoot, lhsValue), .casePath(rhsRoot, rhsValue)):
return lhsRoot == rhsRoot && lhsValue == rhsValue
case let (.keyPath(lhs), .keyPath(rhs)):
return lhs == rhs
case (.casePath, _), (.keyPath, _):
return false
}
}
func hash(into hasher: inout Hasher) {
switch self {
case let .casePath(root: root, value: value):
hasher.combine(0)
hasher.combine(ObjectIdentifier(root))
hasher.combine(ObjectIdentifier(value))
case let .keyPath(keyPath):
hasher.combine(1)
hasher.combine(keyPath)
}
}
}
init<Value, Root>(
base: Value,
keyPath: KeyPath<Root, Value?>
) {
self.kind = .keyPath(keyPath)
self.tag = EnumMetadata(Value.self)?.tag(of: base)
if let id = _identifiableID(base) ?? EnumMetadata.project(base).flatMap(_identifiableID) {
self.identifier = AnyHashableSendable(id)
} else {
self.identifier = nil
}
}
init<Value, Root>(
id: StackElementID,
keyPath: KeyPath<Root, StackState<Value>>
) {
self.kind = .keyPath(keyPath)
self.tag = nil
self.identifier = AnyHashableSendable(id)
}
init<Value, Root, ID: Hashable>(
id: ID,
keyPath: KeyPath<Root, IdentifiedArray<ID, Value>>
) {
self.kind = .keyPath(keyPath)
self.tag = nil
self.identifier = AnyHashableSendable(id)
}
init<Value, Root>(
root: Root,
value: Value,
casePath: AnyCasePath<Root, Value>
) {
self.kind = .casePath(root: Root.self, value: Value.self)
self.tag = EnumMetadata(Root.self)?.tag(of: root)
if let id = _identifiableID(root) ?? _identifiableID(value) {
self.identifier = AnyHashableSendable(id)
} else {
self.identifier = nil
}
}
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.kind == rhs.kind
&& lhs.identifier == rhs.identifier
&& lhs.tag == rhs.tag
}
func hash(into hasher: inout Hasher) {
hasher.combine(self.kind)
hasher.combine(self.identifier)
hasher.combine(self.tag)
}
}
@_spi(Internals) public struct AnyHashableSendable: Hashable, @unchecked Sendable {
@_spi(Internals) public let base: AnyHashable
init<Base: Hashable & Sendable>(_ base: Base) {
self.base = base
}
}