Skip to content

Commit 60dbf52

Browse files
natemannmbrandonwstephencelis
authored
Prevent double optional return value (#168)
* Prevent double optional return value * Simplfiy and added tests * support swift <6 * fix --------- Co-authored-by: Brandon Williams <[email protected]> Co-authored-by: Stephen Celis <[email protected]>
1 parent 6bcb7d7 commit 60dbf52

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed

Sources/IssueReporting/ErrorReporting.swift

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,38 @@ public func withErrorReporting<R>(
5656
}
5757
}
5858

59+
/// Evaluates a throwing closure and automatically catches and reports any error thrown.
60+
///
61+
/// - Parameters:
62+
/// - message: A message describing the expectation.
63+
/// - reporters: Issue reporters to notify during the operation.
64+
/// - fileID: The source `#fileID` associated with the error reporting.
65+
/// - filePath: The source `#filePath` associated with the error reporting.
66+
/// - line: The source `#line` associated with the error reporting.
67+
/// - column: The source `#column` associated with the error reporting.
68+
/// - body: A synchronous operation.
69+
/// - Returns: The optional result of the operation, or `nil` if an error was thrown.
70+
@_transparent
71+
public func withErrorReporting<R>(
72+
_ message: @autoclosure () -> String? = nil,
73+
to reporters: [any IssueReporter]? = nil,
74+
fileID: StaticString = #fileID,
75+
filePath: StaticString = #filePath,
76+
line: UInt = #line,
77+
column: UInt = #column,
78+
catching body: () throws -> R?
79+
) -> R? {
80+
(withErrorReporting(
81+
message(),
82+
to: reporters,
83+
fileID: fileID,
84+
filePath: filePath,
85+
line: line,
86+
column: column,
87+
catching: body
88+
) as R??) ?? nil
89+
}
90+
5991
#if compiler(>=6)
6092
/// Evaluates a throwing closure and automatically catches and reports any error thrown.
6193
///
@@ -113,6 +145,42 @@ public func withErrorReporting<R>(
113145
}
114146
}
115147
}
148+
149+
/// Evaluates a throwing closure and automatically catches and reports any error thrown.
150+
///
151+
/// - Parameters:
152+
/// - message: A message describing the expectation.
153+
/// - reporters: Issue reporters to notify during the operation.
154+
/// - fileID: The source `#fileID` associated with the error reporting.
155+
/// - filePath: The source `#filePath` associated with the error reporting.
156+
/// - line: The source `#line` associated with the error reporting.
157+
/// - column: The source `#column` associated with the error reporting.
158+
/// - isolation: The isolation associated with the error reporting.
159+
/// - body: An asynchronous operation.
160+
/// - Returns: The optional result of the operation, or `nil` if an error was thrown.
161+
@_transparent
162+
public func withErrorReporting<R>(
163+
_ message: @autoclosure () -> String? = nil,
164+
to reporters: [any IssueReporter]? = nil,
165+
fileID: StaticString = #fileID,
166+
filePath: StaticString = #filePath,
167+
line: UInt = #line,
168+
column: UInt = #column,
169+
isolation: isolated (any Actor)? = #isolation,
170+
// DO NOT FIX THE WHITESPACE IN THE NEXT LINE UNTIL 5.10 IS UNSUPPORTED
171+
// https://github.com/swiftlang/swift/issues/79285
172+
catching body: () async throws -> sending R?
173+
) async -> R? {
174+
(await withErrorReporting(
175+
message(),
176+
to: reporters,
177+
fileID: fileID,
178+
filePath: filePath,
179+
line: line,
180+
column: column,
181+
catching: body
182+
) as R??) ?? nil
183+
}
116184
#else
117185
@_transparent
118186
@_unsafeInheritExecutor
@@ -157,4 +225,26 @@ public func withErrorReporting<R>(
157225
}
158226
}
159227
}
228+
229+
@_transparent
230+
@_unsafeInheritExecutor
231+
public func withErrorReporting<R>(
232+
_ message: @autoclosure () -> String? = nil,
233+
to reporters: [any IssueReporter]? = nil,
234+
fileID: StaticString = #fileID,
235+
filePath: StaticString = #filePath,
236+
line: UInt = #line,
237+
column: UInt = #column,
238+
catching body: () async throws -> R?
239+
) async -> R? {
240+
(await withErrorReporting(
241+
message(),
242+
to: reporters,
243+
fileID: fileID,
244+
filePath: filePath,
245+
line: line,
246+
column: column,
247+
catching: body
248+
) as R??) ?? nil
249+
}
160250
#endif

Tests/IssueReportingTests/WithErrorReportingTests.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,28 @@
4040
}
4141
}
4242

43+
@Test func squashOptionalSync() async {
44+
withKnownIssue {
45+
let _: Int? = withErrorReporting { () -> Int? in
46+
throw SomeError()
47+
}
48+
} matching: { issue in
49+
issue.description == "Caught error: SomeError()\(issueDescriptionSuffix)"
50+
}
51+
}
52+
53+
54+
@Test func squashOptionalAsync() async {
55+
await withKnownIssue {
56+
let _: Int? = await withErrorReporting { () -> Int? in
57+
await Task.yield()
58+
throw SomeError()
59+
}
60+
} matching: { issue in
61+
issue.description == "Caught error: SomeError()\(issueDescriptionSuffix)"
62+
}
63+
}
64+
4365
#if compiler(<6.2)
4466
@MainActor
4567
@Test func isolation() async {

0 commit comments

Comments
 (0)