From e89cebff8830c96c72fd42f009b073a9728187e3 Mon Sep 17 00:00:00 2001 From: JP Simard Date: Mon, 30 Jan 2023 10:59:22 -0500 Subject: [PATCH] Add `Request.sendAsync()` function --- CHANGELOG.md | 3 ++- Source/SourceKittenFramework/Request.swift | 13 ++++++++++ .../SourceKitObject.swift | 25 +++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9c6d127..cc2f9628 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ ##### Enhancements -* None. +* Add `Request.sendAsync()` function. + [JP Simard](https://github.com/jpsim) ##### Bug Fixes diff --git a/Source/SourceKittenFramework/Request.swift b/Source/SourceKittenFramework/Request.swift index 4cd9c2b0..65e1aac7 100644 --- a/Source/SourceKittenFramework/Request.swift +++ b/Source/SourceKittenFramework/Request.swift @@ -333,6 +333,19 @@ public enum Request { /** Sends the request to SourceKit and return the response as an [String: SourceKitRepresentable]. + - returns: SourceKit output as a dictionary. + - throws: Request.Error on fail () + */ + public func asyncSend() async throws -> [String: SourceKitRepresentable] { + initializeSourceKitFailable + let response = try await sourcekitObject.sendAsync() + defer { sourcekitd_response_dispose(response) } + return fromSourceKit(sourcekitd_response_get_value(response)) as! [String: SourceKitRepresentable] + } + + /** + Sends the request to SourceKit and return the response as an [String: SourceKitRepresentable]. + - returns: SourceKit output as a dictionary. - throws: Request.Error on fail () */ diff --git a/Source/SourceKittenFramework/SourceKitObject.swift b/Source/SourceKittenFramework/SourceKitObject.swift index 098a1e64..0af9f3f7 100644 --- a/Source/SourceKittenFramework/SourceKitObject.swift +++ b/Source/SourceKittenFramework/SourceKitObject.swift @@ -100,6 +100,31 @@ public final class SourceKitObject { func sendSync() -> sourcekitd_response_t? { return sourcekitd_send_request_sync(sourcekitdObject) } + + func sendAsync() async throws -> sourcekitd_response_t { + let handle = UnsafeMutablePointer.allocate(capacity: 1) + + return try await withTaskCancellationHandler { + try await withUnsafeThrowingContinuation { continuation in + sourcekitd_send_request(sourcekitdObject, handle) { response in + enum SourceKitSendError: Error { case error, noResponse } + + guard let response else { + continuation.resume(throwing: SourceKitSendError.noResponse) + return + } + + if sourcekitd_response_is_error(response) { + continuation.resume(throwing: SourceKitSendError.error) + } else { + continuation.resume(returning: response) + } + } + } + } onCancel: { + sourcekitd_cancel_request(handle) + } + } } extension SourceKitObject: SourceKitObjectConvertible {