Detailed changes
@@ -180,6 +180,7 @@ pub struct CompletionsMenu {
scroll_handle: UniformListScrollHandle,
resolve_completions: bool,
show_completion_documentation: bool,
+ pub(super) ignore_completion_provider: bool,
last_rendered_range: Rc<RefCell<Option<Range<usize>>>>,
markdown_element: Option<Entity<Markdown>>,
}
@@ -189,6 +190,7 @@ impl CompletionsMenu {
id: CompletionId,
sort_completions: bool,
show_completion_documentation: bool,
+ ignore_completion_provider: bool,
initial_position: Anchor,
buffer: Entity<Buffer>,
completions: Box<[Completion]>,
@@ -205,6 +207,7 @@ impl CompletionsMenu {
initial_position,
buffer,
show_completion_documentation,
+ ignore_completion_provider,
completions: RefCell::new(completions).into(),
match_candidates,
entries: RefCell::new(Vec::new()).into(),
@@ -266,6 +269,7 @@ impl CompletionsMenu {
scroll_handle: UniformListScrollHandle::new(),
resolve_completions: false,
show_completion_documentation: false,
+ ignore_completion_provider: false,
last_rendered_range: RefCell::new(None).into(),
markdown_element: None,
}
@@ -3546,7 +3546,21 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
- if self.is_completion_trigger(text, trigger_in_words, cx) {
+ let ignore_completion_provider = self
+ .context_menu
+ .borrow()
+ .as_ref()
+ .map(|menu| match menu {
+ CodeContextMenu::Completions(completions_menu) => {
+ completions_menu.ignore_completion_provider
+ }
+ CodeContextMenu::CodeActions(_) => false,
+ })
+ .unwrap_or(false);
+
+ if ignore_completion_provider {
+ self.show_word_completions(&ShowWordCompletions, window, cx);
+ } else if self.is_completion_trigger(text, trigger_in_words, cx) {
self.show_completions(
&ShowCompletions {
trigger: Some(text.to_owned()).filter(|x| !x.is_empty()),
@@ -4183,6 +4197,7 @@ impl Editor {
id,
sort_completions,
show_completion_documentation,
+ ignore_completion_provider,
position,
buffer.clone(),
completions.into(),
@@ -9212,7 +9212,7 @@ async fn test_completion(cx: &mut TestAppContext) {
}
#[gpui::test]
-async fn test_words_completion(cx: &mut TestAppContext) {
+async fn test_word_completion(cx: &mut TestAppContext) {
let lsp_fetch_timeout_ms = 10;
init_test(cx, |language_settings| {
language_settings.defaults.completions = Some(CompletionSettings {
@@ -9354,7 +9354,7 @@ async fn test_word_completions_do_not_duplicate_lsp_ones(cx: &mut TestAppContext
cx.executor().run_until_parked();
cx.condition(|editor, _| editor.context_menu_visible())
.await;
- cx.update_editor(|editor, window, cx| {
+ cx.update_editor(|editor, _, _| {
if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.borrow_mut().as_ref()
{
assert_eq!(
@@ -9365,7 +9365,78 @@ async fn test_word_completions_do_not_duplicate_lsp_ones(cx: &mut TestAppContext
} else {
panic!("expected completion menu to be open");
}
- editor.cancel(&Cancel, window, cx);
+ });
+}
+
+#[gpui::test]
+async fn test_word_completions_continue_on_typing(cx: &mut TestAppContext) {
+ init_test(cx, |language_settings| {
+ language_settings.defaults.completions = Some(CompletionSettings {
+ words: WordsCompletionMode::Disabled,
+ lsp: true,
+ lsp_fetch_timeout_ms: 0,
+ });
+ });
+
+ let mut cx = EditorLspTestContext::new_rust(
+ lsp::ServerCapabilities {
+ completion_provider: Some(lsp::CompletionOptions {
+ trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
+ ..lsp::CompletionOptions::default()
+ }),
+ signature_help_provider: Some(lsp::SignatureHelpOptions::default()),
+ ..lsp::ServerCapabilities::default()
+ },
+ cx,
+ )
+ .await;
+
+ let _completion_requests_handler =
+ cx.lsp
+ .server
+ .on_request::<lsp::request::Completion, _, _>(move |_, _| async move {
+ panic!("LSP completions should not be queried when dealing with word completions")
+ });
+
+ cx.set_state(indoc! {"ˇ
+ first
+ last
+ second
+ "});
+ cx.update_editor(|editor, window, cx| {
+ editor.show_word_completions(&ShowWordCompletions, window, cx);
+ });
+ cx.executor().run_until_parked();
+ cx.condition(|editor, _| editor.context_menu_visible())
+ .await;
+ cx.update_editor(|editor, _, _| {
+ if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.borrow_mut().as_ref()
+ {
+ assert_eq!(
+ completion_menu_entries(&menu),
+ &["first", "last", "second"],
+ "`ShowWordCompletions` action should show word completions"
+ );
+ } else {
+ panic!("expected completion menu to be open");
+ }
+ });
+
+ cx.simulate_keystroke("s");
+ cx.executor().run_until_parked();
+ cx.condition(|editor, _| editor.context_menu_visible())
+ .await;
+ cx.update_editor(|editor, _, _| {
+ if let Some(CodeContextMenu::Completions(menu)) = editor.context_menu.borrow_mut().as_ref()
+ {
+ assert_eq!(
+ completion_menu_entries(&menu),
+ &["second"],
+ "After showing word completions, further editing should filter them and not query the LSP"
+ );
+ } else {
+ panic!("expected completion menu to be open");
+ }
});
}