typescript: Complete function calls with snippets (#11157)

This allows function call (i.e. snippet) completion with
`typescript-language-server`. So far that didn't work, because
`typescript-language-server` doesn't respond with `insertText` when
getting the completions, but only when then sending
`completionItem/resolve` requests. See:
https://github.com/hrsh7th/nvim-cmp/issues/646#issuecomment-992765479

What this PR does is to support text edits in the response to
`completionItem/resolve`, which means updating the completion item.

It then enables this feature by default for
`typescript-language-server`.


TODOs:

- [x] Make this work over collab
- [x] Test that this doesn't break existing language server support
- [x] Refactor duplicated code

Release Notes:

- Added support for function call completion when using
`typescript-language-server`. This will result in parameters being
added, which can then be changed and navigated with `<tab>`. For this to
work with `typescript-language-server`, the documentation for a given
completion item needs to be resolved, meaning that if one types very
quickly and accepts completion before `typescript-language-server` could
respond with the documentation, no full function completion is used.

Demo:


https://github.com/zed-industries/zed/assets/1185253/c23ebe12-5902-4b50-888c-d9b8cd32965d
This commit is contained in:
Thorsten Ball 2024-05-02 10:50:01 +02:00 committed by GitHub
parent d8ca15372c
commit c81230405f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 256 additions and 50 deletions

View file

@ -837,6 +837,7 @@ impl CompletionsMenu {
}
fn pre_resolve_completion_documentation(
buffer: Model<Buffer>,
completions: Arc<RwLock<Box<[Completion]>>>,
matches: Arc<[StringMatch]>,
editor: &Editor,
@ -852,6 +853,7 @@ impl CompletionsMenu {
};
let resolve_task = provider.resolve_completions(
buffer,
matches.iter().map(|m| m.candidate_id).collect(),
completions.clone(),
cx,
@ -880,7 +882,12 @@ impl CompletionsMenu {
};
let resolve_task = project.update(cx, |project, cx| {
project.resolve_completions(vec![completion_index], self.completions.clone(), cx)
project.resolve_completions(
self.buffer.clone(),
vec![completion_index],
self.completions.clone(),
cx,
)
});
let delay_ms =
@ -3463,7 +3470,7 @@ impl Editor {
)
})
.collect(),
buffer,
buffer: buffer.clone(),
completions: Arc::new(RwLock::new(completions.into())),
matches: Vec::new().into(),
selected_item: 0,
@ -3490,6 +3497,7 @@ impl Editor {
.completion_documentation_pre_resolve_debounce
.fire_new(delay, cx, |editor, cx| {
CompletionsMenu::pre_resolve_completion_documentation(
buffer,
completions,
matches,
editor,
@ -10213,6 +10221,7 @@ pub trait CompletionProvider {
fn resolve_completions(
&self,
buffer: Model<Buffer>,
completion_indices: Vec<usize>,
completions: Arc<RwLock<Box<[Completion]>>>,
cx: &mut ViewContext<Editor>,
@ -10241,12 +10250,13 @@ impl CompletionProvider for Model<Project> {
fn resolve_completions(
&self,
buffer: Model<Buffer>,
completion_indices: Vec<usize>,
completions: Arc<RwLock<Box<[Completion]>>>,
cx: &mut ViewContext<Editor>,
) -> Task<Result<bool>> {
self.update(cx, |project, cx| {
project.resolve_completions(completion_indices, completions, cx)
project.resolve_completions(buffer, completion_indices, completions, cx)
})
}