From 63e543cd57c4f7cf8317acfc93ad5b2719838323 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Tue, 20 Aug 2024 08:58:40 -0700 Subject: [PATCH] `unimplemented` support for typed throws (#117) * `unimplemented` support for typed throws This adds `unimplemented` support for endpoints using typed throws. * Don't include typed throws code in Swift < 6. --------- Co-authored-by: Brandon Williams --- .../Extensions/Unimplemented.md | 2 + Sources/IssueReporting/Unimplemented.swift | 84 +++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/Sources/IssueReporting/Documentation.docc/Extensions/Unimplemented.md b/Sources/IssueReporting/Documentation.docc/Extensions/Unimplemented.md index 7cb2b39..a62bf10 100644 --- a/Sources/IssueReporting/Documentation.docc/Extensions/Unimplemented.md +++ b/Sources/IssueReporting/Documentation.docc/Extensions/Unimplemented.md @@ -6,6 +6,8 @@ - ``unimplemented(_:fileID:filePath:function:line:column:)-2ae22`` - ``unimplemented(_:fileID:filePath:function:line:column:)-1hsov`` +- ``unimplemented(_:throwing:fileID:filePath:function:line:column:)-4h958`` +- ``unimplemented(_:throwing:fileID:filePath:function:line:column:)-5zfy9`` - ``unimplemented(_:placeholder:fileID:filePath:function:line:column:)-6ts5j`` - ``unimplemented(_:placeholder:fileID:filePath:function:line:column:)-34tpp`` diff --git a/Sources/IssueReporting/Unimplemented.swift b/Sources/IssueReporting/Unimplemented.swift index 4a6f1b6..dde3f2a 100644 --- a/Sources/IssueReporting/Unimplemented.swift +++ b/Sources/IssueReporting/Unimplemented.swift @@ -73,6 +73,47 @@ public func unimplemented( } } +#if compiler(>=6) +/// Returns a throwing closure that reports an issue and throws a given error when invoked. +/// +/// Useful for creating closures that need to be overridden by users of your API, and if it is +/// ever invoked without being overridden an issue will be reported. See +/// for more information. +/// +/// - Parameters: +/// - description: An optional description of the unimplemented closure. +/// - failure: The error thrown by the unimplemented closure. +/// - fileID: The fileID. +/// - filePath: The filePath. +/// - function: The function. +/// - line: The line. +/// - column: The column. +/// - Returns: A throwing closure that reports an issue and throws an error when invoked. +public func unimplemented( + _ description: @autoclosure @escaping @Sendable () -> String = "", + throwing failure: @autoclosure @escaping @Sendable () -> Failure, + fileID: StaticString = #fileID, + filePath: StaticString = #filePath, + function: StaticString = #function, + line: UInt = #line, + column: UInt = #column +) -> @Sendable (repeat each Argument) throws(Failure) -> Result { + return { (argument: repeat each Argument) throws(Failure) in + let description = description() + _fail( + description, + (repeat each argument), + fileID: fileID, + filePath: filePath, + function: function, + line: line, + column: column + ) + throw failure() + } +} +#endif + /// Returns an asynchronous closure that reports an issue when invoked. /// /// Useful for creating closures that need to be overridden by users of your API, and if it is @@ -149,6 +190,49 @@ public func unimplemented( } } +#if compiler(>=6) +/// Returns a throwing, asynchronous closure that reports an issue and throws a given error when +/// invoked. +/// +/// Useful for creating closures that need to be overridden by users of your API, and if it is +/// ever invoked without being overridden an issue will be reported. See +/// for more information. +/// +/// - Parameters: +/// - description: An optional description of the unimplemented closure. +/// - failure: The error thrown by the unimplemented closure. +/// - fileID: The fileID. +/// - filePath: The filePath. +/// - function: The function. +/// - line: The line. +/// - column: The column. +/// - Returns: A throwing, asynchronous closure that reports an issue and throws an error when +/// invoked. +public func unimplemented( + _ description: @autoclosure @escaping @Sendable () -> String = "", + throwing failure: @autoclosure @escaping @Sendable () -> Failure, + fileID: StaticString = #fileID, + filePath: StaticString = #filePath, + function: StaticString = #function, + line: UInt = #line, + column: UInt = #column +) -> @Sendable (repeat each Argument) async throws(Failure) -> Result { + return { (argument: repeat each Argument) async throws(Failure) in + let description = description() + _fail( + description, + (repeat each argument), + fileID: fileID, + filePath: filePath, + function: function, + line: line, + column: column + ) + throw failure() + } +} +#endif + @_disfavoredOverload public func unimplemented( _ description: @autoclosure @escaping @Sendable () -> String = "",