mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-26 22:50:28 +03:00
Cancel language server requests if request is dropped
Before this change, we would send requests to language servers without canceling them even if we never wait for their response. Example: when doing document highlights, we'd send a request (modulo debouncing) whenever a change was made, ignoring previously sent requests that might still be in-flight. With this change, we now send a Cancel request (from the LSP spec) to the language server in case no one listens to the response anymore (which is what happens when the `Future` returned by `request_internal`) is dropped.
This commit is contained in:
parent
338dcd76b1
commit
1a6cd73334
@ -863,17 +863,31 @@ impl LanguageServer {
|
||||
.try_send(message)
|
||||
.context("failed to write to language server's stdin");
|
||||
|
||||
let outbound_tx = outbound_tx.downgrade();
|
||||
let mut timeout = executor.timer(LSP_REQUEST_TIMEOUT).fuse();
|
||||
let started = Instant::now();
|
||||
async move {
|
||||
handle_response?;
|
||||
send?;
|
||||
|
||||
let cancel_on_drop = util::defer(move || {
|
||||
if let Some(outbound_tx) = outbound_tx.upgrade() {
|
||||
Self::notify_internal::<notification::Cancel>(
|
||||
&outbound_tx,
|
||||
CancelParams {
|
||||
id: NumberOrString::Number(id as i32),
|
||||
},
|
||||
)
|
||||
.log_err();
|
||||
}
|
||||
});
|
||||
|
||||
let method = T::METHOD;
|
||||
futures::select! {
|
||||
response = rx.fuse() => {
|
||||
let elapsed = started.elapsed();
|
||||
log::trace!("Took {elapsed:?} to receive response to {method:?} id {id}");
|
||||
cancel_on_drop.abort();
|
||||
response?
|
||||
}
|
||||
|
||||
|
@ -299,7 +299,7 @@ pub struct Deferred<F: FnOnce()>(Option<F>);
|
||||
|
||||
impl<F: FnOnce()> Deferred<F> {
|
||||
/// Drop without running the deferred function.
|
||||
pub fn cancel(mut self) {
|
||||
pub fn abort(mut self) {
|
||||
self.0.take();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user