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:
parent
d8ca15372c
commit
c81230405f
7 changed files with 256 additions and 50 deletions
|
@ -1505,18 +1505,11 @@ impl LspCommand for GetCompletions {
|
|||
let edit = match lsp_completion.text_edit.as_ref() {
|
||||
// If the language server provides a range to overwrite, then
|
||||
// check that the range is valid.
|
||||
Some(lsp::CompletionTextEdit::Edit(edit)) => {
|
||||
let range = range_from_lsp(edit.range);
|
||||
let start = snapshot.clip_point_utf16(range.start, Bias::Left);
|
||||
let end = snapshot.clip_point_utf16(range.end, Bias::Left);
|
||||
if start != range.start.0 || end != range.end.0 {
|
||||
log::info!("completion out of expected range");
|
||||
return false;
|
||||
Some(completion_text_edit) => {
|
||||
match parse_completion_text_edit(completion_text_edit, &snapshot) {
|
||||
Some(edit) => edit,
|
||||
None => return false,
|
||||
}
|
||||
(
|
||||
snapshot.anchor_before(start)..snapshot.anchor_after(end),
|
||||
edit.new_text.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
// If the language server does not provide a range, then infer
|
||||
|
@ -1570,21 +1563,6 @@ impl LspCommand for GetCompletions {
|
|||
.clone();
|
||||
(range, text)
|
||||
}
|
||||
|
||||
Some(lsp::CompletionTextEdit::InsertAndReplace(edit)) => {
|
||||
let range = range_from_lsp(edit.insert);
|
||||
|
||||
let start = snapshot.clip_point_utf16(range.start, Bias::Left);
|
||||
let end = snapshot.clip_point_utf16(range.end, Bias::Left);
|
||||
if start != range.start.0 || end != range.end.0 {
|
||||
log::info!("completion out of expected range");
|
||||
return false;
|
||||
}
|
||||
(
|
||||
snapshot.anchor_before(start)..snapshot.anchor_after(end),
|
||||
edit.new_text.clone(),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
completion_edits.push(edit);
|
||||
|
@ -1684,6 +1662,44 @@ impl LspCommand for GetCompletions {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parse_completion_text_edit(
|
||||
edit: &lsp::CompletionTextEdit,
|
||||
snapshot: &BufferSnapshot,
|
||||
) -> Option<(Range<Anchor>, String)> {
|
||||
match edit {
|
||||
lsp::CompletionTextEdit::Edit(edit) => {
|
||||
let range = range_from_lsp(edit.range);
|
||||
let start = snapshot.clip_point_utf16(range.start, Bias::Left);
|
||||
let end = snapshot.clip_point_utf16(range.end, Bias::Left);
|
||||
if start != range.start.0 || end != range.end.0 {
|
||||
log::info!("completion out of expected range");
|
||||
None
|
||||
} else {
|
||||
Some((
|
||||
snapshot.anchor_before(start)..snapshot.anchor_after(end),
|
||||
edit.new_text.clone(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
lsp::CompletionTextEdit::InsertAndReplace(edit) => {
|
||||
let range = range_from_lsp(edit.insert);
|
||||
|
||||
let start = snapshot.clip_point_utf16(range.start, Bias::Left);
|
||||
let end = snapshot.clip_point_utf16(range.end, Bias::Left);
|
||||
if start != range.start.0 || end != range.end.0 {
|
||||
log::info!("completion out of expected range");
|
||||
None
|
||||
} else {
|
||||
Some((
|
||||
snapshot.anchor_before(start)..snapshot.anchor_after(end),
|
||||
edit.new_text.clone(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
impl LspCommand for GetCodeActions {
|
||||
type Response = Vec<CodeAction>;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue