Skip to content

Commit 93fe160

Browse files
authored
Pass message along in async withErrorReporting (#144)
* Pass `message` along in async `withErrorReporting` * Fix isolation * wip * wip * wip * wip * wip * wip * wip
1 parent 9243488 commit 93fe160

File tree

9 files changed

+162
-58
lines changed

9 files changed

+162
-58
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- debug
2222
- release
2323
xcode:
24-
- '16.0'
24+
- '16.2'
2525
name: macOS 15
2626
runs-on: macos-15
2727
steps:
@@ -55,7 +55,7 @@ jobs:
5555
steps:
5656
- uses: actions/checkout@v4
5757
- name: Select Xcode
58-
run: sudo xcode-select -s /Applications/Xcode_16.0.app
58+
run: sudo xcode-select -s /Applications/Xcode_16.2.app
5959
- name: Run tests
6060
run: make build-for-library-evolution
6161

@@ -66,7 +66,7 @@ jobs:
6666
- Debug
6767
- Release
6868
xcode:
69-
- '16.0'
69+
- '16.2'
7070
name: Examples
7171
runs-on: macos-15
7272
steps:
@@ -125,8 +125,8 @@ jobs:
125125
steps:
126126
- uses: compnerd/gha-setup-swift@main
127127
with:
128-
branch: swift-5.10-release
129-
tag: 5.10-RELEASE
128+
branch: swift-6.0.3-release
129+
tag: 6.0.3-RELEASE
130130
- name: Set long paths
131131
run: git config --system core.longpaths true
132132
- uses: actions/checkout@v4
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# ``IssueReporting/withErrorReporting(_:to:fileID:filePath:line:column:catching:)-89omf``
1+
# ``IssueReporting/withErrorReporting(_:to:fileID:filePath:line:column:catching:)``
22

33
## Topics
44

55
### Overloads
66

7-
- ``withErrorReporting(_:to:fileID:filePath:line:column:catching:)-3dh1h``
7+
- ``withErrorReporting(_:to:fileID:filePath:line:column:isolation:catching:)``
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# ``IssueReporting/withIssueReporters(_:operation:)-91179``
1+
# ``IssueReporting/withIssueReporters(_:operation:)``
22

33
## Topics
44

55
### Overloads
66

7-
- ``withIssueReporters(_:operation:)-6xjha``
7+
- ``withIssueReporters(_:isolation:operation:)``

Sources/IssueReporting/Documentation.docc/IssueReporting.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ that ship in the same target as the library itself.
5353

5454
- ``reportIssue(_:fileID:filePath:line:column:)``
5555
- ``withExpectedIssue(_:isIntermittent:fileID:filePath:line:column:_:)-9pinm``
56-
- ``withErrorReporting(_:to:fileID:filePath:line:column:catching:)-89omf``
56+
- ``withErrorReporting(_:to:fileID:filePath:line:column:catching:)``
5757

5858
### Issue reporters
5959

@@ -64,7 +64,7 @@ that ship in the same target as the library itself.
6464
### Custom reporting
6565

6666
- ``IssueReporter``
67-
- ``withIssueReporters(_:operation:)-91179``
67+
- ``withIssueReporters(_:operation:)``
6868
- ``withIssueContext(fileID:filePath:line:column:operation:)-97lux``
6969
- ``IssueReporters``
7070

Sources/IssueReporting/ErrorReporting.swift

Lines changed: 93 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -52,42 +52,104 @@ public func withErrorReporting<R>(
5252
}
5353
}
5454

