@@ -92,16 +92,41 @@ public final class InProcessSourceKitLSPClient: Sendable {
9292 /// necessary and the response of the request is not awaited, use the version of the function that takes a
9393 /// completion handler
9494 public func send< R: RequestType > ( _ request: R ) async throws -> R . Response {
95- return try await withCheckedThrowingContinuation { continuation in
96- self . send ( request) {
97- continuation. resume ( with: $0)
95+ let requestId = ThreadSafeBox < RequestID ? > ( initialValue: nil )
96+ return try await withTaskCancellationHandler {
97+ return try await withCheckedThrowingContinuation { continuation in
98+ if Task . isCancelled {
99+ // Check if the task has been cancelled before we send the request to LSP to avoid any kind of work if
100+ // possible.
101+ return continuation. resume ( throwing: CancellationError ( ) )
102+ }
103+ requestId. value = self . send ( request) {
104+ continuation. resume ( with: $0)
105+ }
106+ if Task . isCancelled, let requestId = requestId. takeValue ( ) {
107+ // The task might have been cancelled after the above cancellation check but before `requestId` was assigned
108+ // a value. To cover that case, check for cancellation here again. Note that we won't cancel twice from here
109+ // and the `onCancel` handler because we take the request ID out of the `ThreadSafeBox` before sending the
110+ // `CancelRequestNotification`.
111+ self . send ( CancelRequestNotification ( id: requestId) )
112+ }
113+ }
114+ } onCancel: {
115+ if let requestId = requestId. takeValue ( ) {
116+ self . send ( CancelRequestNotification ( id: requestId) )
98117 }
99118 }
100119 }
101120
102121 /// Send the request to `server` and return the request result via a completion handler.
103- public func send< R: RequestType > ( _ request: R , reply: @Sendable @escaping ( LSPResult < R . Response > ) -> Void ) {
104- server. handle ( request, id: . number( Int ( nextRequestID. fetchAndIncrement ( ) ) ) , reply: reply)
122+ @discardableResult
123+ public func send< R: RequestType > (
124+ _ request: R ,
125+ reply: @Sendable @escaping ( LSPResult < R . Response > ) -> Void
126+ ) -> RequestID {
127+ let requestID = RequestID . number ( Int ( nextRequestID. fetchAndIncrement ( ) ) )
128+ server. handle ( request, id: requestID, reply: reply)
129+ return requestID
105130 }
106131
107132 /// Send the notification to `server`.
0 commit comments