lsp: Provide completion reason in the request (#12893)

This should help LS make a better call about the completions it should
return back to the caller. For example, it speeds up import completions
for typescript.
Before: 


https://github.com/zed-industries/zed/assets/24362066/b38fd565-f9ff-4db7-a87f-c3b31a9fdc96

after: 


https://github.com/zed-industries/zed/assets/24362066/d4fbc9ae-9aab-4543-b9f6-16acf1619576


This should be merged after 06.12 Preview to give it some time on
Nightly.

Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2024-06-13 14:38:34 +02:00 committed by GitHub
parent eb7b5a7131
commit 0a13b9ee01
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 86 additions and 26 deletions

View file

@ -125,6 +125,11 @@ pub struct ExpandExcerptsDown {
#[serde(default)]
pub(super) lines: u32,
}
#[derive(PartialEq, Clone, Deserialize, Default)]
pub struct ShowCompletions {
#[serde(default)]
pub(super) trigger: Option<char>,
}
impl_actions!(
editor,
@ -147,6 +152,7 @@ impl_actions!(
SelectToBeginningOfLine,
SelectToEndOfLine,
SelectUpByLines,
ShowCompletions,
ToggleCodeActions,
ToggleComments,
UnfoldAt,
@ -274,7 +280,6 @@ gpui::actions!(
SelectToStartOfParagraph,
SelectUp,
ShowCharacterPalette,
ShowCompletions,
ShowInlineCompletion,
ShuffleLines,
SortLinesCaseInsensitive,

View file

@ -93,7 +93,8 @@ use linked_editing_ranges::refresh_linked_ranges;
use task::{ResolvedTask, TaskTemplate, TaskVariables};
use hover_links::{HoverLink, HoveredLinkState, InlayHighlight};
use lsp::{DiagnosticSeverity, LanguageServerId};
pub use lsp::CompletionContext;
use lsp::{CompletionTriggerKind, DiagnosticSeverity, LanguageServerId};
use mouse_context_menu::MouseContextMenu;
use movement::TextLayoutDetails;
pub use multi_buffer::{
@ -2300,7 +2301,7 @@ impl Editor {
.detach();
if show_completions {
self.show_completions(&ShowCompletions, cx);
self.show_completions(&ShowCompletions { trigger: None }, cx);
}
} else {
drop(context_menu);
@ -3494,7 +3495,12 @@ impl Editor {
cx: &mut ViewContext<Self>,
) {
if self.is_completion_trigger(text, trigger_in_words, cx) {
self.show_completions(&ShowCompletions, cx);
self.show_completions(
&ShowCompletions {
trigger: text.chars().last(),
},
cx,
);
} else {
self.hide_context_menu(cx);
}
@ -3890,7 +3896,7 @@ impl Editor {
}))
}
pub fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
pub fn show_completions(&mut self, options: &ShowCompletions, cx: &mut ViewContext<Self>) {
if self.pending_rename.is_some() {
return;
}
@ -3908,7 +3914,29 @@ impl Editor {
};
let query = Self::completion_query(&self.buffer.read(cx).read(cx), position);
let completions = provider.completions(&buffer, buffer_position, cx);
let is_followup_invoke = {
let context_menu_state = self.context_menu.read();
matches!(
context_menu_state.deref(),
Some(ContextMenu::Completions(_))
)
};
let trigger_kind = match (options.trigger, is_followup_invoke) {
(_, true) => CompletionTriggerKind::TRIGGER_FOR_INCOMPLETE_COMPLETIONS,
(Some(_), _) => CompletionTriggerKind::TRIGGER_CHARACTER,
_ => CompletionTriggerKind::INVOKED,
};
let completion_context = CompletionContext {
trigger_character: options.trigger.and_then(|c| {
if trigger_kind == CompletionTriggerKind::TRIGGER_CHARACTER {
Some(String::from(c))
} else {
None
}
}),
trigger_kind,
};
let completions = provider.completions(&buffer, buffer_position, completion_context, cx);
let id = post_inc(&mut self.next_completion_id);
let task = cx.spawn(|this, mut cx| {
@ -4166,7 +4194,7 @@ impl Editor {
}
if completion.show_new_completions_on_confirm {
self.show_completions(&ShowCompletions, cx);
self.show_completions(&ShowCompletions { trigger: None }, cx);
}
let provider = self.completion_provider.as_ref()?;
@ -11428,6 +11456,7 @@ pub trait CompletionProvider {
&self,
buffer: &Model<Buffer>,
buffer_position: text::Anchor,
trigger: CompletionContext,
cx: &mut ViewContext<Editor>,
) -> Task<Result<Vec<Completion>>>;
@ -11462,10 +11491,11 @@ impl CompletionProvider for Model<Project> {
&self,
buffer: &Model<Buffer>,
buffer_position: text::Anchor,
options: CompletionContext,
cx: &mut ViewContext<Editor>,
) -> Task<Result<Vec<Completion>>> {
self.update(cx, |project, cx| {
project.completions(&buffer, buffer_position, cx)
project.completions(&buffer, buffer_position, options, cx)
})
}

View file

@ -6705,7 +6705,7 @@ async fn test_completion(cx: &mut gpui::TestAppContext) {
cx.assert_editor_state("editor.cloˇ");
assert!(cx.editor(|e, _| e.context_menu.read().is_none()));
cx.update_editor(|editor, cx| {
editor.show_completions(&ShowCompletions, cx);
editor.show_completions(&ShowCompletions { trigger: None }, cx);
});
handle_completion_request(
&mut cx,