editor: Cancel ongoing completion requests more eagerly (#12630)

Previously, we were:
- cancelling previous requests only after the latest one has completed
- always running the debounced documentation resolution to completion,
even when we had no need for it.

In this commit, we drop the ongoing completion requests as soon as the
new one is fired.
Fixes #5166 

Release Notes:

- Improved performance and reliability of completions in large
Typescript projects

Co-authored-by: Bennet Bo <bennet@zed.dev>
This commit is contained in:
Piotr Osiewicz 2024-06-04 12:22:01 +02:00 committed by GitHub
parent 47122a3115
commit 8e79609288
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 7 additions and 12 deletions

View file

@ -29,13 +29,9 @@ impl DebouncedDelay {
let (sender, mut receiver) = oneshot::channel::<()>(); let (sender, mut receiver) = oneshot::channel::<()>();
self.cancel_channel = Some(sender); self.cancel_channel = Some(sender);
let previous_task = self.task.take(); drop(self.task.take());
self.task = Some(cx.spawn(move |model, mut cx| async move { self.task = Some(cx.spawn(move |model, mut cx| async move {
let mut timer = cx.background_executor().timer(delay).fuse(); let mut timer = cx.background_executor().timer(delay).fuse();
if let Some(previous_task) = previous_task {
previous_task.await;
}
futures::select_biased! { futures::select_biased! {
_ = receiver => return, _ = receiver => return,
_ = timer => {} _ = timer => {}

View file

@ -15,18 +15,17 @@
pub mod actions; pub mod actions;
mod blame_entry_tooltip; mod blame_entry_tooltip;
mod blink_manager; mod blink_manager;
mod debounced_delay;
pub mod display_map; pub mod display_map;
mod editor_settings; mod editor_settings;
mod element; mod element;
mod hunk_diff;
mod inlay_hint_cache;
mod debounced_delay;
mod git; mod git;
mod highlight_matching_bracket; mod highlight_matching_bracket;
mod hover_links; mod hover_links;
mod hover_popover; mod hover_popover;
mod hunk_diff;
mod indent_guides; mod indent_guides;
mod inlay_hint_cache;
mod inline_completion_provider; mod inline_completion_provider;
pub mod items; pub mod items;
mod mouse_context_menu; mod mouse_context_menu;
@ -3806,6 +3805,9 @@ impl Editor {
let id = post_inc(&mut self.next_completion_id); let id = post_inc(&mut self.next_completion_id);
let task = cx.spawn(|this, mut cx| { let task = cx.spawn(|this, mut cx| {
async move { async move {
this.update(&mut cx, |this, _| {
this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
})?;
let completions = completions.await.log_err(); let completions = completions.await.log_err();
let menu = if let Some(completions) = completions { let menu = if let Some(completions) = completions {
let mut menu = CompletionsMenu { let mut menu = CompletionsMenu {
@ -3844,7 +3846,6 @@ impl Editor {
let delay_ms = EditorSettings::get_global(cx) let delay_ms = EditorSettings::get_global(cx)
.completion_documentation_secondary_query_debounce; .completion_documentation_secondary_query_debounce;
let delay = Duration::from_millis(delay_ms); let delay = Duration::from_millis(delay_ms);
editor editor
.completion_documentation_pre_resolve_debounce .completion_documentation_pre_resolve_debounce
.fire_new(delay, cx, |editor, cx| { .fire_new(delay, cx, |editor, cx| {
@ -3865,8 +3866,6 @@ impl Editor {
}; };
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
let mut context_menu = this.context_menu.write(); let mut context_menu = this.context_menu.write();
match context_menu.as_ref() { match context_menu.as_ref() {
None => {} None => {}