From bf5ecf00ced0bbb8678b6372962ed69607be40fd Mon Sep 17 00:00:00 2001 From: Kirby Turner Date: Wed, 14 Jun 2023 13:26:48 -0400 Subject: [PATCH 1/5] Add reference documentation to Observation symbols. --- .../Sources/Observation/Observable.swift | 34 +++++++++++++++++++ .../Observation/ObservationRegistrar.swift | 31 +++++++++++++++++ .../Observation/ObservationTracking.swift | 26 ++++++++++++++ 3 files changed, 91 insertions(+) diff --git a/stdlib/public/Observation/Sources/Observation/Observable.swift b/stdlib/public/Observation/Sources/Observation/Observable.swift index cc7d1f5732c3b..ee30b8a27f076 100644 --- a/stdlib/public/Observation/Sources/Observation/Observable.swift +++ b/stdlib/public/Observation/Sources/Observation/Observable.swift @@ -10,11 +10,36 @@ //===----------------------------------------------------------------------===// +/// A type that emits notifications to observers when underlying data changes. +/// +/// Conforming to this protocol signals to other APIs that the type supports +/// observation. However, applying the `Observable` protocol by itself to a +/// type doesn't add observation functionality to the type. Instead, always use +/// the ``Observation/Observable-swift.macro`` macro when adding observation +/// support to a type. @available(SwiftStdlib 5.9, *) @_marker public protocol Observable { } #if $Macros && hasAttribute(attached) +/// Defines and implements conformance of the Observable protocol. +/// +/// This macro adds observation support to a custom type and conforms the type +/// to the ``Observation/Observable-swift.protocol`` protocol. For example, the +/// following code apply the `Observable` macro to the type `Car` making it +/// observable: +/// +/// ```swift +/// @Observable class Car { +/// var name: String = "" +/// var needsRepairs: Bool = false +/// +/// init(name: String, needsRepairs: Bool = false) { +/// self.name = name +/// self.needsRepairs = needsRepairs +/// } +///} +///``` @available(SwiftStdlib 5.9, *) #if OBSERVATION_SUPPORTS_PEER_MACROS @attached(member, names: named(_$observationRegistrar), named(access), named(withMutation)) @@ -26,6 +51,10 @@ public macro Observable() = #externalMacro(module: "ObservationMacros", type: "ObservableMacro") +/// Synthesizes a property for accessors. +/// +/// The ``Observation`` framework uses this macro. Its use outside of the +/// framework isn't necessary. @available(SwiftStdlib 5.9, *) @attached(accessor, names: named(init), named(get), named(set)) #if OBSERVATION_SUPPORTS_PEER_MACROS @@ -34,6 +63,11 @@ public macro Observable() = public macro ObservationTracked() = #externalMacro(module: "ObservationMacros", type: "ObservationTrackedMacro") +/// Turns off observation tracking of a property. +/// +/// By default, an object can observe any property of an observable type that +/// is accessible to the observing object. To prevent observation of an +/// accessible property, attach the `ObservationIgnored` macro to the property. @available(SwiftStdlib 5.9, *) @attached(accessor, names: named(willSet)) public macro ObservationIgnored() = diff --git a/stdlib/public/Observation/Sources/Observation/ObservationRegistrar.swift b/stdlib/public/Observation/Sources/Observation/ObservationRegistrar.swift index ccf9c63616aa1..c49750de76066 100644 --- a/stdlib/public/Observation/Sources/Observation/ObservationRegistrar.swift +++ b/stdlib/public/Observation/Sources/Observation/ObservationRegistrar.swift @@ -9,6 +9,11 @@ // //===----------------------------------------------------------------------===// +/// Provides storage for tracking and access to data changes. +/// +/// You don't need to create an instance of `ObservationRegistrar` when using +/// the ``Observation/Observable-swift.macro`` macro to indicate observability +/// of a type. @available(SwiftStdlib 5.9, *) public struct ObservationRegistrar: Sendable { struct State: @unchecked Sendable { @@ -90,9 +95,20 @@ public struct ObservationRegistrar: Sendable { let context = Context() + /// Creates an instance of the observation registrar. + /// + /// You don't need to create an instance of + /// ``Observation/ObservationRegistrar`` when using the + /// ``Observation/Observable-swift.macro`` macro to indicate observably + /// of a type. public init() { } + /// Registers access to a specific property for observation. + /// + /// - Parameters: + /// - subject: An instance of an observable type. + /// - keyPath: The key path of an observed property. public func access( _ subject: Subject, keyPath: KeyPath @@ -106,6 +122,11 @@ public struct ObservationRegistrar: Sendable { } } + /// A property observation called before setting the value of the subject. + /// + /// - Parameters: + /// - subject: An instance of an observable type. + /// - keyPath: The key path of an observed property. public func willSet( _ subject: Subject, keyPath: KeyPath @@ -113,6 +134,11 @@ public struct ObservationRegistrar: Sendable { context.willSet(subject, keyPath: keyPath) } + /// A property observation called after setting the value of the subject. + /// + /// - Parameters: + /// - subject: An instance of an observable type. + /// - keyPath: The key path of an observed property. public func didSet( _ subject: Subject, keyPath: KeyPath @@ -120,6 +146,11 @@ public struct ObservationRegistrar: Sendable { } + /// Identifies mutations to the transactions registered for observers. + /// + /// - Parameters: + /// - of: An instance of an observable type. + /// - keyPath: The key path of an observed property. public func withMutation( of subject: Subject, keyPath: KeyPath, diff --git a/stdlib/public/Observation/Sources/Observation/ObservationTracking.swift b/stdlib/public/Observation/Sources/Observation/ObservationTracking.swift index d97d69186842d..28b2f1ed08784 100644 --- a/stdlib/public/Observation/Sources/Observation/ObservationTracking.swift +++ b/stdlib/public/Observation/Sources/Observation/ObservationTracking.swift @@ -80,6 +80,32 @@ public struct ObservationTracking { } } +/// Tracks access to properties. +/// +/// This method tracks access to any property within the `apply` closure, and +/// informs the caller of value changes made to participating properties by way +/// of the `onChange` closure. For example, the following code tracks changes +/// to the name of cars, but it doesn't track changes to any other property of +/// `Car`: +/// +/// ```swift +/// func render() { +/// withObservationTracking { +/// for car in cars { +/// print(car.name) +/// } +/// } onChange: { +/// print("Schedule renderer.") +/// } +/// } +/// ``` +/// +/// - Parameters: +/// - apply: A closure that contains properties to track. +/// - onChange: The closure invoked when the value of a property changes. +/// +/// - Returns: The value that the `apply` closure returns if it has a return +/// value; otherwise, there is no return value. @available(SwiftStdlib 5.9, *) public func withObservationTracking( _ apply: () -> T, From 37e6741dd29636b89db9885b4d87f2848ee299da Mon Sep 17 00:00:00 2001 From: Kirby Turner Date: Wed, 14 Jun 2023 13:53:59 -0400 Subject: [PATCH 2/5] Apply review feedback. --- .../public/Observation/Sources/Observation/Observable.swift | 4 ++-- .../Sources/Observation/ObservationRegistrar.swift | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/stdlib/public/Observation/Sources/Observation/Observable.swift b/stdlib/public/Observation/Sources/Observation/Observable.swift index ee30b8a27f076..8477afd41779b 100644 --- a/stdlib/public/Observation/Sources/Observation/Observable.swift +++ b/stdlib/public/Observation/Sources/Observation/Observable.swift @@ -53,7 +53,7 @@ public macro Observable() = /// Synthesizes a property for accessors. /// -/// The ``Observation`` framework uses this macro. Its use outside of the +/// The ``Observation`` module uses this macro. Its use outside of the /// framework isn't necessary. @available(SwiftStdlib 5.9, *) @attached(accessor, names: named(init), named(get), named(set)) @@ -63,7 +63,7 @@ public macro Observable() = public macro ObservationTracked() = #externalMacro(module: "ObservationMacros", type: "ObservationTrackedMacro") -/// Turns off observation tracking of a property. +/// Disables observation tracking of a property. /// /// By default, an object can observe any property of an observable type that /// is accessible to the observing object. To prevent observation of an diff --git a/stdlib/public/Observation/Sources/Observation/ObservationRegistrar.swift b/stdlib/public/Observation/Sources/Observation/ObservationRegistrar.swift index c49750de76066..f471b531476c7 100644 --- a/stdlib/public/Observation/Sources/Observation/ObservationRegistrar.swift +++ b/stdlib/public/Observation/Sources/Observation/ObservationRegistrar.swift @@ -148,6 +148,8 @@ public struct ObservationRegistrar: Sendable { /// Identifies mutations to the transactions registered for observers. /// + /// This method calls ``willset(_:keypath:)`` before the mutation. Then it + /// calls ``didset(_:keypath:)`` after the mutation. /// - Parameters: /// - of: An instance of an observable type. /// - keyPath: The key path of an observed property. From 410b77024a4d04bdc6b2d263cf9d49f9f0003c90 Mon Sep 17 00:00:00 2001 From: Kirby Turner Date: Wed, 14 Jun 2023 16:37:50 -0400 Subject: [PATCH 3/5] Apply suggested coding style. --- stdlib/public/Observation/Sources/Observation/Observable.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/public/Observation/Sources/Observation/Observable.swift b/stdlib/public/Observation/Sources/Observation/Observable.swift index 8477afd41779b..b1fcc8b625b91 100644 --- a/stdlib/public/Observation/Sources/Observation/Observable.swift +++ b/stdlib/public/Observation/Sources/Observation/Observable.swift @@ -30,7 +30,8 @@ /// observable: /// /// ```swift -/// @Observable class Car { +/// @Observable +/// class Car { /// var name: String = "" /// var needsRepairs: Bool = false /// From 837f6e0999ce5df1c623a2345ffdda53916c7187 Mon Sep 17 00:00:00 2001 From: Kirby Turner Date: Wed, 14 Jun 2023 17:40:57 -0400 Subject: [PATCH 4/5] Fix typo. --- stdlib/public/Observation/Sources/Observation/Observable.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/Observation/Sources/Observation/Observable.swift b/stdlib/public/Observation/Sources/Observation/Observable.swift index b1fcc8b625b91..f3c8e23b62d3c 100644 --- a/stdlib/public/Observation/Sources/Observation/Observable.swift +++ b/stdlib/public/Observation/Sources/Observation/Observable.swift @@ -26,7 +26,7 @@ /// /// This macro adds observation support to a custom type and conforms the type /// to the ``Observation/Observable-swift.protocol`` protocol. For example, the -/// following code apply the `Observable` macro to the type `Car` making it +/// following code applies the `Observable` macro to the type `Car` making it /// observable: /// /// ```swift From 367a7f6453de928cb057b309d89d323c502755cc Mon Sep 17 00:00:00 2001 From: Kirby Turner Date: Wed, 14 Jun 2023 17:50:57 -0400 Subject: [PATCH 5/5] Replace fenced code blocks with indentions. --- .../Sources/Observation/Observable.swift | 22 +++++++++---------- .../Observation/ObservationTracking.swift | 16 ++++++-------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/stdlib/public/Observation/Sources/Observation/Observable.swift b/stdlib/public/Observation/Sources/Observation/Observable.swift index f3c8e23b62d3c..fcd7fe4cff1d6 100644 --- a/stdlib/public/Observation/Sources/Observation/Observable.swift +++ b/stdlib/public/Observation/Sources/Observation/Observable.swift @@ -29,18 +29,16 @@ /// following code applies the `Observable` macro to the type `Car` making it /// observable: /// -/// ```swift -/// @Observable -/// class Car { -/// var name: String = "" -/// var needsRepairs: Bool = false -/// -/// init(name: String, needsRepairs: Bool = false) { -/// self.name = name -/// self.needsRepairs = needsRepairs -/// } -///} -///``` +/// @Observable +/// class Car { +/// var name: String = "" +/// var needsRepairs: Bool = false +/// +/// init(name: String, needsRepairs: Bool = false) { +/// self.name = name +/// self.needsRepairs = needsRepairs +/// } +/// } @available(SwiftStdlib 5.9, *) #if OBSERVATION_SUPPORTS_PEER_MACROS @attached(member, names: named(_$observationRegistrar), named(access), named(withMutation)) diff --git a/stdlib/public/Observation/Sources/Observation/ObservationTracking.swift b/stdlib/public/Observation/Sources/Observation/ObservationTracking.swift index 28b2f1ed08784..c6558fb3e38a4 100644 --- a/stdlib/public/Observation/Sources/Observation/ObservationTracking.swift +++ b/stdlib/public/Observation/Sources/Observation/ObservationTracking.swift @@ -88,17 +88,15 @@ public struct ObservationTracking { /// to the name of cars, but it doesn't track changes to any other property of /// `Car`: /// -/// ```swift -/// func render() { -/// withObservationTracking { -/// for car in cars { -/// print(car.name) +/// func render() { +/// withObservationTracking { +/// for car in cars { +/// print(car.name) +/// } +/// } onChange: { +/// print("Schedule renderer.") /// } -/// } onChange: { -/// print("Schedule renderer.") /// } -/// } -/// ``` /// /// - Parameters: /// - apply: A closure that contains properties to track.