55-
/// Evaluates a throwing closure and automatically catches and reports any error thrown.
56-
///
57-
/// - Parameters:
58-
/// - message: A message describing the expectation.
59-
/// - reporters: Issue reporters to notify during the operation.
60-
/// - fileID: The source `#fileID` associated with the error reporting.
61-
/// - filePath: The source `#filePath` associated with the error reporting.
62-
/// - line: The source `#line` associated with the error reporting.
63-
/// - column: The source `#column` associated with the error reporting.
64-
/// - body: An asynchronous operation.
65-
/// - Returns: The optional result of the operation, or `nil` if an error was thrown.
66-
@_transparent
67-
public func withErrorReporting<R>(
68-
_ message: @autoclosure () -> String? = nil,
69-
to reporters: [any IssueReporter]? = nil,
70-
fileID: StaticString = #fileID,
71-
filePath: StaticString = #filePath,
72-
line: UInt = #line,
73-
column: UInt = #column,
74-
catching body: () async throws -> R
75-
) async -> R? {
76-
if let reporters {
77-
return await withIssueReporters(reporters) {
55+
#if compiler(>=6)
56+
/// Evaluates a throwing closure and automatically catches and reports any error thrown.
57+
///
58+
/// - Parameters:
59+
/// - message: A message describing the expectation.
60+
/// - reporters: Issue reporters to notify during the operation.
61+
/// - fileID: The source `#fileID` associated with the error reporting.
62+
/// - filePath: The source `#filePath` associated with the error reporting.
63+
/// - line: The source `#line` associated with the error reporting.
64+
/// - column: The source `#column` associated with the error reporting.
65+
/// - isolation: The isolation associated with the error reporting.
66+
/// - body: An asynchronous operation.
67+
/// - Returns: The optional result of the operation, or `nil` if an error was thrown.
68+
@_transparent
69+
public func withErrorReporting<R>(
70+
_ message: @autoclosure () -> String? = nil,
71+
to reporters: [any IssueReporter]? = nil,
72+
fileID: StaticString = #fileID,
73+
filePath: StaticString = #filePath,
74+
line: UInt = #line,
75+
column: UInt = #column,
76+
isolation: isolated (any Actor)? = #isolation,
77+
catching body: () async throws -> sending R
78+
) async -> R? {
79+
if let reporters {
80+
return await withIssueReporters(reporters) {
81+
do {
82+
return try await body()
83+
} catch {
84+
reportIssue(
85+
error,
86+
message(),
87+
fileID: fileID,
88+
filePath: filePath,
89+
line: line,
90+
column: column
91+
)
92+
return nil
93+
}
94+
}
95+
} else {
7896
do {
7997
return try await body()
8098
} catch {
81-
reportIssue(error, fileID: fileID, filePath: filePath, line: line, column: column)
99+
reportIssue(
100+
error,
101+
message(),
102+
fileID: fileID,
103+
filePath: filePath,
104+
line: line,
105+
column: column
106+
)
82107
return nil
83108
}
84109
}
85-
} else {
86-
do {
87-
return try await body()
88-
} catch {
89-
reportIssue(error, fileID: fileID, filePath: filePath, line: line, column: column)
90-
return nil
110+
}
111+
#else
112+
@_transparent
113+
@_unsafeInheritExecutor
114+
public func withErrorReporting<R>(
115+
_ message: @autoclosure () -> String? = nil,
116+
to reporters: [any IssueReporter]? = nil,
117+
fileID: StaticString = #fileID,
118+
filePath: StaticString = #filePath,
119+
line: UInt = #line,
120+
column: UInt = #column,
121+
catching body: () async throws -> R
122+
) async -> R? {
123+
if let reporters {
124+
return await withIssueReporters(reporters) {
125+
do {
126+
return try await body()
127+
} catch {
128+
reportIssue(
129+
error,
130+
message(),
131+
fileID: fileID,
132+
filePath: filePath,
133+
line: line,
134+
column: column
135+
)
136+
return nil
137+
}
138+
}
139+
} else {
140+
do {
141+
return try await body()
142+
} catch {
143+
reportIssue(
144+
error,
145+
message(),
146+
fileID: fileID,
147+
filePath: filePath,
148+
line: line,
149+
column: column
150+
)
151+
return nil
152+
}
91153
}
92154
}
93-
}
155+
#endif

Sources/IssueReporting/IssueReporter.swift

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -183,16 +183,28 @@ public func withIssueReporters<R>(
183183
try IssueReporters.$_current.withValue(LockIsolated(reporters), operation: operation)
184184
}
185185

186-
/// Overrides the task's issue reporters for the duration of the asynchronous operation.
187-
///
188-
/// An asynchronous version of ``withIssueReporters(_:operation:)-91179``.
189-
///
190-
/// - Parameters:
191-
/// - reporters: Issue reporters to notify during the operation.
192-
/// - operation: An asynchronous operation.
193-
public func withIssueReporters<R>(
194-
_ reporters: [any IssueReporter],
195-
operation: () async throws -> R
196-
) async rethrows -> R {
197-
try await IssueReporters.$_current.withValue(LockIsolated(reporters), operation: operation)
198-
}
186+
#if compiler(>=6)
187+
/// Overrides the task's issue reporters for the duration of the asynchronous operation.
188+
///
189+
/// An asynchronous version of ``withIssueReporters(_:operation:)-91179``.
190+
///
191+
/// - Parameters:
192+
/// - reporters: Issue reporters to notify during the operation.
193+
/// - isolation: The isolation associated with the operation.
194+
/// - operation: An asynchronous operation.
195+
public func withIssueReporters<R>(
196+
_ reporters: [any IssueReporter],
197+
isolation: isolated (any Actor)? = #isolation,
198+
operation: () async throws -> R
199+
) async rethrows -> R {
200+
try await IssueReporters.$_current.withValue(LockIsolated(reporters), operation: operation)
201+
}
202+
#else
203+
@_unsafeInheritExecutor
204+
public func withIssueReporters<R>(
205+
_ reporters: [any IssueReporter],
206+
operation: () async throws -> R
207+
) async rethrows -> R {
208+
try await IssueReporters.$_current.withValue(LockIsolated(reporters), operation: operation)
209+
}
210+
#endif

Tests/IssueReportingTests/SwiftTestingTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#if canImport(Testing)
1+
#if canImport(Testing) && !os(Windows)
22
import Testing
33
import IssueReporting
44

Tests/IssueReportingTests/UnimplementedTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#if canImport(Testing)
1+
#if canImport(Testing) && !os(Windows)
22
import IssueReporting
33
import Testing
44

Tests/IssueReportingTests/WithErrorReportingTests.swift

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#if canImport(Testing)
1+
#if canImport(Testing) && !os(Windows)
22
import Testing
33
import IssueReporting
44

@@ -21,7 +21,37 @@
2121
issue.description == "Caught error: SomeError(): Failed"
2222
}
2323
}
24+
25+
@Test func overload() async {
26+
await withKnownIssue {
27+
await withErrorReporting { () async throws in
28+
throw SomeError()
29+
}
30+
} matching: { issue in
31+
issue.description == "Caught error: SomeError()"
32+
}
33+
34+
await withKnownIssue {
35+
await withErrorReporting("Failed") { () async throws in
36+
throw SomeError()
37+
}
38+
} matching: { issue in
39+
issue.description == "Caught error: SomeError(): Failed"
40+
}
41+
}
42+
43+
@MainActor
44+
@Test func isolation() async {
45+
await withKnownIssue {
46+
await withErrorReporting { () async throws in
47+
throw SomeError()
48+
}
49+
} matching: { issue in
50+
issue.description == "Caught error: SomeError()"
51+
}
52+
}
2453
}
2554

2655
private struct SomeError: Error {}
2756
#endif
57+

0 commit comments

Comments
 (0)