diff --git a/Sources/OpenSwiftUI/Core/Graph/GraphHost.swift b/Sources/OpenSwiftUI/Core/Graph/GraphHost.swift index 1c6252ff..544a0a6d 100644 --- a/Sources/OpenSwiftUI/Core/Graph/GraphHost.swift +++ b/Sources/OpenSwiftUI/Core/Graph/GraphHost.swift @@ -9,6 +9,7 @@ internal import COpenSwiftUICore internal import OpenGraphShims @_spi(ForOpenSwiftUIOnly) import OpenSwiftUICore +@_spi(Private) import OpenSwiftUICore private let waitingForPreviewThunks = EnvironmentHelper.bool(for: "XCODE_RUNNING_FOR_PREVIEWS") private var blockedGraphHosts: [Unmanaged] = [] @@ -170,7 +171,7 @@ class GraphHost { } final func updatePreferences() -> Bool { - let seed = hostPreferenceValues.value?.mergedSeed ?? .empty + let seed = hostPreferenceValues.value?.seed ?? .empty let lastSeed = lastHostPreferencesSeed let didUpdate = seed.isInvalid || lastSeed.isInvalid /*|| (seed != lastSeed)*/ lastHostPreferencesSeed = seed diff --git a/Sources/OpenSwiftUI/Data/Preference/AnyPreferenceKey.swift b/Sources/OpenSwiftUI/Data/Preference/AnyPreferenceKey.swift deleted file mode 100644 index 3bb88676..00000000 --- a/Sources/OpenSwiftUI/Data/Preference/AnyPreferenceKey.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// AnyPreferenceKey.swift -// OpenSwiftUI -// -// Audited for RELEASE_2021 -// Status: Complete - -protocol AnyPreferenceKey { - static var valueType: Any.Type { get } - static func visitKey(_ visitor: inout Visitor) -} - -struct _AnyPreferenceKey: AnyPreferenceKey { - static var valueType: Any.Type { Key.self } - - static func visitKey(_ visitor: inout Visitor) where Visitor : PreferenceKeyVisitor { - visitor.visit(key: Key.self) - } -} diff --git a/Sources/OpenSwiftUI/Data/Preference/HostPreferencesKey.swift b/Sources/OpenSwiftUI/Data/Preference/HostPreferencesKey.swift deleted file mode 100644 index 78757cf8..00000000 --- a/Sources/OpenSwiftUI/Data/Preference/HostPreferencesKey.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// HostPreferencesKey.swift -// OpenSwiftUI -// -// Audited for RELEASE_2021 -// Status: Complete -// ID: 7429200566949B8FB892A77E01A988C8 - -internal import OpenGraphShims - -struct HostPreferencesKey: PreferenceKey { - static var defaultValue: PreferenceList { - PreferenceList() - } - - static func reduce(value: inout PreferenceList, nextValue: () -> PreferenceList) { - value.merge(nextValue()) - } -} - -extension HostPreferencesKey { - private static var nodeId: UInt32 = .zero - - @inline(__always) - static func makeNodeID() -> UInt32 { - defer { nodeId &+= 1 } - return nodeId - } -} - -extension _ViewOutputs { - @inline(__always) - var hostPreferences: Attribute? { - get { self[HostPreferencesKey.self] } - set { self[HostPreferencesKey.self] = newValue } - } -} - -extension PreferencesOutputs { - @inline(__always) - var hostPreferences: Attribute? { - get { self[HostPreferencesKey.self] } - set { self[HostPreferencesKey.self] = newValue } - } -} diff --git a/Sources/OpenSwiftUI/Data/Preference/PreferenceBridge.swift b/Sources/OpenSwiftUI/Data/Preference/PreferenceBridge.swift index 9a585fe4..efac7acd 100644 --- a/Sources/OpenSwiftUI/Data/Preference/PreferenceBridge.swift +++ b/Sources/OpenSwiftUI/Data/Preference/PreferenceBridge.swift @@ -195,7 +195,7 @@ private struct MergePreferenceKeys: Rule, AsyncAttribute { guard let rhs else { return result } - result.merge(rhs) + // result.merge(rhs) return result } } diff --git a/Sources/OpenSwiftUI/Data/Preference/PreferenceKey.swift b/Sources/OpenSwiftUI/Data/Preference/PreferenceKey.swift deleted file mode 100644 index 9a00bf5f..00000000 --- a/Sources/OpenSwiftUI/Data/Preference/PreferenceKey.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// PreferenceKey.swift -// OpenSwiftUI -// -// Audited for RELEASE_2021 -// Status: Complete - -/// A named value produced by a view. -/// -/// A view with multiple children automatically combines its values for a given -/// preference into a single value visible to its ancestors. -public protocol PreferenceKey { - /// The type of value produced by this preference. - associatedtype Value - - /// The default value of the preference. - /// - /// Views that have no explicit value for the key produce this default - /// value. Combining child views may remove an implicit value produced by - /// using the default. This means that `reduce(value: &x, nextValue: - /// {defaultValue})` shouldn't change the meaning of `x`. - static var defaultValue: Value { get } - - /// Combines a sequence of values by modifying the previously-accumulated - /// value with the result of a closure that provides the next value. - /// - /// This method receives its values in view-tree order. Conceptually, this - /// combines the preference value from one tree with that of its next - /// sibling. - /// - /// - Parameters: - /// - value: The value accumulated through previous calls to this method. - /// The implementation should modify this value. - /// - nextValue: A closure that returns the next value in the sequence. - static func reduce(value: inout Value, nextValue: () -> Value) - - static var _includesRemovedValues: Bool { get } - - static var _isReadableByHost: Bool { get } -} - -extension PreferenceKey where Value: ExpressibleByNilLiteral { - public static var defaultValue: Value { Value(nilLiteral: ()) } -} - -extension PreferenceKey { - public static var _includesRemovedValues: Bool { false } - - public static var _isReadableByHost: Bool { false } -} - -protocol HostPreferenceKey: PreferenceKey {} - -extension HostPreferenceKey { - static var _isReadableByHost: Bool { true } -} diff --git a/Sources/OpenSwiftUI/Data/Preference/PreferenceKeyVisitor.swift b/Sources/OpenSwiftUI/Data/Preference/PreferenceKeyVisitor.swift deleted file mode 100644 index 1727fa9f..00000000 --- a/Sources/OpenSwiftUI/Data/Preference/PreferenceKeyVisitor.swift +++ /dev/null @@ -1,10 +0,0 @@ -// -// PreferenceKeyVisitor.swift -// OpenSwiftUI -// -// Audited for RELEASE_2021 -// Status: Complete - -protocol PreferenceKeyVisitor { - mutating func visit(key: Key.Type) -} diff --git a/Sources/OpenSwiftUI/Data/Preference/PreferenceKeys.swift b/Sources/OpenSwiftUI/Data/Preference/PreferenceKeys.swift deleted file mode 100644 index 53b95085..00000000 --- a/Sources/OpenSwiftUI/Data/Preference/PreferenceKeys.swift +++ /dev/null @@ -1,85 +0,0 @@ -// -// PreferenceKeys.swift -// OpenSwiftUI -// -// Audited for RELEASE_2021 -// Status: Complete - -struct PreferenceKeys { - private var keys: [AnyPreferenceKey.Type] = [] - - init() {} -} - -extension PreferenceKeys: RandomAccessCollection, MutableCollection { - var startIndex: Int { keys.startIndex } - var endIndex: Int { keys.endIndex } - - mutating func add(_: Key.Type) { - keys.append(_AnyPreferenceKey.self) - } - - mutating func add(_ key: AnyPreferenceKey.Type) { - keys.append(key) - } - - mutating func remove(_: Key.Type) { - remove(_AnyPreferenceKey.self) - } - - mutating func remove(_ key: AnyPreferenceKey.Type) { - for index in keys.indices { - if keys[index] == key { - keys.remove(at: index) - return - } - } - } - - func contains(_: Key.Type) -> Bool { - contains(_AnyPreferenceKey.self) - } - - func contains(_ key: AnyPreferenceKey.Type) -> Bool { - keys.contains { $0 == key } - } - - var isEmpty: Bool { keys.isEmpty } - - subscript(position: Int) -> AnyPreferenceKey.Type { - get { keys[position] } - set { keys[position] = newValue } - } - - mutating func merge(_ preferenceKeys: PreferenceKeys) { - for key in preferenceKeys.keys { - guard !contains(key) else { - continue - } - add(key) - } - } - - func merging(_ preferenceKeys: PreferenceKeys) -> PreferenceKeys { - var result = self - result.merge(preferenceKeys) - return result - } -} - -extension PreferenceKeys: Equatable { - static func == (lhs: PreferenceKeys, rhs: PreferenceKeys) -> Bool { - guard lhs.keys.count == rhs.keys.count else { - return false - } - guard !lhs.keys.isEmpty else { - return true - } - for index in lhs.indices { - guard lhs[index] == rhs[index] else { - return false - } - } - return true - } -} diff --git a/Sources/OpenSwiftUI/Data/Preference/PreferencesCombiner.swift b/Sources/OpenSwiftUI/Data/Preference/PreferencesCombiner.swift index c67586ca..ba394d01 100644 --- a/Sources/OpenSwiftUI/Data/Preference/PreferencesCombiner.swift +++ b/Sources/OpenSwiftUI/Data/Preference/PreferencesCombiner.swift @@ -78,7 +78,7 @@ struct HostPreferencesCombiner: Rule, AsyncAttribute { continue } guard let values = child.$values, - let listValue = values.value.valueIfPresent(key) else { + let listValue = values.value.valueIfPresent(for: key) else { continue } if initialValue { diff --git a/Sources/OpenSwiftUI/Data/Preference/PreferencesInputs.swift b/Sources/OpenSwiftUI/Data/Preference/PreferencesInputs.swift index 0590c0cb..1da52fc7 100644 --- a/Sources/OpenSwiftUI/Data/Preference/PreferencesInputs.swift +++ b/Sources/OpenSwiftUI/Data/Preference/PreferencesInputs.swift @@ -31,6 +31,6 @@ struct PreferencesInputs { @inline(__always) mutating func merge(_ preferenceKeys: PreferenceKeys) { - keys.merge(preferenceKeys) + // keys.merge(preferenceKeys) } } diff --git a/Sources/OpenSwiftUI/Data/Preference/PreferencesOutputs.swift b/Sources/OpenSwiftUI/Data/Preference/PreferencesOutputs.swift index 543ba61b..5ab5dc3f 100644 --- a/Sources/OpenSwiftUI/Data/Preference/PreferencesOutputs.swift +++ b/Sources/OpenSwiftUI/Data/Preference/PreferencesOutputs.swift @@ -95,3 +95,19 @@ extension PreferencesOutputs { #endif } } + +extension _ViewOutputs { + @inline(__always) + var hostPreferences: Attribute? { + get { self[HostPreferencesKey.self] } + set { self[HostPreferencesKey.self] = newValue } + } +} + +extension PreferencesOutputs { + @inline(__always) + var hostPreferences: Attribute? { + get { self[HostPreferencesKey.self] } + set { self[HostPreferencesKey.self] = newValue } + } +} diff --git a/Sources/OpenSwiftUI/Data/Preference/View_Preference.swift b/Sources/OpenSwiftUI/Data/Preference/View_Preference.swift index edb88b73..2ad7b3b2 100644 --- a/Sources/OpenSwiftUI/Data/Preference/View_Preference.swift +++ b/Sources/OpenSwiftUI/Data/Preference/View_Preference.swift @@ -6,6 +6,9 @@ // Status: Complete // ID: 6C396F98EFDD04A6B58F2F9112448013 +@_spi(ForOpenSwiftUIOnly) import OpenSwiftUICore +@_spi(Private) import OpenSwiftUICore + extension View { /// Sets a value for the given preference. @inlinable diff --git a/Sources/OpenSwiftUICore/Data/Preference/PreferenceKey.swift b/Sources/OpenSwiftUICore/Data/Preference/PreferenceKey.swift new file mode 100644 index 00000000..e3551369 --- /dev/null +++ b/Sources/OpenSwiftUICore/Data/Preference/PreferenceKey.swift @@ -0,0 +1,187 @@ +// +// PreferenceKey.swift +// OpenSwiftUICore +// +// Audited for RELEASE_2024 +// Status: Complete +// ID: 3D8838A231BB2CC7FC00E7880D8B2FC4 + +// MARK: - PreferenceKey + +/// A named value produced by a view. +/// +/// A view with multiple children automatically combines its values for a given +/// preference into a single value visible to its ancestors. +public protocol PreferenceKey { + /// The type of value produced by this preference. + associatedtype Value + + /// The default value of the preference. + /// + /// Views that have no explicit value for the key produce this default + /// value. Combining child views may remove an implicit value produced by + /// using the default. This means that `reduce(value: &x, nextValue: + /// {defaultValue})` shouldn't change the meaning of `x`. + static var defaultValue: Value { get } + + /// Combines a sequence of values by modifying the previously-accumulated + /// value with the result of a closure that provides the next value. + /// + /// This method receives its values in view-tree order. Conceptually, this + /// combines the preference value from one tree with that of its next + /// sibling. + /// + /// - Parameters: + /// - value: The value accumulated through previous calls to this method. + /// The implementation should modify this value. + /// - nextValue: A closure that returns the next value in the sequence. + static func reduce(value: inout Value, nextValue: () -> Value) + + static var _includesRemovedValues: Bool { get } + + static var _isReadableByHost: Bool { get } +} + +extension PreferenceKey where Value: ExpressibleByNilLiteral { + public static var defaultValue: Value { Value(nilLiteral: ()) } +} + +extension PreferenceKey { + public static var _includesRemovedValues: Bool { false } + + public static var _isReadableByHost: Bool { false } + + package static var readableName: String { + var name = _typeName(Self.self, qualified: false) + if name.hasSuffix("Key") { + name.removeLast(3) + } + if name.hasSuffix("Preference") { + name.removeLast(10) + } + if name.isEmpty { + let fullname = _typeName(Self.self, qualified: true) + let results = fullname.split(maxSplits: 1) { $0 == "." } + return String(results[1]) + } else { + return name + } + } +} + +// MARK: - AnyPreferenceKey + +package protocol AnyPreferenceKey { + static var valueType: any Any.Type { get } + static func visitKey(_ v: inout V) where V: PreferenceKeyVisitor +} + +// MARK: - PreferenceKeyVisitor + +package protocol PreferenceKeyVisitor { + mutating func visit(key: K.Type) where K: PreferenceKey +} + +// MARK: - _AnyPreferenceKey + +package struct _AnyPreferenceKey: AnyPreferenceKey where K: PreferenceKey{ + package static var valueType: any Any.Type { K.self } + + package static func visitKey(_ v: inout V) where V : PreferenceKeyVisitor { + v.visit(key: K.self) + } +} + +// MARK: - PreferenceKeys + +package struct PreferenceKeys: Equatable, RandomAccessCollection, MutableCollection { + var keys: [any AnyPreferenceKey.Type] = [] + + @inlinable + package init() {} + + @inlinable + package var isEmpty: Bool { keys.isEmpty } + + @inlinable + package func contains(_ key: any AnyPreferenceKey.Type) -> Bool { + keys.contains { $0 == key } + } + + @inlinable + package func contains(_ key: K.Type) -> Bool where K: PreferenceKey { + contains(_AnyPreferenceKey.self) + } + + package mutating func add(_ key: any AnyPreferenceKey.Type) { + guard !contains(key) else { + return + } + keys.append(key) + } + + package mutating func add(_ key: K.Type) where K: PreferenceKey { + add(_AnyPreferenceKey.self) + } + + package mutating func remove(_ key: AnyPreferenceKey.Type) { + keys.removeAll { $0 == key } + } + + package mutating func remove(_ key: K.Type) where K: PreferenceKey { + remove(_AnyPreferenceKey.self) + } + + package static func == (lhs: PreferenceKeys, rhs: PreferenceKeys) -> Bool { + guard lhs.keys.count == rhs.keys.count else { + return false + } + guard !lhs.keys.isEmpty else { + return true + } + for index in lhs.indices { + guard lhs[index] == rhs[index] else { + return false + } + } + return true + } + + package var startIndex: Int { keys.startIndex } + package var endIndex: Int { keys.endIndex } + + @inlinable + package subscript(position: Int) -> AnyPreferenceKey.Type { + get { keys[position] } + set { keys[position] = newValue } + } +} + +// MARK: - HostPreferencesKey + +package struct HostPreferencesKey: PreferenceKey { + package static var defaultValue: PreferenceList { + PreferenceList() + } + + package static func reduce(value: inout PreferenceList, nextValue: () -> PreferenceList) { + value.combine(with: nextValue()) + } + + private static var nodeId = UInt32.zero + + package static func makeNodeId() -> UInt32 { + nodeId &+= 1 + return nodeId + } +} + +// MARK: - HostPreferenceKey + +@_spi(Private) +public protocol HostPreferenceKey: PreferenceKey {} + +@_spi(Private) +extension HostPreferenceKey { + public static var _isReadableByHost: Bool { true } +} diff --git a/Sources/OpenSwiftUI/Data/Preference/PreferenceList.swift b/Sources/OpenSwiftUICore/Data/Preference/PreferenceList.swift similarity index 63% rename from Sources/OpenSwiftUI/Data/Preference/PreferenceList.swift rename to Sources/OpenSwiftUICore/Data/Preference/PreferenceList.swift index f92e6649..83716a5c 100644 --- a/Sources/OpenSwiftUI/Data/Preference/PreferenceList.swift +++ b/Sources/OpenSwiftUICore/Data/Preference/PreferenceList.swift @@ -3,82 +3,90 @@ // OpenSwiftUI // // Audited for RELEASE_2021 -// Status: Complete -// ID: C1C63C2F6F2B9F3EB30DD747F0605FBD +// Status: WIP +// ID: C1C63C2F6F2B9F3EB30DD747F0605FBD (RELEASE_2021) +// ID: 7B694C05291EA7AF22785AB458D1BC2F (RELEASE_2024) -struct PreferenceList: CustomStringConvertible { - fileprivate var first: PreferenceNode? +package struct PreferenceList: CustomStringConvertible { + private var first: PreferenceNode? - init() {} + @inlinable + package init() {} - subscript(_ keyType: Key.Type) -> Value { + package struct Value { + package var value: T + package var seed: VersionSeed + + package init(value: T, seed: VersionSeed) { + self.value = value + self.seed = seed + } + } + + // TODO: TO BE AUDITED + package subscript(key: K.Type) -> Value where K: PreferenceKey{ get { guard let first, - let node = first.find(key: keyType) else { - return Value(value: keyType.defaultValue, seed: .empty) + let node = first.find(key: key) else { + return Value(value: key.defaultValue, seed: .empty) } return Value(value: node.value, seed: node.seed) } set { if let first, - let _ = first.find(key: keyType) { - removeValue(for: keyType) + let _ = first.find(key: key) { + removeValue(for: key) } - first = _PreferenceNode(value: newValue.value, seed: newValue.seed, next: first) + first = _PreferenceNode(value: newValue.value, seed: newValue.seed, next: first) } } - mutating func removeValue(for keyType: Key.Type) { - let first = first - self.first = nil - first?.forEach { node in - guard node.keyType != keyType else { - return - } - self.first = node.copy(next: self.first) - } - } - - func valueIfPresent(_ keyType: Key.Type) -> Value? { + // TODO: TO BE AUDITED + package func valueIfPresent(for _: K.Type) -> Value? where K: PreferenceKey { guard let first else { return nil } - return first.find(key: keyType).map { node in + return first.find(key: K.self).map { node in Value(value: node.value, seed: node.seed) } } - func contains(_ keyType: Key.Type) -> Bool { - first?.find(key: keyType) != nil + // TODO: TO BE AUDITED + package func contains(_ key: K.Type) -> Bool where K: PreferenceKey { + first?.find(key: key) != nil } - mutating func modifyValue(for keyType: Key.Type, transform: Value < (inout Key.Value) -> Void>) { - var value = self[keyType] + // TODO: TO BE AUDITED + package mutating func removeValue(for key: K.Type) where K: PreferenceKey { + let first = first + self.first = nil + first?.forEach { node in + guard node.keyType != key else { + return + } + self.first = node.copy(next: self.first) + } + } + + // TODO: TO BE AUDITED + package mutating func modifyValue(for key: K.Type, transform: Value <(inout K.Value) -> Void>) where K: PreferenceKey { + var value = self[key] value.seed.merge(transform.seed) transform.value(&value.value) - removeValue(for: keyType) - first = _PreferenceNode(value: value.value, seed: value.seed, next: first) + removeValue(for: key) + first = _PreferenceNode(value: value.value, seed: value.seed, next: first) } - var description: String { - var description = "\((first?.mergedSeed ?? .empty).description): [" - var currentNode = first - var shouldAddSeparator = false - while let node = currentNode { - if shouldAddSeparator { - description.append(", ") - } else { - shouldAddSeparator = true - } - description.append(node.description) - currentNode = node.next - } - description.append("]") - return description + // TODO: TO BE AUDITED + package func mayNotBeEqual(to other: PreferenceList) -> Bool { + // TODO + return false } - @inline(__always) - mutating func merge(_ other: PreferenceList) { + package var seed: VersionSeed { first?.mergedSeed ?? .empty } + + // TODO: TO BE AUDITED + package mutating func combine(with other: PreferenceList) { guard let otherFirst = other.first else { return } @@ -102,22 +110,38 @@ struct PreferenceList: CustomStringConvertible { } } - @inline(__always) - var mergedSeed: VersionSeed? { first?.mergedSeed } -} - -extension PreferenceList { - struct Value { - var value: V - var seed: VersionSeed - - init(value: V, seed: VersionSeed) { - self.value = value - self.seed = seed + package mutating func filterRemoved() { + guard let first else { + return + } + self.first = nil + first.forEach { node in + guard type(of: node)._includesRemovedValues else { + return + } + self.first = node.copy(next: self.first) + } + } + + package var description: String { + var description = "\(seed.description): [" + var currentNode = first + var shouldAddSeparator = false + while let node = currentNode { + if shouldAddSeparator { + description.append(", ") + } else { + shouldAddSeparator = true + } + description.append(node.description) + currentNode = node.next } + description.append("]") + return description } } +// TODO: TO BE AUDITED private class PreferenceNode: CustomStringConvertible { let keyType: Any.Type let seed: VersionSeed @@ -141,11 +165,10 @@ private class PreferenceNode: CustomStringConvertible { var node = self repeat { body(node) - if let next = node.next { - node = next - } else { + guard let next = node.next else { break } + node = next } while true } @@ -168,9 +191,11 @@ private class PreferenceNode: CustomStringConvertible { func find(from _: PreferenceNode?) -> PreferenceNode? { fatalError() } func combine(from _: PreferenceNode?, next _: PreferenceNode?) -> PreferenceNode? { fatalError() } func copy(next _: PreferenceNode?) -> PreferenceNode { fatalError() } + class var _includesRemovedValues: Bool { fatalError() } var description: String { fatalError() } } +// TODO: TO BE AUDITED private class _PreferenceNode: PreferenceNode { let value: Key.Value @@ -204,7 +229,9 @@ private class _PreferenceNode: PreferenceNode { override func copy(next: PreferenceNode?) -> PreferenceNode { _PreferenceNode(value: value, seed: seed, next: next) } - + + override class var _includesRemovedValues: Bool { Key._includesRemovedValues } + override var description: String { "\(Key.self) = \(value)" } diff --git a/Tests/OpenSwiftUICoreTests/Data/Preference/PreferenceKeyTests.swift b/Tests/OpenSwiftUICoreTests/Data/Preference/PreferenceKeyTests.swift new file mode 100644 index 00000000..6cbfc934 --- /dev/null +++ b/Tests/OpenSwiftUICoreTests/Data/Preference/PreferenceKeyTests.swift @@ -0,0 +1,35 @@ +// +// PreferenceKeyTests.swift +// OpenSwiftUICoreTests + +import OpenSwiftUICore +import Testing + +struct PreferenceKeyTests { + @Test + func readableName() { + struct AKey: OpenSwiftUICore.PreferenceKey { + static var defaultValue: Int { 0 } + static func reduce(value: inout Int, nextValue: () -> Int) {} + } + #expect(AKey.readableName == "A") + + struct BPreference: OpenSwiftUICore.PreferenceKey { + static var defaultValue: Int { 0 } + static func reduce(value: inout Int, nextValue: () -> Int) {} + } + #expect(BPreference.readableName == "B") + + struct CPreferenceKey: OpenSwiftUICore.PreferenceKey { + static var defaultValue: Int { 0 } + static func reduce(value: inout Int, nextValue: () -> Int) {} + } + #expect(BPreference.readableName == "C") + + struct PreferenceKey: OpenSwiftUICore.PreferenceKey { + static var defaultValue: Int { 0 } + static func reduce(value: inout Int, nextValue: () -> Int) {} + } + #expect(PreferenceKey.readableName == "PreferenceKey") + } +} diff --git a/Tests/OpenSwiftUICoreTests/Data/Preference/PreferenceListTests.swift b/Tests/OpenSwiftUICoreTests/Data/Preference/PreferenceListTests.swift new file mode 100644 index 00000000..10742901 --- /dev/null +++ b/Tests/OpenSwiftUICoreTests/Data/Preference/PreferenceListTests.swift @@ -0,0 +1,44 @@ +// +// PreferenceListTests.swift +// OpenSwiftUICoreTests + +import OpenSwiftUICore +import Testing + +struct PreferenceListTests { + struct AKey: PreferenceKey { + static let defaultValue = 0 + static func reduce(value _: inout Int, nextValue _: () -> Int) {} + static var _includesRemovedValues: Bool { true } + } + + struct B: PreferenceKey { + static let defaultValue = 0 + static func reduce(value _: inout Int, nextValue _: () -> Int) {} + } + + struct C: PreferenceKey { + static let defaultValue = 0 + static func reduce(value _: inout Int, nextValue _: () -> Int) {} + static var _includesRemovedValues: Bool { true } + } + + @Test + func filterRemoved() { + var list = PreferenceList() + list[AKey.self] = .init(value: 0, seed: .invalid) + list[B.self] = .init(value: 1, seed: .empty) + list[C.self] = .init(value: 2, seed: .empty) + #expect(list.description == "invalid: [C = 2, B = 1, AKey = 0]") + list.filterRemoved() + #expect(list.description == "invalid: [AKey = 0, C = 2]") + } + + @Test + func description() { + var list = PreferenceList() + list[AKey.self] = .init(value: 2, seed: .invalid) + list[B.self] = .init(value: 2, seed: .empty) + #expect(list.description == "invalid: [B = 2, AKey = 2]") + } +} diff --git a/Tests/OpenSwiftUITests/Data/Preference/HostPreferencesKeyTests.swift b/Tests/OpenSwiftUITests/Data/Preference/HostPreferencesKeyTests.swift index ff45b94b..442ec3af 100644 --- a/Tests/OpenSwiftUITests/Data/Preference/HostPreferencesKeyTests.swift +++ b/Tests/OpenSwiftUITests/Data/Preference/HostPreferencesKeyTests.swift @@ -53,9 +53,9 @@ struct HostPreferencesKeyTests { @Test func nodeID() { - let id0 = HostPreferencesKey.makeNodeID() - let id1 = HostPreferencesKey.makeNodeID() - let id2 = HostPreferencesKey.makeNodeID() + let id0 = HostPreferencesKey.makeNodeId() + let id1 = HostPreferencesKey.makeNodeId() + let id2 = HostPreferencesKey.makeNodeId() #expect(id1 == (id0 + 1)) #expect(id2 == (id1 + 1)) }