Merge pull request #1871 from zed-industries/skip-additional-edit-within-primary

Skip LSP additional completion edits which fall within primary edit
This commit is contained in:
Julia 2022-11-11 10:31:41 -05:00 committed by GitHub
commit b6f78cd5dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 21 deletions

View file

@ -4146,14 +4146,26 @@ async fn test_completion(cx: &mut gpui::TestAppContext) {
handle_resolve_completion_request( handle_resolve_completion_request(
&mut cx, &mut cx,
Some(( Some(vec![
indoc! {" (
one.second_completion //This overlaps with the primary completion edit which is
two //misbehavior from the LSP spec, test that we filter it out
threeˇ indoc! {"
"}, one.second_ˇcompletion
"\nadditional edit", two
)), threeˇ
"},
"overlapping aditional edit",
),
(
indoc! {"
one.second_completion
two
threeˇ
"},
"\nadditional edit",
),
]),
) )
.await; .await;
apply_additional_edits.await.unwrap(); apply_additional_edits.await.unwrap();
@ -4303,19 +4315,24 @@ async fn test_completion(cx: &mut gpui::TestAppContext) {
async fn handle_resolve_completion_request<'a>( async fn handle_resolve_completion_request<'a>(
cx: &mut EditorLspTestContext<'a>, cx: &mut EditorLspTestContext<'a>,
edit: Option<(&'static str, &'static str)>, edits: Option<Vec<(&'static str, &'static str)>>,
) { ) {
let edit = edit.map(|(marked_string, new_text)| { let edits = edits.map(|edits| {
let (_, marked_ranges) = marked_text_ranges(marked_string, false); edits
let replace_range = cx.to_lsp_range(marked_ranges[0].clone()); .iter()
vec![lsp::TextEdit::new(replace_range, new_text.to_string())] .map(|(marked_string, new_text)| {
let (_, marked_ranges) = marked_text_ranges(marked_string, false);
let replace_range = cx.to_lsp_range(marked_ranges[0].clone());
lsp::TextEdit::new(replace_range, new_text.to_string())
})
.collect::<Vec<_>>()
}); });
cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| { cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
let edit = edit.clone(); let edits = edits.clone();
async move { async move {
Ok(lsp::CompletionItem { Ok(lsp::CompletionItem {
additional_text_edits: edit, additional_text_edits: edits,
..Default::default() ..Default::default()
}) })
} }

View file

@ -3453,29 +3453,41 @@ impl Project {
let buffer_id = buffer.remote_id(); let buffer_id = buffer.remote_id();
if self.is_local() { if self.is_local() {
let lang_server = if let Some((_, server)) = self.language_server_for_buffer(buffer, cx) let lang_server = match self.language_server_for_buffer(buffer, cx) {
{ Some((_, server)) => server.clone(),
server.clone() _ => return Task::ready(Ok(Default::default())),
} else {
return Task::ready(Ok(Default::default()));
}; };
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
let resolved_completion = lang_server let resolved_completion = lang_server
.request::<lsp::request::ResolveCompletionItem>(completion.lsp_completion) .request::<lsp::request::ResolveCompletionItem>(completion.lsp_completion)
.await?; .await?;
if let Some(edits) = resolved_completion.additional_text_edits { if let Some(edits) = resolved_completion.additional_text_edits {
let edits = this let edits = this
.update(&mut cx, |this, cx| { .update(&mut cx, |this, cx| {
this.edits_from_lsp(&buffer_handle, edits, None, cx) this.edits_from_lsp(&buffer_handle, edits, None, cx)
}) })
.await?; .await?;
buffer_handle.update(&mut cx, |buffer, cx| { buffer_handle.update(&mut cx, |buffer, cx| {
buffer.finalize_last_transaction(); buffer.finalize_last_transaction();
buffer.start_transaction(); buffer.start_transaction();
for (range, text) in edits { for (range, text) in edits {
buffer.edit([(range, text)], None, cx); let primary = &completion.old_range;
let start_within = primary.start.cmp(&range.start, buffer).is_le()
&& primary.end.cmp(&range.start, buffer).is_ge();
let end_within = range.start.cmp(&primary.end, buffer).is_le()
&& range.end.cmp(&primary.end, buffer).is_ge();
//Skip addtional edits which overlap with the primary completion edit
//https://github.com/zed-industries/zed/pull/1871
if !start_within && !end_within {
buffer.edit([(range, text)], None, cx);
}
} }
let transaction = if buffer.end_transaction(cx).is_some() { let transaction = if buffer.end_transaction(cx).is_some() {
let transaction = buffer.finalize_last_transaction().unwrap().clone(); let transaction = buffer.finalize_last_transaction().unwrap().clone();
if !push_to_history { if !push_to_history {