|
8 | 8 | [lsp4clj.lsp.responses :as lsp.responses] |
9 | 9 | [lsp4clj.protocols.endpoint :as protocols.endpoint] |
10 | 10 | [lsp4clj.trace :as trace] |
11 | | - [promesa.core :as p]) |
| 11 | + [promesa.core :as p] |
| 12 | + [promesa.protocols]) |
12 | 13 | (:import |
13 | 14 | (java.util.concurrent CancellationException))) |
14 | 15 |
|
|
159 | 160 | (when-let [trace-body (apply trace-f @tracer* params)] |
160 | 161 | (async/put! trace-ch [:debug trace-body]))) |
161 | 162 |
|
| 163 | +(defrecord PendingReceivedRequest [result-promise cancelled?] |
| 164 | + promesa.protocols/ICancellable |
| 165 | + (-cancel! [_] |
| 166 | + (p/cancel! result-promise) |
| 167 | + (reset! cancelled? true)) |
| 168 | + (-cancelled? [_] |
| 169 | + @cancelled?)) |
| 170 | + |
| 171 | +(defn pending-received-request [method context params] |
| 172 | + (let [cancelled? (atom false) |
| 173 | + ;; coerce result/error to promise |
| 174 | + result-promise (p/promise |
| 175 | + (receive-request method |
| 176 | + (assoc context ::req-cancelled? cancelled?) |
| 177 | + params))] |
| 178 | + (map->PendingReceivedRequest |
| 179 | + {:result-promise result-promise |
| 180 | + :cancelled? cancelled?}))) |
| 181 | + |
162 | 182 | ;; TODO: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize |
163 | 183 | ;; * receive-request should return error until initialize request is received |
164 | 184 | ;; * receive-notification should drop until initialize request is received, with the exception of exit |
|
240 | 260 | resp (lsp.responses/response id)] |
241 | 261 | (try |
242 | 262 | (trace this trace/received-request req started) |
243 | | - ;; coerce result/error to promise |
244 | | - (let [result-promise (p/promise (receive-request method context params))] |
245 | | - (swap! pending-received-requests* assoc id result-promise) |
246 | | - (-> result-promise |
| 263 | + (let [pending-req (pending-received-request method context params)] |
| 264 | + (swap! pending-received-requests* assoc id pending-req) |
| 265 | + (-> pending-req |
| 266 | + :result-promise |
247 | 267 | ;; convert result/error to response |
248 | 268 | (p/then |
249 | 269 | (fn [result] |
|
274 | 294 | (let [now (.instant clock)] |
275 | 295 | (trace this trace/received-notification notif now) |
276 | 296 | (if (= method "$/cancelRequest") |
277 | | - (if-let [result-promise (get @pending-received-requests* (:id params))] |
278 | | - (p/cancel! result-promise) |
| 297 | + (if-let [pending-req (get @pending-received-requests* (:id params))] |
| 298 | + (p/cancel! pending-req) |
279 | 299 | (trace this trace/received-unmatched-cancellation-notification notif now)) |
280 | 300 | (let [result (receive-notification method context params)] |
281 | 301 | (when (identical? ::method-not-found result) |
|
0 commit comments