From b6a9d90609db840b3d6b1487b85ff1cad37156b3 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 3 Apr 2023 13:30:57 +0200 Subject: [PATCH 1/3] Move creation of `GetCompletionsParams` entirely to the background --- crates/copilot/src/copilot.rs | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index d27332cbde..1fb7ee0b5b 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -522,6 +522,9 @@ impl Copilot { let language = snapshot.language_at(position); let language_name = language.map(|language| language.name()); let language_name = language_name.as_deref(); + let tab_size = settings.tab_size(language_name); + let hard_tabs = settings.hard_tabs(language_name); + let language_id = id_for_language(language); let path; let relative_path; @@ -537,22 +540,23 @@ impl Copilot { relative_path = PathBuf::new(); } - let params = request::GetCompletionsParams { - doc: request::GetCompletionsDocument { - source: snapshot.text(), - tab_size: settings.tab_size(language_name).into(), - indent_size: 1, - insert_spaces: !settings.hard_tabs(language_name), - uri, - path: path.to_string_lossy().into(), - relative_path: relative_path.to_string_lossy().into(), - language_id: id_for_language(language), - position: point_to_lsp(position), - version: 0, - }, - }; cx.background().spawn(async move { - let result = server.request::(params).await?; + let result = server + .request::(request::GetCompletionsParams { + doc: request::GetCompletionsDocument { + source: snapshot.text(), + tab_size: tab_size.into(), + indent_size: 1, + insert_spaces: !hard_tabs, + uri, + path: path.to_string_lossy().into(), + relative_path: relative_path.to_string_lossy().into(), + language_id, + position: point_to_lsp(position), + version: 0, + }, + }) + .await?; let completions = result .completions .into_iter() From ec5309b543b4a23403ce2e361c7d6fdd0fd45233 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 3 Apr 2023 13:56:11 +0200 Subject: [PATCH 2/3] Make autocompletion and copilot mutually exclusive --- crates/editor/src/display_map.rs | 4 + .../editor/src/display_map/suggestion_map.rs | 5 ++ crates/editor/src/editor.rs | 80 +++++++------------ 3 files changed, 36 insertions(+), 53 deletions(-) diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index c9869e7a9c..c5e6b371ed 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -230,6 +230,10 @@ impl DisplayMap { self.text_highlights.remove(&Some(type_id)) } + pub fn has_suggestion(&self) -> bool { + self.suggestion_map.has_suggestion() + } + pub fn replace_suggestion( &self, new_suggestion: Option>, diff --git a/crates/editor/src/display_map/suggestion_map.rs b/crates/editor/src/display_map/suggestion_map.rs index 0fc2a025fe..ccc07bf591 100644 --- a/crates/editor/src/display_map/suggestion_map.rs +++ b/crates/editor/src/display_map/suggestion_map.rs @@ -171,6 +171,11 @@ impl SuggestionMap { (snapshot.clone(), suggestion_edits) } + + pub fn has_suggestion(&self) -> bool { + let snapshot = self.0.lock(); + snapshot.suggestion.is_some() + } } #[derive(Clone)] diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 5c6470fe90..0d365aee50 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2188,7 +2188,9 @@ impl Editor { } fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext) { - if !cx.global::().show_completions_on_input { + if !cx.global::().show_completions_on_input + || self.has_active_copilot_suggestion(cx) + { return; } @@ -2373,11 +2375,11 @@ impl Editor { } this.completion_tasks.retain(|(id, _)| *id > menu.id); - if this.focused { + if this.focused && !menu.matches.is_empty() { this.show_context_menu(ContextMenu::Completions(menu), cx); + } else { + this.hide_context_menu(cx); } - - cx.notify(); }); } Ok::<_, anyhow::Error>(()) @@ -2806,33 +2808,9 @@ impl Editor { let cursor = if selection.start == selection.end { selection.start.bias_left(&snapshot) } else { - self.clear_copilot_suggestions(cx); return None; }; - - if let Some(new_text) = self - .copilot_state - .text_for_active_completion(cursor, &snapshot) - { - self.display_map.update(cx, |map, cx| { - map.replace_suggestion( - Some(Suggestion { - position: cursor, - text: new_text.into(), - }), - cx, - ) - }); - self.copilot_state - .completions - .swap(0, self.copilot_state.active_completion_index); - self.copilot_state.completions.truncate(1); - self.copilot_state.active_completion_index = 0; - cx.notify(); - } else { - self.display_map - .update(cx, |map, cx| map.replace_suggestion::(None, cx)); - } + self.refresh_active_copilot_suggestion(cx); if !copilot.read(cx).status().is_authorized() { return None; @@ -2860,23 +2838,7 @@ impl Editor { for completion in completions { this.copilot_state.push_completion(completion); } - - let buffer = this.buffer.read(cx).snapshot(cx); - if let Some(text) = this - .copilot_state - .text_for_active_completion(cursor, &buffer) - { - this.display_map.update(cx, |map, cx| { - map.replace_suggestion( - Some(Suggestion { - position: cursor, - text: text.into(), - }), - cx, - ) - }); - } - cx.notify(); + this.refresh_active_copilot_suggestion(cx); } }); @@ -2901,7 +2863,7 @@ impl Editor { self.copilot_state.active_completion_index = (self.copilot_state.active_completion_index + 1) % self.copilot_state.completions.len(); - self.sync_suggestion(cx); + self.refresh_active_copilot_suggestion(cx); } fn previous_copilot_suggestion( @@ -2927,7 +2889,7 @@ impl Editor { self.copilot_state.active_completion_index - 1 }; - self.sync_suggestion(cx); + self.refresh_active_copilot_suggestion(cx); } fn toggle_copilot_suggestions(&mut self, _: &copilot::Toggle, cx: &mut ViewContext) { @@ -2957,11 +2919,13 @@ impl Editor { cx.notify(); } - fn sync_suggestion(&mut self, cx: &mut ViewContext) { + fn refresh_active_copilot_suggestion(&mut self, cx: &mut ViewContext) { let snapshot = self.buffer.read(cx).snapshot(cx); let cursor = self.selections.newest_anchor().head(); - - if let Some(text) = self + if self.context_menu.is_some() { + self.display_map + .update(cx, |map, cx| map.replace_suggestion::(None, cx)); + } else if let Some(text) = self .copilot_state .text_for_active_completion(cursor, &snapshot) { @@ -2974,8 +2938,11 @@ impl Editor { cx, ) }); - cx.notify(); + } else { + self.display_map + .update(cx, |map, cx| map.replace_suggestion::(None, cx)); } + cx.notify(); } fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext) -> bool { @@ -3005,6 +2972,10 @@ impl Editor { !was_empty } + fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool { + self.display_map.read(cx).has_suggestion() + } + pub fn render_code_actions_indicator( &self, style: &EditorStyle, @@ -3120,13 +3091,16 @@ impl Editor { self.completion_tasks.clear(); } self.context_menu = Some(menu); + self.refresh_active_copilot_suggestion(cx); cx.notify(); } fn hide_context_menu(&mut self, cx: &mut ViewContext) -> Option { cx.notify(); self.completion_tasks.clear(); - self.context_menu.take() + let context_menu = self.context_menu.take(); + self.refresh_active_copilot_suggestion(cx); + context_menu } pub fn insert_snippet( From b88aa9af1de418d671be798a06a64ab51df4608f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 3 Apr 2023 14:32:41 +0200 Subject: [PATCH 3/3] Clear active copilot suggestion only if there is one --- crates/editor/src/editor.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 0d365aee50..7a8293e195 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2922,9 +2922,11 @@ impl Editor { fn refresh_active_copilot_suggestion(&mut self, cx: &mut ViewContext) { let snapshot = self.buffer.read(cx).snapshot(cx); let cursor = self.selections.newest_anchor().head(); + if self.context_menu.is_some() { self.display_map .update(cx, |map, cx| map.replace_suggestion::(None, cx)); + cx.notify(); } else if let Some(text) = self .copilot_state .text_for_active_completion(cursor, &snapshot) @@ -2938,11 +2940,12 @@ impl Editor { cx, ) }); - } else { + cx.notify(); + } else if self.has_active_copilot_suggestion(cx) { self.display_map .update(cx, |map, cx| map.replace_suggestion::(None, cx)); + cx.notify(); } - cx.notify(); } fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext) -> bool {