Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #13427 - Veykril:cancel-check, r=Veykril
feat: Make flycheck workdone progress reports cancellable In clients that support this (like VSCode), the clients will now render a cancel button on the notification message which can be clicked to cancel the flycheck instead. Closes https://github.com/rust-lang/rust-analyzer/issues/6895 ![Code_VbXgP3SbFD](https://user-images.githubusercontent.com/3757771/196205329-2df93451-c143-4d1b-a700-d988edf55efa.gif)
bors 2022-10-17
parent 067c410 · parent e41023c · commit 106285b
-rw-r--r--crates/rust-analyzer/src/lsp_utils.rs10
-rw-r--r--crates/rust-analyzer/src/main_loop.rs26
2 files changed, 28 insertions, 8 deletions
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs
index 5a37cbe2e3..b3cea64d41 100644
--- a/crates/rust-analyzer/src/lsp_utils.rs
+++ b/crates/rust-analyzer/src/lsp_utils.rs
@@ -87,6 +87,7 @@ impl GlobalState {
state: Progress,
message: Option<String>,
fraction: Option<f64>,
+ cancel_token: Option<String>,
) {
if !self.config.work_done_progress() {
return;
@@ -95,7 +96,10 @@ impl GlobalState {
assert!((0.0..=1.0).contains(&f));
(f * 100.0) as u32
});
- let token = lsp_types::ProgressToken::String(format!("rustAnalyzer/{}", title));
+ let cancellable = Some(cancel_token.is_some());
+ let token = lsp_types::ProgressToken::String(
+ cancel_token.unwrap_or_else(|| format!("rustAnalyzer/{}", title)),
+ );
let work_done_progress = match state {
Progress::Begin => {
self.send_request::<lsp_types::request::WorkDoneProgressCreate>(
@@ -105,14 +109,14 @@ impl GlobalState {
lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin {
title: title.into(),
- cancellable: None,
+ cancellable,
message,
percentage,
})
}
Progress::Report => {
lsp_types::WorkDoneProgress::Report(lsp_types::WorkDoneProgressReport {
- cancellable: None,
+ cancellable,
message,
percentage,
})
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 15922dac65..3a379993ad 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -257,7 +257,7 @@ impl GlobalState {
}
};
- self.report_progress("Indexing", state, message, Some(fraction));
+ self.report_progress("Indexing", state, message, Some(fraction), None);
}
}
Event::Vfs(message) => {
@@ -465,7 +465,7 @@ impl GlobalState {
}
};
- self.report_progress("Fetching", state, msg, None);
+ self.report_progress("Fetching", state, msg, None, None);
}
Task::FetchBuildData(progress) => {
let (state, msg) = match progress {
@@ -481,7 +481,7 @@ impl GlobalState {
};
if let Some(state) = state {
- self.report_progress("Loading", state, msg, None);
+ self.report_progress("Loading", state, msg, None, None);
}
}
}
@@ -518,6 +518,7 @@ impl GlobalState {
state,
Some(format!("{}/{}", n_done, n_total)),
Some(Progress::fraction(n_done, n_total)),
+ None,
)
}
}
@@ -584,7 +585,13 @@ impl GlobalState {
} else {
format!("cargo check (#{})", id + 1)
};
- self.report_progress(&title, state, message, None);
+ self.report_progress(
+ &title,
+ state,
+ message,
+ None,
+ Some(format!("rust-analyzer/checkOnSave/{}", id)),
+ );
}
}
}
@@ -698,7 +705,16 @@ impl GlobalState {
this.cancel(id);
Ok(())
})?
- .on::<lsp_types::notification::WorkDoneProgressCancel>(|_this, _params| {
+ .on::<lsp_types::notification::WorkDoneProgressCancel>(|this, params| {
+ if let lsp_types::NumberOrString::String(s) = &params.token {
+ if let Some(id) = s.strip_prefix("rust-analyzer/checkOnSave/") {
+ if let Ok(id) = u32::from_str_radix(id, 10) {
+ if let Some(flycheck) = this.flycheck.get(id as usize) {
+ flycheck.cancel();
+ }
+ }
+ }
+ }
// Just ignore this. It is OK to continue sending progress
// notifications for this token, as the client can't know when
// we accepted notification.