From d6bffb1f7e16e9b05f7b607229077d87c5e5781d Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 26 Oct 2025 22:14:51 +0800 Subject: [PATCH 1/8] Add AnyStyleContext API --- .../View/Style/AnyStyleContext.swift | 69 +++++++++++++++++++ .../View/Style/StyleContext.swift | 6 ++ 2 files changed, 75 insertions(+) create mode 100644 Sources/OpenSwiftUICore/View/Style/AnyStyleContext.swift diff --git a/Sources/OpenSwiftUICore/View/Style/AnyStyleContext.swift b/Sources/OpenSwiftUICore/View/Style/AnyStyleContext.swift new file mode 100644 index 000000000..178bd0407 --- /dev/null +++ b/Sources/OpenSwiftUICore/View/Style/AnyStyleContext.swift @@ -0,0 +1,69 @@ +// +// AnyStyleContext.swift +// OpenSwiftUICore +// +// Audited for 6.5.4 +// Status: Complete +// ID: 95C35B9B1549B6F41E131C274C6E343F (SwiftUICore) + +// MARK: - AnyStyleContextType + +package struct AnyStyleContextType: Equatable { + private let base: any AnyStyleContextTypeBox.Type + + private init(base: any AnyStyleContextTypeBox.Type) { + self.base = base + } + + package init(_ context: C.Type = C.self) where C: StyleContext { + base = StyleContextTypeBox.self + } + + package static func == (lhs: AnyStyleContextType, rhs: AnyStyleContextType) -> Bool { + lhs.base.isEqual(to: rhs.base) + } + + package func acceptsTop(_ query: Q.Type) -> Bool { + base.acceptsTop(query) + } + + package func pushing(_ newContext: N.Type) -> AnyStyleContextType where N: StyleContext { + AnyStyleContextType(base: base.pushing(newContext)) + } + + package func acceptsAny(_ queries: repeat (each Q).Type) -> Bool where repeat each Q: StyleContext { + base.acceptsAny(repeat each queries) + } +} + +// MARK: - AnyStyleContextTypeBox + +private protocol AnyStyleContextTypeBox { + static func isEqual(to other: AnyStyleContextTypeBox.Type) -> Bool + + static func acceptsTop(_ query: Q.Type) -> Bool + + static func acceptsAny(_ queries: repeat (each Q).Type) -> Bool where repeat each Q: StyleContext + + static func pushing(_ newContext: N.Type) -> AnyStyleContextTypeBox.Type where N: StyleContext +} + +// MARK: - StyleContextTypeBox + +private struct StyleContextTypeBox: AnyStyleContextTypeBox where Context: StyleContext { + static func isEqual(to other: AnyStyleContextTypeBox.Type) -> Bool { + other is StyleContextTypeBox.Type + } + + static func acceptsTop(_ query: Q.Type) -> Bool { + Context.acceptsTop(query) + } + + static func acceptsAny(_ queries: repeat (each Q).Type) -> Bool where repeat each Q: StyleContext { + Context.acceptsAny(repeat each queries) + } + + static func pushing(_ newContext: N.Type) -> AnyStyleContextTypeBox.Type where N: StyleContext { + StyleContextTypeBox>.self + } +} diff --git a/Sources/OpenSwiftUICore/View/Style/StyleContext.swift b/Sources/OpenSwiftUICore/View/Style/StyleContext.swift index d2fa3401b..ee17019bc 100644 --- a/Sources/OpenSwiftUICore/View/Style/StyleContext.swift +++ b/Sources/OpenSwiftUICore/View/Style/StyleContext.swift @@ -6,6 +6,8 @@ // Status: WIP // ID: 2EF43D8D991A83294E93848563DD541B (SwiftUICore) +// TODO: View + StyleContext + // MARK: - StyleContext package protocol StyleContext { @@ -61,6 +63,10 @@ package struct StyleContextAcceptsAnyPredicate: ViewInputPredicate w } } +struct TupleStyleContext: StyleContext { + +} + // TODO // MARK: - StyleContextVisitor From f1e79577e4f0c14830a86d7a5ec141d75cc10651 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 26 Oct 2025 23:08:16 +0800 Subject: [PATCH 2/8] Update StyleContext --- .../View/Style/StyleContext.swift | 399 +++++++++++++++++- 1 file changed, 386 insertions(+), 13 deletions(-) diff --git a/Sources/OpenSwiftUICore/View/Style/StyleContext.swift b/Sources/OpenSwiftUICore/View/Style/StyleContext.swift index ee17019bc..18c5f1bf6 100644 --- a/Sources/OpenSwiftUICore/View/Style/StyleContext.swift +++ b/Sources/OpenSwiftUICore/View/Style/StyleContext.swift @@ -2,12 +2,10 @@ // StyleContext.swift // OpenSwiftUICore // -// Audited for 6.0.87 +// Audited for 6.5.4 // Status: WIP // ID: 2EF43D8D991A83294E93848563DD541B (SwiftUICore) -// TODO: View + StyleContext - // MARK: - StyleContext package protocol StyleContext { @@ -28,14 +26,14 @@ extension StyleContext { } package static func acceptsAny(_ queries: repeat (each Q).Type) -> Bool where repeat each Q: StyleContext { - var visitor = QueryVisitor() for query in repeat each queries { + var visitor = QueryVisitor(accepts: false) query.visitStyle(&visitor) guard !visitor.accepts else { return true } } - return visitor.accepts + return false } package static func acceptsTop(_ query: Q.Type) -> Bool { @@ -43,31 +41,390 @@ extension StyleContext { } } -// TODO +// MARK: - Concreate StyleContext + +package struct WindowRootContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == WindowRootContext { + package static var windowRoot: WindowRootContext { + WindowRootContext() + } +} + +package struct AccessibilityRepresentableStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == AccessibilityRepresentableStyleContext { + package static var accessibilityRepresentable: AccessibilityRepresentableStyleContext { + AccessibilityRepresentableStyleContext() + } +} + +package struct AccessibilityQuickActionStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == AccessibilityQuickActionStyleContext { + package static var accessibilityQuickAction: AccessibilityQuickActionStyleContext { + AccessibilityQuickActionStyleContext() + } +} + +package struct ContainerStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == ContainerStyleContext { + package static var container: ContainerStyleContext { + ContainerStyleContext() + } +} + +package struct ContentListStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == ContentListStyleContext { + package static var contentList: ContentListStyleContext { + ContentListStyleContext() + } +} + +package struct DocumentStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == DocumentStyleContext { + package static var document: DocumentStyleContext { + DocumentStyleContext() + } +} + +package struct ControlGroupStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == ControlGroupStyleContext { + package static var controlGroup: ControlGroupStyleContext { + ControlGroupStyleContext() + } +} + +package struct DialogActionStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == DialogActionStyleContext { + package static var dialogAction: DialogActionStyleContext { + DialogActionStyleContext() + } +} + +package struct HostingConfigurationContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == HostingConfigurationContext { + package static var hostingConfiguration: HostingConfigurationContext { + HostingConfigurationContext() + } +} + +package struct MenuStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == MenuStyleContext { + package static var menu: MenuStyleContext { + MenuStyleContext() + } +} + +package struct MultimodalListContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == MultimodalListContext { + package static var multimodalList: MultimodalListContext { + MultimodalListContext() + } +} + +package struct MultimodalListGridContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == MultimodalListGridContext { + package static var multimodalListGrid: MultimodalListGridContext { + MultimodalListGridContext() + } +} + +package struct MultimodalListStackContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == MultimodalListStackContext { + package static var multimodalListStack: MultimodalListStackContext { + MultimodalListStackContext() + } +} + +package struct NoStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == NoStyleContext { + package static var none: NoStyleContext { + NoStyleContext() + } +} + +package struct ScrollViewStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == ScrollViewStyleContext { + package static var scrollView: ScrollViewStyleContext { + ScrollViewStyleContext() + } +} + +package struct TextInputSuggestionsContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == TextInputSuggestionsContext { + package static var textInputSuggestions: TextInputSuggestionsContext { + TextInputSuggestionsContext() + } +} + +package struct SectionHeaderStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == SectionHeaderStyleContext { + package static var sectionHeader: SectionHeaderStyleContext { + SectionHeaderStyleContext() + } +} + +package struct SheetStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == SheetStyleContext { + package static var sheet: SheetStyleContext { + SheetStyleContext() + } +} + +package struct SheetToolbarStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == SheetToolbarStyleContext { + package static var sheetToolbar: SheetToolbarStyleContext { + SheetToolbarStyleContext() + } +} + +package struct SidebarStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == SidebarStyleContext { + package static var sidebar: SidebarStyleContext { + SidebarStyleContext() + } +} + +package struct SwipeActionsStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == SwipeActionsStyleContext { + package static var swipeActions: SwipeActionsStyleContext { + SwipeActionsStyleContext() + } +} + +package struct TableStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == TableStyleContext { + package static var table: TableStyleContext { + TableStyleContext() + } +} -// MARK: - StyleContextAcceptsPredicate [WIP] +package struct ToolbarStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == ToolbarStyleContext { + package static var toolbar: ToolbarStyleContext { + ToolbarStyleContext() + } +} + +package struct InspectorStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == InspectorStyleContext { + package static var inspector: InspectorStyleContext { + InspectorStyleContext() + } +} + +package struct MenuBarExtraWindowStyleContext: StyleContext { + package init() {} +} + +extension StyleContext where Self == MenuBarExtraWindowStyleContext { + package static var menuBarExtraWindow: MenuBarExtraWindowStyleContext { + MenuBarExtraWindowStyleContext() + } +} + +// MARK: View + StyleContext [WIP] + +@available(OpenSwiftUI_v1_0, *) +extension View { + package func styleContext(_ context: C) -> some View where C: StyleContext { + modifier(StyleContextWriter()) + } + + package func styleContext(_ context: C, if predicate: P) -> some View where C: StyleContext, P: ViewInputPredicate { +// modifier(StyleContextWriter() .requiring(P.self)) + _openSwiftUIUnimplementedFailure() + } + + package func styleContext(_ context: C, in requiredContext: P) -> some View where C: StyleContext, P: StyleContext { + _openSwiftUIUnimplementedFailure() + } + + /// Sets the style context of `self` to the default context. + nonisolated public func _defaultContext() -> some View { + modifier(DefaultStyleContextWriter()) + } +} + +// MARK: - StyleContextWriter + +package struct StyleContextWriter: PrimitiveViewModifier, _GraphInputsModifier where Context: StyleContext { + package init() {} + + package static func _makeInputs( + modifier: _GraphValue, + inputs: inout _GraphInputs + ) { + inputs.styleContext = inputs.styleContext.pushing(Context.self) + } +} + +// MARK: - DefaultStyleContextWriter + +package struct DefaultStyleContextWriter: PrimitiveViewModifier, _GraphInputsModifier { + package static func _makeInputs( + modifier: _GraphValue, + inputs: inout _GraphInputs + ) { + inputs.styleContext = StyleContextInput.defaultValue + } +} + +// MARK: - StyleContextInput + +package struct StyleContextInput: ViewInput { + package static let defaultValue = AnyStyleContextType(NoStyleContext.self) +} + +extension _GraphInputs { + @inline(__always) + var styleContext: AnyStyleContextType { + get { self[StyleContextInput.self] } + set { self[StyleContextInput.self] = newValue } + } +} + +// MARK: - StyleContextAcceptsPredicate package struct StyleContextAcceptsPredicate: ViewInputPredicate { package init() {} package static func evaluate(inputs: _GraphInputs) -> Bool { - _openSwiftUIUnimplementedFailure() + inputs.styleContext.acceptsTop(Query.self) } } +// MARK: - StyleContextAcceptsAnyPredicate + package struct StyleContextAcceptsAnyPredicate: ViewInputPredicate where repeat each Query: StyleContext { package init() {} package static func evaluate(inputs: _GraphInputs) -> Bool { - _openSwiftUIUnimplementedFailure() + inputs.styleContext.acceptsAny(repeat (each Query).self) + } +} + +// MARK: - _GraphInputs + StyleContext + +extension _GraphInputs { + package var isDefaultStyleContext: Bool { + styleContext == StyleContextInput.defaultValue + } + + package func accepts(_ context: repeat each C) -> Bool where repeat each C: StyleContext { + styleContext.acceptsAny(repeat (each C).self) + } + + package mutating func pushStyleContext(_ context: C) where C: StyleContext { + styleContext = styleContext.pushing(C.self) + } + + package mutating func resetStyleContext() { + styleContext = StyleContextInput.defaultValue + } + + package func printStyleContext() { + print(styleContext) } } -struct TupleStyleContext: StyleContext { +// MARK: - _ViewListCountInputs + StyleContext +extension _ViewListCountInputs { + package mutating func resetStyleContext() { + customInputs[StyleContextInput.self] = StyleContextInput.defaultValue + } } -// TODO +// MARK: - StyleContextPrintingModifier + +package typealias StyleContextPrintingModifier = EmptyModifier + +// MARK: - TupleStyleContext [WIP] + +package struct TupleStyleContext: StyleContext { + package static func acceptsAny(_: repeat (each Q).Type) -> Bool where repeat each Q: StyleContext { + _openSwiftUIUnimplementedFailure() + } + + package static func visitStyle(_ visitor: inout V) where V: StyleContextVisitor { + _openSwiftUIUnimplementedFailure() + } + + package static func accepts(_ query: Q.Type, at queryIndex: Int) -> Bool { + _openSwiftUIUnimplementedFailure() + } +} // MARK: - StyleContextVisitor @@ -75,12 +432,28 @@ package protocol StyleContextVisitor { mutating func visit(_ context: C.Type) where C: StyleContext } +// MARK: - StyleContextDescriptor [WIP] + +package struct StyleContextDescriptor: TupleDescriptor { + package static var typeCache: [ObjectIdentifier: TupleTypeDescription] = [:] + + package static var descriptor: UnsafeRawPointer { + _openSwiftUIUnimplementedFailure() + } +} + +extension TypeConformance where P == StyleContextDescriptor { + package func visitType(visitor: UnsafeMutablePointer) where V: StyleContextVisitor { + _openSwiftUIUnimplementedFailure() + } +} + // MARK: - QueryVisitor private struct QueryVisitor: StyleContextVisitor where Context: StyleContext { - var accepts: Bool = false + var accepts: Bool - mutating func visit(_ context: C.Type) where C : StyleContext { + mutating func visit(_ context: C.Type) where C: StyleContext { accepts = accepts ? true : Context.self == context } } From b3812ebb3ebfbc85595ea9035200ed243090f544 Mon Sep 17 00:00:00 2001 From: Kyle Date: Mon, 27 Oct 2025 01:14:38 +0800 Subject: [PATCH 3/8] Update ProtocolDescriptor --- .../Event/Gesture/GestureDebug.swift | 2 +- .../Event/Gesture/GestureDescriptor.swift | 4 +-- Sources/OpenSwiftUICore/View/View.swift | 2 +- Sources/OpenSwiftUICore/View/ViewDebug.swift | 8 ++--- .../OpenSwiftUI_SPI/Util/ProtocolDescriptor.c | 31 +++++++++++++++++++ .../OpenSwiftUI_SPI/Util/ProtocolDescriptor.h | 23 +++++++++++--- 6 files changed, 58 insertions(+), 12 deletions(-) diff --git a/Sources/OpenSwiftUICore/Event/Gesture/GestureDebug.swift b/Sources/OpenSwiftUICore/Event/Gesture/GestureDebug.swift index cbf1d7085..961dc2195 100644 --- a/Sources/OpenSwiftUICore/Event/Gesture/GestureDebug.swift +++ b/Sources/OpenSwiftUICore/Event/Gesture/GestureDebug.swift @@ -136,7 +136,7 @@ extension _GestureOutputs { } reallyWrap( type, - kind: conformsToProtocol(type, _OpenSwiftUI_gestureModifierProtocolDescriptor()) ? .modifier : .primitive, + kind: conformsToProtocol(type, _gestureModifierProtocolDescriptor()) ? .modifier : .primitive, properties: properties, inputs: inputs, data: (debugData, nil) diff --git a/Sources/OpenSwiftUICore/Event/Gesture/GestureDescriptor.swift b/Sources/OpenSwiftUICore/Event/Gesture/GestureDescriptor.swift index 0c0240c23..17dcab2bf 100644 --- a/Sources/OpenSwiftUICore/Event/Gesture/GestureDescriptor.swift +++ b/Sources/OpenSwiftUICore/Event/Gesture/GestureDescriptor.swift @@ -12,7 +12,7 @@ package struct GestureDescriptor: TupleDescriptor { package static var typeCache: [ObjectIdentifier: TupleTypeDescription] = [:] package static var descriptor: UnsafeRawPointer { - _OpenSwiftUI_gestureProtocolDescriptor() + _gestureProtocolDescriptor() } } @@ -22,6 +22,6 @@ package struct GestureModifierDescriptor: TupleDescriptor { package static var typeCache: [ObjectIdentifier: TupleTypeDescription] = [:] package static var descriptor: UnsafeRawPointer { - _OpenSwiftUI_gestureModifierProtocolDescriptor() + _gestureModifierProtocolDescriptor() } } diff --git a/Sources/OpenSwiftUICore/View/View.swift b/Sources/OpenSwiftUICore/View/View.swift index 32d95c68c..a4858bebf 100644 --- a/Sources/OpenSwiftUICore/View/View.swift +++ b/Sources/OpenSwiftUICore/View/View.swift @@ -177,7 +177,7 @@ package struct ViewDescriptor: TupleDescriptor, ConditionalProtocolDescriptor { package static var typeCache: [ObjectIdentifier: TupleTypeDescription] = [:] package static var descriptor: UnsafeRawPointer { - _OpenSwiftUI_viewProtocolDescriptor() + _viewProtocolDescriptor() } private static var conditionalCache: [ObjectIdentifier: ConditionalTypeDescriptor] = [:] diff --git a/Sources/OpenSwiftUICore/View/ViewDebug.swift b/Sources/OpenSwiftUICore/View/ViewDebug.swift index ad595b378..5eb8ffd87 100644 --- a/Sources/OpenSwiftUICore/View/ViewDebug.swift +++ b/Sources/OpenSwiftUICore/View/ViewDebug.swift @@ -385,8 +385,8 @@ extension _ViewDebug.Data { self.type = String(reflecting: anyType) self.readableType = Metadata(anyType).description self.flags = [ - conformsToProtocol(anyType, _OpenSwiftUI_viewProtocolDescriptor()) ? .view : [], - conformsToProtocol(anyType, _OpenSwiftUI_viewModifierProtocolDescriptor()) ? .viewModifier : [], + conformsToProtocol(anyType, _viewProtocolDescriptor()) ? .view : [], + conformsToProtocol(anyType, _viewModifierProtocolDescriptor()) ? .viewModifier : [], ] self.value = nil self.subattributes = nil @@ -398,8 +398,8 @@ extension _ViewDebug.Data { self.type = String(reflecting: anyType) self.readableType = Metadata(anyType).description self.flags = [ - conformsToProtocol(anyType, _OpenSwiftUI_viewProtocolDescriptor()) ? .view : [], - conformsToProtocol(anyType, _OpenSwiftUI_viewModifierProtocolDescriptor()) ? .viewModifier : [], + conformsToProtocol(anyType, _viewProtocolDescriptor()) ? .view : [], + conformsToProtocol(anyType, _viewModifierProtocolDescriptor()) ? .viewModifier : [], ] self.value = serializeValue ? SerializedAttribute.serialize(value: value) : nil self.subattributes = subattributes diff --git a/Sources/OpenSwiftUI_SPI/Util/ProtocolDescriptor.c b/Sources/OpenSwiftUI_SPI/Util/ProtocolDescriptor.c index 253291226..a2e4d0bb7 100644 --- a/Sources/OpenSwiftUI_SPI/Util/ProtocolDescriptor.c +++ b/Sources/OpenSwiftUI_SPI/Util/ProtocolDescriptor.c @@ -1,6 +1,9 @@ // // ProtocolDescriptor.c // OpenSwiftUI_SPI +// +// Audit for 6.5.4 +// Status: Complete #include "ProtocolDescriptor.h" @@ -36,3 +39,31 @@ const void *$s15OpenSwiftUICore15GestureModifierMp; const void *_OpenSwiftUI_gestureModifierProtocolDescriptor(void) { return &$s15OpenSwiftUICore15GestureModifierMp; } + +OPENSWIFTUI_EXPORT +const void *$s15OpenSwiftUICore20DefaultStyleModifierMp; + +const void *_OpenSwiftUI_defaultStyleModifierProtocolDescriptor(void) { + return &$s15OpenSwiftUICore15GestureModifierMp; +} + +OPENSWIFTUI_EXPORT +const void *$s15OpenSwiftUICore21StyleOverrideModifierMp; + +const void *_OpenSwiftUI_styleOverrideModifierProtocolDescriptor(void) { + return &$s15OpenSwiftUICore21StyleOverrideModifierMp; +} + +OPENSWIFTUI_EXPORT +const void *$s15OpenSwiftUICore27StyleWriterOverrideModifierMp; + +const void *_OpenSwiftUI_styleWriterOverrideModifierProtocolDescriptor(void) { + return &$s15OpenSwiftUICore27StyleWriterOverrideModifierMp; +} + +OPENSWIFTUI_EXPORT +const void *$s15OpenSwiftUICore12StyleContextMp; + +const void *_OpenSwiftUI_styleContextProtocolDescriptor(void) { + return &$s15OpenSwiftUICore12StyleContextMp; +} diff --git a/Sources/OpenSwiftUI_SPI/Util/ProtocolDescriptor.h b/Sources/OpenSwiftUI_SPI/Util/ProtocolDescriptor.h index 14effe173..aa1625e98 100644 --- a/Sources/OpenSwiftUI_SPI/Util/ProtocolDescriptor.h +++ b/Sources/OpenSwiftUI_SPI/Util/ProtocolDescriptor.h @@ -1,6 +1,9 @@ // // ProtocolDescriptor_h // OpenSwiftUI_SPI +// +// Audit for 6.5.4 +// Status: Complete #ifndef ProtocolDescriptor_h #define ProtocolDescriptor_h @@ -10,16 +13,28 @@ OPENSWIFTUI_ASSUME_NONNULL_BEGIN OPENSWIFTUI_EXPORT -const void *_OpenSwiftUI_viewProtocolDescriptor(void); +const void *_OpenSwiftUI_viewProtocolDescriptor(void) OPENSWIFTUI_SWIFT_NAME(_viewProtocolDescriptor()); + +OPENSWIFTUI_EXPORT +const void *_OpenSwiftUI_viewModifierProtocolDescriptor(void) OPENSWIFTUI_SWIFT_NAME(_viewModifierProtocolDescriptor()); + +OPENSWIFTUI_EXPORT +const void *_OpenSwiftUI_gestureProtocolDescriptor(void) OPENSWIFTUI_SWIFT_NAME(_gestureProtocolDescriptor()); + +OPENSWIFTUI_EXPORT +const void *_OpenSwiftUI_gestureModifierProtocolDescriptor(void) OPENSWIFTUI_SWIFT_NAME(_gestureModifierProtocolDescriptor()); + +OPENSWIFTUI_EXPORT +const void *_OpenSwiftUI_defaultStyleModifierProtocolDescriptor(void) OPENSWIFTUI_SWIFT_NAME(_defaultStyleModifierProtocolDescriptor()); OPENSWIFTUI_EXPORT -const void *_OpenSwiftUI_viewModifierProtocolDescriptor(void); +const void *_OpenSwiftUI_styleOverrideModifierProtocolDescriptor(void) OPENSWIFTUI_SWIFT_NAME(_styleOverrideModifierProtocolDescriptor()); OPENSWIFTUI_EXPORT -const void *_OpenSwiftUI_gestureProtocolDescriptor(void); +const void *_OpenSwiftUI_styleWriterOverrideModifierProtocolDescriptor(void) OPENSWIFTUI_SWIFT_NAME(_styleWriterOverrideModifierProtocolDescriptor()); OPENSWIFTUI_EXPORT -const void *_OpenSwiftUI_gestureModifierProtocolDescriptor(void); +const void *_OpenSwiftUI_styleContextProtocolDescriptor(void) OPENSWIFTUI_SWIFT_NAME(_styleContextProtocolDescriptor()); OPENSWIFTUI_ASSUME_NONNULL_END From e4c081d51acf83a3d57e4c4dfb8a278cf9091c0c Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 26 Oct 2025 23:18:19 +0800 Subject: [PATCH 4/8] Update StyleContextDescriptor --- Sources/OpenSwiftUICore/View/Style/StyleContext.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Sources/OpenSwiftUICore/View/Style/StyleContext.swift b/Sources/OpenSwiftUICore/View/Style/StyleContext.swift index 18c5f1bf6..5fbf8c564 100644 --- a/Sources/OpenSwiftUICore/View/Style/StyleContext.swift +++ b/Sources/OpenSwiftUICore/View/Style/StyleContext.swift @@ -6,6 +6,8 @@ // Status: WIP // ID: 2EF43D8D991A83294E93848563DD541B (SwiftUICore) +import OpenSwiftUI_SPI + // MARK: - StyleContext package protocol StyleContext { @@ -432,19 +434,19 @@ package protocol StyleContextVisitor { mutating func visit(_ context: C.Type) where C: StyleContext } -// MARK: - StyleContextDescriptor [WIP] +// MARK: - StyleContextDescriptor package struct StyleContextDescriptor: TupleDescriptor { package static var typeCache: [ObjectIdentifier: TupleTypeDescription] = [:] package static var descriptor: UnsafeRawPointer { - _openSwiftUIUnimplementedFailure() + _styleContextProtocolDescriptor() } } extension TypeConformance where P == StyleContextDescriptor { package func visitType(visitor: UnsafeMutablePointer) where V: StyleContextVisitor { - _openSwiftUIUnimplementedFailure() + visitor.pointee.visit(unsafeBitCast(self, to: (any StyleContext.Type).self)) } } From 0322c2afa93e2c2df2636be3c924d5a0022895fa Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 26 Oct 2025 23:31:26 +0800 Subject: [PATCH 5/8] Update View + StyleContext --- .../View/Configuration/StaticIf.swift | 24 +++++++++++++++---- .../View/Style/StyleContext.swift | 7 +++--- 2 files changed, 22 insertions(+), 9 deletions(-) rename Sources/{OpenSwiftUI => OpenSwiftUICore}/View/Configuration/StaticIf.swift (95%) diff --git a/Sources/OpenSwiftUI/View/Configuration/StaticIf.swift b/Sources/OpenSwiftUICore/View/Configuration/StaticIf.swift similarity index 95% rename from Sources/OpenSwiftUI/View/Configuration/StaticIf.swift rename to Sources/OpenSwiftUICore/View/Configuration/StaticIf.swift index f2321bf42..57d04e763 100644 --- a/Sources/OpenSwiftUI/View/Configuration/StaticIf.swift +++ b/Sources/OpenSwiftUICore/View/Configuration/StaticIf.swift @@ -1,12 +1,10 @@ // // StaticIf.swift -// OpenSwiftUI +// OpenSwiftUICore // -// Audited for 6.0.87 +// Audited for 6.5.4 // Status: Complete -import OpenSwiftUICore - /// A container view that conditionally renders one of two views based on a `ViewInputPredicate`. /// /// `StaticIf` makes view selection decisions based on the evaluation of a `ViewInputPredicate` @@ -228,7 +226,23 @@ extension ViewModifier { /// /// - Parameter predicate: The predicate type used to evaluate against view inputs. /// - Returns: A conditional modifier that applies the current modifier only when the predicate is true. - package func requiring(_ predicate: Predicate.Type) -> StaticIf where Predicate: ViewInputPredicate { + package func requiring( + _ predicate: Predicate.Type + ) -> StaticIf< + Predicate, + Self, + EmptyModifier + > where Predicate: ViewInputPredicate { StaticIf(predicate, then: self) } + + package func requiring( + _ queries: repeat (each Q).Type + ) -> StaticIf< + StyleContextAcceptsPredicate<(repeat each Q)>, + Self, + EmptyModifier + > where repeat each Q: StyleContext { + StaticIf(StyleContextAcceptsPredicate<(repeat each Q)>.self, then: self) + } } diff --git a/Sources/OpenSwiftUICore/View/Style/StyleContext.swift b/Sources/OpenSwiftUICore/View/Style/StyleContext.swift index 5fbf8c564..ae64a0c65 100644 --- a/Sources/OpenSwiftUICore/View/Style/StyleContext.swift +++ b/Sources/OpenSwiftUICore/View/Style/StyleContext.swift @@ -295,7 +295,7 @@ extension StyleContext where Self == MenuBarExtraWindowStyleContext { } } -// MARK: View + StyleContext [WIP] +// MARK: View + StyleContext @available(OpenSwiftUI_v1_0, *) extension View { @@ -304,12 +304,11 @@ extension View { } package func styleContext(_ context: C, if predicate: P) -> some View where C: StyleContext, P: ViewInputPredicate { -// modifier(StyleContextWriter() .requiring(P.self)) - _openSwiftUIUnimplementedFailure() + modifier(StyleContextWriter().requiring(P.self)) } package func styleContext(_ context: C, in requiredContext: P) -> some View where C: StyleContext, P: StyleContext { - _openSwiftUIUnimplementedFailure() + modifier(StyleContextWriter().requiring(P.self)) } /// Sets the style context of `self` to the default context. From ce142fcc5abfb5a3b4dd83664f3f9af022e2ffe2 Mon Sep 17 00:00:00 2001 From: Kyle Date: Mon, 27 Oct 2025 00:45:15 +0800 Subject: [PATCH 6/8] Update TupleStyleContext --- .../View/Style/StyleContext.swift | 68 +++++++++++++++++-- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/Sources/OpenSwiftUICore/View/Style/StyleContext.swift b/Sources/OpenSwiftUICore/View/Style/StyleContext.swift index ae64a0c65..628cebbde 100644 --- a/Sources/OpenSwiftUICore/View/Style/StyleContext.swift +++ b/Sources/OpenSwiftUICore/View/Style/StyleContext.swift @@ -3,9 +3,10 @@ // OpenSwiftUICore // // Audited for 6.5.4 -// Status: WIP +// Status: Complete // ID: 2EF43D8D991A83294E93848563DD541B (SwiftUICore) +import OpenAttributeGraphShims import OpenSwiftUI_SPI // MARK: - StyleContext @@ -411,19 +412,74 @@ extension _ViewListCountInputs { package typealias StyleContextPrintingModifier = EmptyModifier -// MARK: - TupleStyleContext [WIP] +// MARK: - TupleStyleContext package struct TupleStyleContext: StyleContext { - package static func acceptsAny(_: repeat (each Q).Type) -> Bool where repeat each Q: StyleContext { - _openSwiftUIUnimplementedFailure() + package static func acceptsAny(_ queries: repeat (each Q).Type) -> Bool where repeat each Q: StyleContext { + let desc = StyleContextDescriptor.tupleDescription(TupleType(T.self)) + var visitor = QueryVisitor(accepts: false) + for (_, descriptor) in desc.contentTypes { + descriptor.visitType(visitor: &visitor) + } + return false } package static func visitStyle(_ visitor: inout V) where V: StyleContextVisitor { - _openSwiftUIUnimplementedFailure() + let desc = StyleContextDescriptor.tupleDescription(TupleType(T.self)) + for (_, descriptor) in desc.contentTypes { + descriptor.visitType(visitor: &visitor) + } } package static func accepts(_ query: Q.Type, at queryIndex: Int) -> Bool { - _openSwiftUIUnimplementedFailure() + let selfDesc = StyleContextDescriptor.tupleDescription(TupleType(T.self)) + let queryDesc = StyleContextDescriptor.tupleDescription(TupleType(Q.self)) + let selfCount = selfDesc.contentTypes.count + let queryCount = queryDesc.contentTypes.count + guard selfCount >= queryCount else { + return false + } + var visitor = QueryAtIndexVisitor( + index: queryIndex, + queryDesc: queryDesc, + accepts: true + ) + for (index, descriptor) in selfDesc.contentTypes { + guard index >= queryIndex, index < queryCount else { + continue + } + descriptor.visitType(visitor: &visitor) + } + return visitor.accepts + } + + private struct QueryAtIndexVisitor: StyleContextVisitor { + var index: Int + var queryDesc: TupleTypeDescription + var accepts: Bool + + mutating func visit(_ context: C.Type) where C: StyleContext { + var visitor = ContextAcceptsVisitor(accepts: false) + queryDesc.contentTypes[index].1.visitType(visitor: &visitor) + accepts = accepts && visitor.accepts + index &+= 1 + } + } + + private struct QueryVisitor: StyleContextVisitor where repeat each U: StyleContext { + var accepts: Bool + + mutating func visit(_ context: C.Type) where C: StyleContext { + accepts = accepts ? true : C.acceptsAny(repeat (each U).self) + } + } + + private struct ContextAcceptsVisitor: StyleContextVisitor where U: StyleContext { + var accepts: Bool + + mutating func visit(_ context: C.Type) where C: StyleContext { + accepts = U.accepts(context, at: 0) + } } } From 52dc129b954feed48eb70ac0efbd73aff3650a5a Mon Sep 17 00:00:00 2001 From: Kyle Date: Mon, 27 Oct 2025 02:28:29 +0800 Subject: [PATCH 7/8] Add StyleContextTests --- .../View/Style/StyleContextTests.swift | 253 ++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 Tests/OpenSwiftUICoreTests/View/Style/StyleContextTests.swift diff --git a/Tests/OpenSwiftUICoreTests/View/Style/StyleContextTests.swift b/Tests/OpenSwiftUICoreTests/View/Style/StyleContextTests.swift new file mode 100644 index 000000000..2bc9cff1a --- /dev/null +++ b/Tests/OpenSwiftUICoreTests/View/Style/StyleContextTests.swift @@ -0,0 +1,253 @@ +// +// StyleContextTests.swift +// OpenSwiftUICoreTests +// +// Author: Claude Code with Claude Sonnet 4.5 + +@_spi(ForOpenSwiftUIOnly) +import OpenSwiftUICore +import Testing + +@MainActor +struct TupleStyleContextTests { + @Test("Test TupleStyleContext accepts single context at index 0") + func acceptsSingleContextAtIndexZero() { + typealias SingleContext = TupleStyleContext<(WindowRootContext)> + #expect(SingleContext.accepts(WindowRootContext.self, at: 0)) + #expect(!SingleContext.accepts(MenuStyleContext.self, at: 0)) + #expect(!SingleContext.accepts(ToolbarStyleContext.self, at: 0)) + } + + @Test("Test TupleStyleContext accepts multiple contexts at different indices") + func acceptsMultipleContextsAtDifferentIndices() { + typealias DoubleContext = TupleStyleContext<(WindowRootContext, MenuStyleContext)> + #expect(DoubleContext.accepts(WindowRootContext.self, at: 0)) + #expect(DoubleContext.accepts(MenuStyleContext.self, at: 1)) + #expect(!DoubleContext.accepts(ToolbarStyleContext.self, at: 0)) + } + + @Test("Test TupleStyleContext accepts with tuple query type") + func acceptsWithTupleQueryType() { + typealias TripleContext = TupleStyleContext<(WindowRootContext, MenuStyleContext, ToolbarStyleContext)> + typealias DoubleQuery = TupleStyleContext<(WindowRootContext, MenuStyleContext)> + #expect(!TripleContext.accepts(DoubleQuery.self, at: 0)) + #expect(TripleContext.accepts(DoubleQuery.self, at: 1)) + #expect(TripleContext.accepts(DoubleQuery.self, at: 2)) + } + + @Test("Test TupleStyleContext rejects query when count exceeds context count") + func rejectsQueryWhenCountExceedsContextCount() { + typealias SingleContext = TupleStyleContext<(WindowRootContext)> + typealias DoubleQuery = TupleStyleContext<(WindowRootContext, MenuStyleContext)> + #expect(!SingleContext.accepts(DoubleQuery.self, at: 0)) + } + + @Test("Test TupleStyleContext accepts at valid query index") + func acceptsAtValidQueryIndex() { + typealias QuadContext = TupleStyleContext<(WindowRootContext, MenuStyleContext, ToolbarStyleContext, TableStyleContext)> + #expect(QuadContext.accepts(MenuStyleContext.self, at: 1)) + #expect(QuadContext.accepts(ToolbarStyleContext.self, at: 2)) + #expect(QuadContext.accepts(TableStyleContext.self, at: 3)) + } + + @Test("Test TupleStyleContext with out of bounds query index") + func outOfBoundsQueryIndex() { + typealias DoubleContext = TupleStyleContext<(WindowRootContext, MenuStyleContext)> + #expect(DoubleContext.accepts(ToolbarStyleContext.self, at: 2)) + #expect(DoubleContext.accepts(WindowRootContext.self, at: 5)) + } + + @Test("Test TupleStyleContext with homogeneous tuple") + func acceptsWithHomogeneousTuple() { + typealias HomogeneousContext = TupleStyleContext<(MenuStyleContext, MenuStyleContext, MenuStyleContext)> + #expect(HomogeneousContext.accepts(MenuStyleContext.self, at: 0)) + #expect(HomogeneousContext.accepts(MenuStyleContext.self, at: 1)) + #expect(HomogeneousContext.accepts(MenuStyleContext.self, at: 2)) + } + + @Test("Test TupleStyleContext with different context types") + func acceptsWithDifferentContextTypes() { + typealias MixedContext = TupleStyleContext<( + WindowRootContext, + MenuStyleContext, + ToolbarStyleContext, + ScrollViewStyleContext, + SheetStyleContext + )> + #expect(MixedContext.accepts(WindowRootContext.self, at: 0)) + #expect(MixedContext.accepts(MenuStyleContext.self, at: 1)) + #expect(MixedContext.accepts(ToolbarStyleContext.self, at: 2)) + #expect(MixedContext.accepts(ScrollViewStyleContext.self, at: 3)) + #expect(MixedContext.accepts(SheetStyleContext.self, at: 4)) + #expect(!MixedContext.accepts(TableStyleContext.self, at: 0)) + } + + @Test("Test TupleStyleContext accepts nested tuple query") + func acceptsNestedTupleQuery() { + typealias LargeContext = TupleStyleContext<( + WindowRootContext, + MenuStyleContext, + ToolbarStyleContext, + TableStyleContext, + SheetStyleContext + )> + typealias TripleQuery = TupleStyleContext<(MenuStyleContext, ToolbarStyleContext, TableStyleContext)> + #expect(LargeContext.accepts(TripleQuery.self, at: 1)) + #expect(!LargeContext.accepts(TripleQuery.self, at: 0)) + #expect(LargeContext.accepts(TripleQuery.self, at: 3)) + } + + @Test("Test TupleStyleContext accepts with accessibility contexts") + func acceptsWithAccessibilityContexts() { + typealias AccessibilityContext = TupleStyleContext<( + AccessibilityRepresentableStyleContext, + AccessibilityQuickActionStyleContext + )> + #expect(AccessibilityContext.accepts(AccessibilityRepresentableStyleContext.self, at: 0)) + #expect(AccessibilityContext.accepts(AccessibilityQuickActionStyleContext.self, at: 1)) + } + + @Test("Test TupleStyleContext accepts with container and list contexts") + func acceptsWithContainerAndListContexts() { + typealias ContainerContext = TupleStyleContext<( + ContainerStyleContext, + ContentListStyleContext, + MultimodalListContext + )> + #expect(ContainerContext.accepts(ContainerStyleContext.self, at: 0)) + #expect(ContainerContext.accepts(ContentListStyleContext.self, at: 1)) + #expect(ContainerContext.accepts(MultimodalListContext.self, at: 2)) + } + + @Test("Test TupleStyleContext with sidebar and inspector contexts") + func acceptsWithSidebarAndInspectorContexts() { + typealias SidebarContext = TupleStyleContext<(SidebarStyleContext, InspectorStyleContext)> + #expect(SidebarContext.accepts(SidebarStyleContext.self, at: 0)) + #expect(SidebarContext.accepts(InspectorStyleContext.self, at: 1)) + #expect(!SidebarContext.accepts(WindowRootContext.self, at: 0)) + } + + @Test("Test TupleStyleContext with sheet and dialog contexts") + func acceptsWithSheetAndDialogContexts() { + typealias SheetContext = TupleStyleContext<( + SheetStyleContext, + SheetToolbarStyleContext, + DialogActionStyleContext + )> + #expect(SheetContext.accepts(SheetStyleContext.self, at: 0)) + #expect(SheetContext.accepts(SheetToolbarStyleContext.self, at: 1)) + #expect(SheetContext.accepts(DialogActionStyleContext.self, at: 2)) + } +} + +@MainActor +struct StyleContextVisitorTests { + private struct CollectingVisitor: StyleContextVisitor { + var visitedTypes: [String] = [] + + mutating func visit(_ context: C.Type) where C: StyleContext { + visitedTypes.append(String(describing: context)) + } + } + + @Test("Test TupleStyleContext visitStyle with single context") + func visitStyleWithSingleContext() { + typealias SingleContext = TupleStyleContext<(WindowRootContext)> + var visitor = CollectingVisitor() + SingleContext.visitStyle(&visitor) + #expect(visitor.visitedTypes.contains("WindowRootContext")) + } + + @Test("Test TupleStyleContext visitStyle with multiple contexts") + func visitStyleWithMultipleContexts() { + typealias TripleContext = TupleStyleContext<(WindowRootContext, MenuStyleContext, ToolbarStyleContext)> + var visitor = CollectingVisitor() + TripleContext.visitStyle(&visitor) + #expect(visitor.visitedTypes.contains("WindowRootContext")) + #expect(visitor.visitedTypes.contains("MenuStyleContext")) + #expect(visitor.visitedTypes.contains("ToolbarStyleContext")) + } +} + +@MainActor +struct ConcreteStyleContextTests { + @Test("Test WindowRootContext accepts itself") + func windowRootContextAcceptsItself() { + #expect(WindowRootContext.accepts(WindowRootContext.self, at: 0)) + #expect(!WindowRootContext.accepts(MenuStyleContext.self, at: 0)) + } + + @Test("Test NoStyleContext accepts itself") + func noStyleContextAcceptsItself() { + #expect(NoStyleContext.accepts(NoStyleContext.self, at: 0)) + #expect(!NoStyleContext.accepts(WindowRootContext.self, at: 0)) + } + + @Test("Test acceptsTop convenience method") + func acceptsTopConvenienceMethod() { + #expect(WindowRootContext.acceptsTop(WindowRootContext.self)) + #expect(!WindowRootContext.acceptsTop(MenuStyleContext.self)) + + typealias DoubleContext = TupleStyleContext<(WindowRootContext, MenuStyleContext)> + #expect(DoubleContext.acceptsTop(WindowRootContext.self)) + #expect(!DoubleContext.acceptsTop(MenuStyleContext.self)) + } + + @Test("Test concrete context initialization") + func concreteContextInitialization() { + _ = WindowRootContext() + _ = AccessibilityRepresentableStyleContext() + _ = AccessibilityQuickActionStyleContext() + _ = ContainerStyleContext() + _ = ContentListStyleContext() + _ = DocumentStyleContext() + _ = ControlGroupStyleContext() + _ = DialogActionStyleContext() + _ = HostingConfigurationContext() + _ = MenuStyleContext() + _ = MultimodalListContext() + _ = MultimodalListGridContext() + _ = MultimodalListStackContext() + _ = NoStyleContext() + _ = ScrollViewStyleContext() + _ = TextInputSuggestionsContext() + _ = SectionHeaderStyleContext() + _ = SheetStyleContext() + _ = SheetToolbarStyleContext() + _ = SidebarStyleContext() + _ = SwipeActionsStyleContext() + _ = TableStyleContext() + _ = ToolbarStyleContext() + _ = InspectorStyleContext() + _ = MenuBarExtraWindowStyleContext() + } + + @Test("Test concrete context static accessors") + func concreteContextStaticAccessors() { + _ = WindowRootContext.windowRoot + _ = AccessibilityRepresentableStyleContext.accessibilityRepresentable + _ = AccessibilityQuickActionStyleContext.accessibilityQuickAction + _ = ContainerStyleContext.container + _ = ContentListStyleContext.contentList + _ = DocumentStyleContext.document + _ = ControlGroupStyleContext.controlGroup + _ = DialogActionStyleContext.dialogAction + _ = HostingConfigurationContext.hostingConfiguration + _ = MenuStyleContext.menu + _ = MultimodalListContext.multimodalList + _ = MultimodalListGridContext.multimodalListGrid + _ = MultimodalListStackContext.multimodalListStack + _ = NoStyleContext.none + _ = ScrollViewStyleContext.scrollView + _ = TextInputSuggestionsContext.textInputSuggestions + _ = SectionHeaderStyleContext.sectionHeader + _ = SheetStyleContext.sheet + _ = SheetToolbarStyleContext.sheetToolbar + _ = SidebarStyleContext.sidebar + _ = SwipeActionsStyleContext.swipeActions + _ = TableStyleContext.table + _ = ToolbarStyleContext.toolbar + _ = InspectorStyleContext.inspector + _ = MenuBarExtraWindowStyleContext.menuBarExtraWindow + } +} From dbdfba806a69ba13718e51f864bc2e96197d5632 Mon Sep 17 00:00:00 2001 From: Kyle Date: Mon, 27 Oct 2025 02:49:21 +0800 Subject: [PATCH 8/8] Disable TupleID usage for no toolchain setup env --- Tests/OpenSwiftUICoreTests/View/Style/StyleContextTests.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tests/OpenSwiftUICoreTests/View/Style/StyleContextTests.swift b/Tests/OpenSwiftUICoreTests/View/Style/StyleContextTests.swift index 2bc9cff1a..6a3512819 100644 --- a/Tests/OpenSwiftUICoreTests/View/Style/StyleContextTests.swift +++ b/Tests/OpenSwiftUICoreTests/View/Style/StyleContextTests.swift @@ -4,11 +4,13 @@ // // Author: Claude Code with Claude Sonnet 4.5 +import OpenAttributeGraphShims @_spi(ForOpenSwiftUIOnly) import OpenSwiftUICore import Testing @MainActor +@Suite(.enabled(if: swiftToolchainSupported)) struct TupleStyleContextTests { @Test("Test TupleStyleContext accepts single context at index 0") func acceptsSingleContextAtIndexZero() { @@ -141,6 +143,7 @@ struct TupleStyleContextTests { } @MainActor +@Suite(.enabled(if: swiftToolchainSupported)) struct StyleContextVisitorTests { private struct CollectingVisitor: StyleContextVisitor { var visitedTypes: [String] = [] @@ -170,6 +173,7 @@ struct StyleContextVisitorTests { } @MainActor +@Suite(.enabled(if: swiftToolchainSupported)) struct ConcreteStyleContextTests { @Test("Test WindowRootContext accepts itself") func windowRootContextAcceptsItself() {