mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-20 02:47:34 +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)
|
.try_send(message)
|
||||||
.context("failed to write to language server's stdin");
|
.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 mut timeout = executor.timer(LSP_REQUEST_TIMEOUT).fuse();
|
||||||
let started = Instant::now();
|
let started = Instant::now();
|
||||||
async move {
|
async move {
|
||||||
handle_response?;
|
handle_response?;
|
||||||
send?;
|
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;
|
let method = T::METHOD;
|
||||||
futures::select! {
|
futures::select! {
|
||||||
response = rx.fuse() => {
|
response = rx.fuse() => {
|
||||||
let elapsed = started.elapsed();
|
let elapsed = started.elapsed();
|
||||||
log::trace!("Took {elapsed:?} to receive response to {method:?} id {id}");
|
log::trace!("Took {elapsed:?} to receive response to {method:?} id {id}");
|
||||||
|
cancel_on_drop.abort();
|
||||||
response?
|
response?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ pub struct Deferred<F: FnOnce()>(Option<F>);
|
|||||||
|
|
||||||
impl<F: FnOnce()> Deferred<F> {
|
impl<F: FnOnce()> Deferred<F> {
|
||||||
/// Drop without running the deferred function.
|
/// Drop without running the deferred function.
|
||||||
pub fn cancel(mut self) {
|
pub fn abort(mut self) {
|
||||||
self.0.take();
|
self.0.take();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user