@@ -92,16 +92,41 @@ public final class InProcessSourceKitLSPClient: Sendable {
92
92
/// necessary and the response of the request is not awaited, use the version of the function that takes a
93
93
/// completion handler
94
94
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) )
98
117
}
99
118
}
100
119
}
101
120
102
121
/// 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
105
130
}
106
131
107
132
/// Send the notification to `server`.
0 commit comments