@@ -549,9 +549,7 @@ pub struct Editor {
549549 signature_help_state: SignatureHelpState,
550550 auto_signature_help: Option<bool>,
551551 find_all_references_task_sources: Vec<Anchor>,
552- // invariant: backup_completion_task.is_some() -> latest_completion_task.is_some()
553- backup_completion_task: Option<(CompletionId, Task<Option<()>>)>,
554- latest_completion_task: Option<(CompletionId, Task<Option<()>>)>,
552+ completion_tasks: CompletionsTasks,
555553 next_completion_id: CompletionId,
556554 completion_documentation_pre_resolve_debounce: DebouncedDelay,
557555 available_code_actions: Option<(Location, Arc<[CodeAction]>)>,
@@ -855,6 +853,22 @@ enum ContextMenu {
855853 CodeActions(CodeActionsMenu),
856854}
857855
856+ #[derive(Default, Debug)]
857+ enum CompletionsTasks {
858+ Single {
859+ id: CompletionId,
860+ task: Task<Option<()>>,
861+ },
862+ WithBackup {
863+ latest_id: CompletionId,
864+ latest_task: Task<Option<()>>,
865+ backup_id: CompletionId,
866+ backup_task: Task<Option<()>>,
867+ },
868+ #[default]
869+ None,
870+ }
871+
858872impl ContextMenu {
859873 fn select_first(
860874 &mut self,
@@ -1893,8 +1907,7 @@ impl Editor {
18931907 nav_history: None,
18941908 context_menu: RwLock::new(None),
18951909 mouse_context_menu: None,
1896- latest_completion_task: None,
1897- backup_completion_task: None,
1910+ completion_tasks: CompletionsTasks::None,
18981911 signature_help_state: SignatureHelpState::default(),
18991912 auto_signature_help: None,
19001913 find_all_references_task_sources: Vec::new(),
@@ -4227,20 +4240,20 @@ impl Editor {
42274240 .trigger
42284241 .as_ref()
42294242 .and_then(|trigger| trigger.chars().next());
4230- let should_cancel_backup = first_char.is_some_and(|char| !classifier.is_word(char));
4243+ let should_cancel_previous = first_char.is_some_and(|char| !classifier.is_word(char));
42314244 let completions = provider.completions(&buffer, buffer_position, completion_context, cx);
42324245 let sort_completions = provider.sort_completions();
42334246
42344247 let id = post_inc(&mut self.next_completion_id);
42354248 dbg!(
42364249 id,
42374250 &options.trigger,
4238- &should_cancel_backup,
4239- &self.backup_completion_task,
4240- &self.latest_completion_task,
4251+ &should_cancel_previous,
4252+ &self.completion_tasks,
42414253 );
4242- if should_cancel_backup {
4243- self.backup_completion_task = None;
4254+ if should_cancel_previous {
4255+ self.completion_tasks = CompletionsTasks::None;
4256+ // maybe even close the menu?
42444257 }
42454258 let task = cx.spawn(|this, mut cx| {
42464259 async move {
@@ -4325,25 +4338,33 @@ impl Editor {
43254338 _ => return,
43264339 }
43274340
4328- let is_latest = if this
4329- .latest_completion_task
4330- .as_ref()
4331- .map_or(false, |(task_id, _)| *task_id == id)
4332- {
4333- // we drop the both tasks
4334- this.backup_completion_task = None;
4335- this.latest_completion_task = None;
4336- true
4337- } else if this
4338- .backup_completion_task
4339- .as_ref()
4340- .map_or(false, |(task_id, _)| *task_id == id)
4341- {
4342- this.backup_completion_task = None;
4343- false
4344- } else {
4345- // the task didn't get cancelled, so we manually return
4346- return;
4341+ let is_latest = match std::mem::take(&mut this.completion_tasks) {
4342+ CompletionsTasks::Single { id: latest_id, .. }
4343+ | CompletionsTasks::WithBackup { latest_id, .. }
4344+ if latest_id == id =>
4345+ {
4346+ // if this is latest completion task, then drop all
4347+ this.completion_tasks = CompletionsTasks::None;
4348+ true
4349+ }
4350+ CompletionsTasks::WithBackup {
4351+ backup_id,
4352+ latest_id,
4353+ latest_task,
4354+ ..
4355+ } if backup_id == id => {
4356+ // convert to single task
4357+ this.completion_tasks = CompletionsTasks::Single {
4358+ id: latest_id,
4359+ task: latest_task,
4360+ };
4361+ false
4362+ }
4363+ // neither latest nor backup task
4364+ _ => {
4365+ // the task didn't get cancelled, so we manually return
4366+ return;
4367+ }
43474368 };
43484369 if this.focus_handle.is_focused(cx) && menu.is_some() {
43494370 let menu = menu.unwrap();
@@ -4366,9 +4387,34 @@ impl Editor {
43664387 }
43674388 .log_err()
43684389 });
4369- let prev_task = std::mem::replace(&mut self.latest_completion_task, Some((id, task)));
4370- if self.backup_completion_task.is_none() {
4371- self.backup_completion_task = prev_task;
4390+ match std::mem::take(&mut self.completion_tasks) {
4391+ CompletionsTasks::None => self.completion_tasks = CompletionsTasks::Single { id, task },
4392+ CompletionsTasks::Single {
4393+ id: prev_id,
4394+ task: prev_task,
4395+ } => {
4396+ // move prev task to backup
4397+ self.completion_tasks = CompletionsTasks::WithBackup {
4398+ latest_id: id,
4399+ latest_task: task,
4400+ backup_id: prev_id,
4401+ backup_task: prev_task,
4402+ }
4403+ }
4404+ CompletionsTasks::WithBackup {
4405+ latest_id: prev_latest_id,
4406+ latest_task: prev_latest_task,
4407+ backup_id,
4408+ backup_task,
4409+ } => {
4410+ // replace the latest task
4411+ self.completion_tasks = &CompletionsTasks::WithBackup {
4412+ latest_id: id,
4413+ latest_task: task,
4414+ backup_id,
4415+ backup_task,
4416+ }
4417+ }
43724418 }
43734419 }
43744420
@@ -4631,8 +4677,7 @@ impl Editor {
46314677 return None;
46324678 }
46334679
4634- editor.latest_completion_task = None;
4635- editor.backup_completion_task = None;
4680+ editor.completion_tasks = CompletionsTasks::None;
46364681 editor.discard_inline_completion(false, cx);
46374682 let task_context =
46384683 tasks
@@ -5240,7 +5285,7 @@ impl Editor {
52405285 let excerpt_id = cursor.excerpt_id;
52415286
52425287 if self.context_menu.read().is_none()
5243- && self.latest_completion_task.is_none( )
5288+ && matches!( self.completion_tasks, CompletionsTasks::None )
52445289 && selection.start == selection.end
52455290 {
52465291 if let Some(provider) = self.inline_completion_provider() {
@@ -5412,8 +5457,7 @@ impl Editor {
54125457
54135458 fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
54145459 cx.notify();
5415- self.latest_completion_task = None;
5416- self.backup_completion_task = None;
5460+ self.completion_tasks = CompletionsTasks::None;
54175461 let context_menu = self.context_menu.write().take();
54185462 if context_menu.is_some() {
54195463 self.update_visible_inline_completion(cx);
0 commit comments