Skip to content

Commit 25c9b67

Browse files
authored
Rename streamWithContinuation to makeStream (#92)
* Rename `streamWithContinuation` to `makeStream` With [SE-388: Async Stream Factory][se-0388] officially in Swift 5.9, we can deprecate our version of this API and back-port the official API in the library. [se-0388]: https://github.com/apple/swift-evolution/blob/main/proposals/0388-async-stream-factory.md * wip * Update Deprecations.swift
1 parent f68419a commit 25c9b67

File tree

4 files changed

+149
-110
lines changed

4 files changed

+149
-110
lines changed

Sources/Dependencies/ConcurrencySupport/AsyncStream.swift

Lines changed: 61 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,11 @@ extension AsyncStream {
3131
/// }
3232
/// ```
3333
///
34-
/// While your tests can use `AsyncStream.streamWithContinuation` to spin up a controllable stream
35-
/// for tests:
34+
/// While your tests can use `AsyncStream.makeStream` to spin up a controllable stream for tests:
3635
///
3736
/// ```swift
3837
/// func testScreenshots() {
39-
/// let screenshots = AsyncStream<Void>.streamWithContinuation()
38+
/// let screenshots = AsyncStream.makeStream(of: Void.self)
4039
///
4140
/// let model = withDependencies {
4241
/// $0.screenshots = { screenshots.stream }
@@ -61,59 +60,65 @@ extension AsyncStream {
6160
}
6261
}
6362

64-
/// Constructs and returns a stream along with its backing continuation.
65-
///
66-
/// This is handy for immediately escaping the continuation from an async stream, which typically
67-
/// requires multiple steps:
68-
///
69-
/// ```swift
70-
/// var _continuation: AsyncStream<Int>.Continuation!
71-
/// let stream = AsyncStream<Int> { continuation = $0 }
72-
/// let continuation = _continuation!
73-
///
74-
/// // vs.
75-
///
76-
/// let (stream, continuation) = AsyncStream<Int>.streamWithContinuation()
77-
/// ```
78-
///
79-
/// This tool is usually used for tests where we need to supply an async sequence to a dependency
80-
/// endpoint and get access to its continuation so that we can emulate the dependency emitting
81-
/// data. For example, suppose you have a dependency exposing an async sequence for listening to
82-
/// notifications. To test this you can use `streamWithContinuation`:
83-
///
84-
/// ```swift
85-
/// func testScreenshots() {
86-
/// let screenshots = AsyncStream<Void>.streamWithContinuation()
87-
///
88-
/// let model = withDependencies {
89-
/// $0.screenshots = { screenshots.stream }
90-
/// } operation: {
91-
/// FeatureModel()
92-
/// }
93-
///
94-
/// XCTAssertEqual(model.screenshotCount, 0)
95-
/// screenshots.continuation.yield() // Simulate a screenshot being taken.
96-
/// XCTAssertEqual(model.screenshotCount, 1)
97-
/// }
98-
/// ```
99-
///
100-
/// > Warning: ⚠️ `AsyncStream` does not support multiple subscribers, therefore you can only use
101-
/// > this helper to test features that do not subscribe multiple times to the dependency
102-
/// > endpoint.
103-
///
104-
/// - Parameters:
105-
/// - elementType: The type of element the `AsyncStream` produces.
106-
/// - limit: A Continuation.BufferingPolicy value to set the stream’s buffering behavior. By
107-
/// default, the stream buffers an unlimited number of elements. You can also set the policy
108-
/// to buffer a specified number of oldest or newest elements.
109-
/// - Returns: An `AsyncStream`.
110-
public static func streamWithContinuation(
111-
_ elementType: Element.Type = Element.self,
112-
bufferingPolicy limit: Continuation.BufferingPolicy = .unbounded
113-
) -> (stream: Self, continuation: Continuation) {
114-
var continuation: Continuation!
115-
return (Self(elementType, bufferingPolicy: limit) { continuation = $0 }, continuation)
116-
}
63+
#if swift(<5.9)
64+
/// Constructs and returns a stream along with its backing continuation.
65+
///
66+
/// A back-port of [SE-0388: Convenience Async[Throwing]Stream.makeStream methods][se-0388].
67+
///
68+
/// This is handy for immediately escaping the continuation from an async stream, which
69+
/// typically requires multiple steps:
70+
///
71+
/// ```swift
72+
/// var _continuation: AsyncStream<Int>.Continuation!
73+
/// let stream = AsyncStream<Int> { continuation = $0 }
74+
/// let continuation = _continuation!
75+
///
76+
/// // vs.
77+
///
78+
/// let (stream, continuation) = AsyncStream.makeStream(of: Int.self)
79+
/// ```
80+
///
81+
/// This tool is usually used for tests where we need to supply an async sequence to a
82+
/// dependency endpoint and get access to its continuation so that we can emulate the dependency
83+
/// emitting data. For example, suppose you have a dependency exposing an async sequence for
84+
/// listening to notifications. To test this you can use `makeStream`:
85+
///
86+
/// ```swift
87+
/// func testScreenshots() {
88+
/// let screenshots = AsyncStream.makeStream(of: Void.self)
89+
///
90+
/// let model = withDependencies {
91+
/// $0.screenshots = { screenshots.stream }
92+
/// } operation: {
93+
/// FeatureModel()
94+
/// }
95+
///
96+
/// XCTAssertEqual(model.screenshotCount, 0)
97+
/// screenshots.continuation.yield() // Simulate a screenshot being taken.
98+
/// XCTAssertEqual(model.screenshotCount, 1)
99+
/// }
100+
/// ```
101+
///
102+
/// > Warning: ⚠️ `AsyncStream` does not support multiple subscribers, therefore you can only
103+
/// > use this helper to test features that do not subscribe multiple times to the dependency
104+
/// > endpoint.
105+
///
106+
/// [se-0388]: https://github.com/apple/swift-evolution/blob/main/proposals/0388-async-stream-factory.md
107+
///
108+
/// - Parameters:
109+
/// - elementType: The type of element the `AsyncStream` produces.
110+
/// - limit: A Continuation.BufferingPolicy value to set the stream’s buffering behavior. By
111+
/// default, the stream buffers an unlimited number of elements. You can also set the policy
112+
/// to buffer a specified number of oldest or newest elements.
113+
/// - Returns: An `AsyncStream`.
114+
public static func makeStream(
115+
of elementType: Element.Type = Element.self,
116+
bufferingPolicy limit: Continuation.BufferingPolicy = .unbounded
117+
) -> (stream: Self, continuation: Continuation) {
118+
var continuation: Continuation!
119+
return (Self(elementType, bufferingPolicy: limit) { continuation = $0 }, continuation)
120+
}
121+
#endif
117122

118123
/// An `AsyncStream` that never emits and never completes unless cancelled.
119124
public static var never: Self {

Sources/Dependencies/ConcurrencySupport/AsyncThrowingStream.swift

Lines changed: 61 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -13,59 +13,67 @@ extension AsyncThrowingStream where Failure == Error {
1313
}
1414
}
1515

16-
/// Constructs and returns a stream along with its backing continuation.
17-
///
18-
/// This is handy for immediately escaping the continuation from an async stream, which typically
19-
/// requires multiple steps:
20-
///
21-
/// ```swift
22-
/// var _continuation: AsyncThrowingStream<Int, Error>.Continuation!
23-
/// let stream = AsyncThrowingStream<Int, Error> { continuation = $0 }
24-
/// let continuation = _continuation!
25-
///
26-
/// // vs.
27-
///
28-
/// let (stream, continuation) = AsyncThrowingStream<Int, Error>.streamWithContinuation()
29-
/// ```
30-
///
31-
/// This tool is usually used for tests where we need to supply an async sequence to a dependency
32-
/// endpoint and get access to its continuation so that we can emulate the dependency emitting
33-
/// data. For example, suppose you have a dependency exposing an async sequence for listening to
34-
/// notifications. To test this you can use `streamWithContinuation`:
35-
///
36-
/// ```swift
37-
/// func testScreenshots() {
38-
/// let screenshots = AsyncThrowingStream<Void>.streamWithContinuation()
39-
///
40-
/// let model = withDependencies {
41-
/// $0.screenshots = { screenshots.stream }
42-
/// } operation: {
43-
/// FeatureModel()
44-
/// }
45-
///
46-
/// XCTAssertEqual(model.screenshotCount, 0)
47-
/// screenshots.continuation.yield() // Simulate a screenshot being taken.
48-
/// XCTAssertEqual(model.screenshotCount, 1)
49-
/// }
50-
/// ```
51-
///
52-
/// > Warning: ⚠️ `AsyncStream` does not support multiple subscribers, therefore you can only use
53-
/// > this helper to test features that do not subscribe multiple times to the dependency
54-
/// > endpoint.
55-
///
56-
/// - Parameters:
57-
/// - elementType: The type of element the `AsyncThrowingStream` produces.
58-
/// - limit: A Continuation.BufferingPolicy value to set the stream’s buffering behavior. By
59-
/// default, the stream buffers an unlimited number of elements. You can also set the policy
60-
/// to buffer a specified number of oldest or newest elements.
61-
/// - Returns: An `AsyncThrowingStream`.
62-
public static func streamWithContinuation(
63-
_ elementType: Element.Type = Element.self,
64-
bufferingPolicy limit: Continuation.BufferingPolicy = .unbounded
65-
) -> (stream: Self, continuation: Continuation) {
66-
var continuation: Continuation!
67-
return (Self(elementType, bufferingPolicy: limit) { continuation = $0 }, continuation)
68-
}
16+
#if swift(<5.9)
17+
/// Constructs and returns a stream along with its backing continuation.
18+
///
19+
/// A back-port of [SE-0388: Convenience Async[Throwing]Stream.makeStream methods][se-0388].
20+
///
21+
/// This is handy for immediately escaping the continuation from an async stream, which
22+
/// typically requires multiple steps:
23+
///
24+
/// ```swift
25+
/// var _continuation: AsyncThrowingStream<Int, Error>.Continuation!
26+
/// let stream = AsyncThrowingStream<Int, Error> { continuation = $0 }
27+
/// let continuation = _continuation!
28+
///
29+
/// // vs.
30+
///
31+
/// let (stream, continuation) = AsyncThrowingStream.makeStream(of: Int.self)
32+
/// ```
33+
///
34+
/// This tool is usually used for tests where we need to supply an async sequence to a
35+
/// dependency endpoint and get access to its continuation so that we can emulate the dependency
36+
/// emitting data. For example, suppose you have a dependency exposing an async sequence for
37+
/// listening to notifications. To test this you can use `makeStream`:
38+
///
39+
/// ```swift
40+
/// func testScreenshots() {
41+
/// let screenshots = AsyncThrowingStream.makeStream(of: Void.self)
42+
///
43+
/// let model = withDependencies {
44+
/// $0.screenshots = { screenshots.stream }
45+
/// } operation: {
46+
/// FeatureModel()
47+
/// }
48+
///
49+
/// XCTAssertEqual(model.screenshotCount, 0)
50+
/// screenshots.continuation.yield() // Simulate a screenshot being taken.
51+
/// XCTAssertEqual(model.screenshotCount, 1)
52+
/// }
53+
/// ```
54+
///
55+
/// > Warning: ⚠️ `AsyncThrowingStream` does not support multiple subscribers, therefore you can
56+
/// > only use this helper to test features that do not subscribe multiple times to the
57+
/// > dependency endpoint.
58+
///
59+
/// [se-0388]: https://github.com/apple/swift-evolution/blob/main/proposals/0388-async-stream-factory.md
60+
///
61+
/// - Parameters:
62+
/// - elementType: The type of element the `AsyncThrowingStream` produces.
63+
/// - failureType: The type of failure the `AsyncThrowingStream` throws.
64+
/// - limit: A Continuation.BufferingPolicy value to set the stream’s buffering behavior. By
65+
/// default, the stream buffers an unlimited number of elements. You can also set the policy
66+
/// to buffer a specified number of oldest or newest elements.
67+
/// - Returns: An `AsyncThrowingStream`.
68+
public static func makeStream(
69+
of elementType: Element.Type = Element.self,
70+
throwing failureType: Failure.Type = Failure.self,
71+
bufferingPolicy limit: Continuation.BufferingPolicy = .unbounded
72+
) -> (stream: Self, continuation: Continuation) {
73+
var continuation: Continuation!
74+
return (Self(elementType, bufferingPolicy: limit) { continuation = $0 }, continuation)
75+
}
76+
#endif
6977

7078
/// An `AsyncThrowingStream` that never emits and never completes unless cancelled.
7179
public static var never: Self {

Sources/Dependencies/Documentation.docc/Articles/ConcurrencySupport.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ The library comes with numerous helper APIs spread across the two Swift stream t
5353
be handy in tests when overriding a dependency endpoint that returns a stream:
5454

5555
```swift
56-
let screenshots = AsyncStream<Void>.streamWithContinuation()
56+
let screenshots = AsyncStream.makeStream(of: Void.self)
5757

5858
let model = withDependencies {
5959
$0.screenshots = { screenshots.stream }

Sources/Dependencies/Internal/Deprecations.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
1+
// MARK: - Deprecated after 0.4.2
2+
3+
extension AsyncStream {
4+
@available(*, deprecated, renamed: "makeStream(of:bufferingPolicy:)")
5+
public static func streamWithContinuation(
6+
_ elementType: Element.Type = Element.self,
7+
bufferingPolicy limit: Continuation.BufferingPolicy = .unbounded
8+
) -> (stream: Self, continuation: Continuation) {
9+
var continuation: Continuation!
10+
return (Self(elementType, bufferingPolicy: limit) { continuation = $0 }, continuation)
11+
}
12+
}
13+
14+
extension AsyncThrowingStream where Failure == Error {
15+
@available(*, deprecated, renamed: "makeStream(of:throwing:bufferingPolicy:)")
16+
public static func streamWithContinuation(
17+
_ elementType: Element.Type = Element.self,
18+
bufferingPolicy limit: Continuation.BufferingPolicy = .unbounded
19+
) -> (stream: Self, continuation: Continuation) {
20+
var continuation: Continuation!
21+
return (Self(elementType, bufferingPolicy: limit) { continuation = $0 }, continuation)
22+
}
23+
}
24+
25+
// MARK: -
26+
127
extension ActorIsolated {
228
@available(
329
*,

0 commit comments

Comments
 (0)