Rename LSP function and simplify tests (#27313)

While working on a fix I found opportunities to improve readability, but
it's a big rename diff, so I'm landing separately.

Release Notes:

- N/A
This commit is contained in:
João Marcos 2025-03-22 16:23:11 -03:00 committed by GitHub
parent f4d1e7901c
commit 9f0b09007b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 641 additions and 642 deletions

View file

@ -2300,6 +2300,7 @@ impl Editor {
)
})
.collect();
DB.save_editor_selections(editor_id, workspace_id, selections)
.await
.with_context(|| format!("persisting editor selections for editor {editor_id}, workspace {workspace_id:?}"))
@ -3242,8 +3243,7 @@ impl Editor {
let start_point = TP::to_point(&range.start, &snapshot);
(start_point..end_point, text)
})
.sorted_by_key(|(range, _)| range.start)
.collect::<Vec<_>>();
.sorted_by_key(|(range, _)| range.start);
buffer.edit(edits, None, cx);
})
}
@ -4408,9 +4408,7 @@ impl Editor {
intent: CompletionIntent,
window: &mut Window,
cx: &mut Context<Editor>,
) -> Option<Task<std::result::Result<(), anyhow::Error>>> {
use language::ToOffset as _;
) -> Option<Task<Result<()>>> {
let completions_menu =
if let CodeContextMenu::Completions(menu) = self.hide_context_menu(window, cx)? {
menu
@ -4418,13 +4416,14 @@ impl Editor {
return None;
};
let entries = completions_menu.entries.borrow();
let mat = entries.get(item_ix.unwrap_or(completions_menu.selected_item))?;
if self.show_edit_predictions_in_menu() {
self.discard_inline_completion(true, cx);
}
let candidate_id = mat.candidate_id;
drop(entries);
let candidate_id = {
let entries = completions_menu.entries.borrow();
let mat = entries.get(item_ix.unwrap_or(completions_menu.selected_item))?;
if self.show_edit_predictions_in_menu() {
self.discard_inline_completion(true, cx);
}
mat.candidate_id
};
let buffer_handle = completions_menu.buffer;
let completion = completions_menu
@ -4434,37 +4433,33 @@ impl Editor {
.clone();
cx.stop_propagation();
let snippet;
let text;
if self.selections.newest_anchor().start.buffer_id
!= Some(buffer_handle.read(cx).remote_id())
{
return None;
}
let snippet;
let new_text;
if completion.is_snippet() {
snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
text = snippet.as_ref().unwrap().text.clone();
new_text = snippet.as_ref().unwrap().text.clone();
} else {
snippet = None;
text = completion.new_text.clone();
new_text = completion.new_text.clone();
};
let newest_selection = self.selections.newest::<usize>(cx);
let selections = self.selections.all::<usize>(cx);
let buffer = buffer_handle.read(cx);
let old_range = completion.old_range.to_offset(buffer);
let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
let newest_selection = self.selections.newest_anchor();
if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
return None;
}
let lookbehind = newest_selection
.start
.text_anchor
.to_offset(buffer)
.saturating_sub(old_range.start);
let lookahead = old_range
.end
.saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
let start_distance = newest_selection.start.saturating_sub(old_range.start);
let end_distance = old_range.end.saturating_sub(newest_selection.end);
let mut common_prefix_len = old_text
.bytes()
.zip(text.bytes())
.zip(new_text.bytes())
.take_while(|(a, b)| a == b)
.count();
@ -4473,9 +4468,9 @@ impl Editor {
let mut ranges = Vec::new();
let mut linked_edits = HashMap::<_, Vec<_>>::default();
for selection in &selections {
if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
let start = selection.start.saturating_sub(lookbehind);
let end = selection.end + lookahead;
if snapshot.contains_str_at(selection.start.saturating_sub(start_distance), &old_text) {
let start = selection.start.saturating_sub(start_distance);
let end = selection.end + end_distance;
if selection.id == newest_selection.id {
range_to_replace = Some(
((start + common_prefix_len) as isize - selection.start as isize)
@ -4511,13 +4506,13 @@ impl Editor {
linked_edits.entry(buffer.clone()).or_default().extend(
edits
.into_iter()
.map(|range| (range, text[common_prefix_len..].to_owned())),
.map(|range| (range, new_text[common_prefix_len..].to_owned())),
);
}
}
}
}
let text = &text[common_prefix_len..];
let text = &new_text[common_prefix_len..];
cx.emit(EditorEvent::InputHandled {
utf16_range_to_replace: range_to_replace,
@ -4539,11 +4534,8 @@ impl Editor {
this.insert_snippet(&ranges, snippet, window, cx).log_err();
} else {
this.buffer.update(cx, |buffer, cx| {
buffer.edit(
ranges.iter().map(|range| (range.clone(), text)),
this.autoindent_mode.clone(),
cx,
);
let edits = ranges.iter().map(|range| (range.clone(), text));
buffer.edit(edits, this.autoindent_mode.clone(), cx);
});
}
for (buffer, edits) in linked_edits {
@ -4557,8 +4549,7 @@ impl Editor {
let start_point = TP::to_point(&range.start, &snapshot);
(start_point..end_point, text)
})
.sorted_by_key(|(range, _)| range.start)
.collect::<Vec<_>>();
.sorted_by_key(|(range, _)| range.start);
buffer.edit(edits, None, cx);
})
}
@ -7525,14 +7516,11 @@ impl Editor {
let tabstops = self.buffer.update(cx, |buffer, cx| {
let snippet_text: Arc<str> = snippet.text.clone().into();
buffer.edit(
insertion_ranges
.iter()
.cloned()
.map(|range| (range, snippet_text.clone())),
Some(AutoindentMode::EachLine),
cx,
);
let edits = insertion_ranges
.iter()
.cloned()
.map(|range| (range, snippet_text.clone()));
buffer.edit(edits, Some(AutoindentMode::EachLine), cx);
let snapshot = &*buffer.read(cx);
let snippet = &snippet;

View file

@ -27,6 +27,7 @@ use language::{
Override, Point,
};
use language_settings::{Formatter, FormatterList, IndentGuideSettings};
use lsp::CompletionParams;
use multi_buffer::{IndentGuide, PathKey};
use parking_lot::Mutex;
use pretty_assertions::{assert_eq, assert_ne};
@ -7698,7 +7699,7 @@ async fn test_document_format_during_save(cx: &mut TestAppContext) {
})
.unwrap();
fake_server
.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
.set_request_handler::<lsp::request::Formatting, _, _>(move |params, _| async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/file.rs")).unwrap()
@ -7726,14 +7727,16 @@ async fn test_document_format_during_save(cx: &mut TestAppContext) {
assert!(cx.read(|cx| editor.is_dirty(cx)));
// Ensure we can still save even if formatting hangs.
fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/file.rs")).unwrap()
);
futures::future::pending::<()>().await;
unreachable!()
});
fake_server.set_request_handler::<lsp::request::Formatting, _, _>(
move |params, _| async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/file.rs")).unwrap()
);
futures::future::pending::<()>().await;
unreachable!()
},
);
let save = editor
.update_in(cx, |editor, window, cx| {
editor.save(true, project.clone(), window, cx)
@ -7755,7 +7758,7 @@ async fn test_document_format_during_save(cx: &mut TestAppContext) {
})
.unwrap();
let _pending_format_request = fake_server
.handle_request::<lsp::request::RangeFormatting, _, _>(move |_, _| async move {
.set_request_handler::<lsp::request::RangeFormatting, _, _>(move |_, _| async move {
panic!("Should not be invoked on non-dirty buffer");
})
.next();
@ -7783,7 +7786,7 @@ async fn test_document_format_during_save(cx: &mut TestAppContext) {
})
.unwrap();
fake_server
.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
.set_request_handler::<lsp::request::Formatting, _, _>(move |params, _| async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/file.rs")).unwrap()
@ -8073,7 +8076,7 @@ async fn test_range_format_during_save(cx: &mut TestAppContext) {
})
.unwrap();
fake_server
.handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
.set_request_handler::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/file.rs")).unwrap()
@ -8100,7 +8103,7 @@ async fn test_range_format_during_save(cx: &mut TestAppContext) {
assert!(cx.read(|cx| editor.is_dirty(cx)));
// Ensure we can still save even if formatting hangs.
fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
fake_server.set_request_handler::<lsp::request::RangeFormatting, _, _>(
move |params, _| async move {
assert_eq!(
params.text_document.uri,
@ -8131,7 +8134,7 @@ async fn test_range_format_during_save(cx: &mut TestAppContext) {
})
.unwrap();
let _pending_format_request = fake_server
.handle_request::<lsp::request::RangeFormatting, _, _>(move |_, _| async move {
.set_request_handler::<lsp::request::RangeFormatting, _, _>(move |_, _| async move {
panic!("Should not be invoked on non-dirty buffer");
})
.next();
@ -8159,7 +8162,7 @@ async fn test_range_format_during_save(cx: &mut TestAppContext) {
})
.unwrap();
fake_server
.handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
.set_request_handler::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/file.rs")).unwrap()
@ -8247,7 +8250,7 @@ async fn test_document_format_manual_trigger(cx: &mut TestAppContext) {
})
.unwrap();
fake_server
.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
.set_request_handler::<lsp::request::Formatting, _, _>(move |params, _| async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/file.rs")).unwrap()
@ -8271,14 +8274,16 @@ async fn test_document_format_manual_trigger(cx: &mut TestAppContext) {
editor.set_text("one\ntwo\nthree\n", window, cx)
});
// Ensure we don't lock if formatting hangs.
fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/file.rs")).unwrap()
);
futures::future::pending::<()>().await;
unreachable!()
});
fake_server.set_request_handler::<lsp::request::Formatting, _, _>(
move |params, _| async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/file.rs")).unwrap()
);
futures::future::pending::<()>().await;
unreachable!()
},
);
let format = editor
.update_in(cx, |editor, window, cx| {
editor.perform_format(
@ -8374,7 +8379,7 @@ async fn test_organize_imports_manual_trigger(cx: &mut TestAppContext) {
})
.unwrap();
fake_server
.handle_request::<lsp::request::CodeActionRequest, _, _>(move |params, _| async move {
.set_request_handler::<lsp::request::CodeActionRequest, _, _>(move |params, _| async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/file.ts")).unwrap()
@ -8421,7 +8426,7 @@ async fn test_organize_imports_manual_trigger(cx: &mut TestAppContext) {
)
});
// Ensure we don't lock if code action hangs.
fake_server.handle_request::<lsp::request::CodeActionRequest, _, _>(
fake_server.set_request_handler::<lsp::request::CodeActionRequest, _, _>(
move |params, _| async move {
assert_eq!(
params.text_document.uri,
@ -8470,7 +8475,7 @@ async fn test_concurrent_format_requests(cx: &mut TestAppContext) {
// The format request takes a long time. When it completes, it inserts
// a newline and an indent before the `.`
cx.lsp
.handle_request::<lsp::request::Formatting, _, _>(move |_, cx| {
.set_request_handler::<lsp::request::Formatting, _, _>(move |_, cx| {
let executor = cx.background_executor().clone();
async move {
executor.timer(Duration::from_millis(100)).await;
@ -8554,44 +8559,51 @@ async fn test_strip_whitespace_and_format_via_lsp(cx: &mut TestAppContext) {
});
// Handle formatting requests to the language server.
cx.lsp.handle_request::<lsp::request::Formatting, _, _>({
let buffer_changes = buffer_changes.clone();
move |_, _| {
// When formatting is requested, trailing whitespace has already been stripped,
// and the trailing newline has already been added.
assert_eq!(
&buffer_changes.lock()[1..],
&[
(
lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(0, 4)),
"".into()
),
(
lsp::Range::new(lsp::Position::new(2, 5), lsp::Position::new(2, 6)),
"".into()
),
(
lsp::Range::new(lsp::Position::new(3, 4), lsp::Position::new(3, 4)),
"\n".into()
),
]
);
cx.lsp
.set_request_handler::<lsp::request::Formatting, _, _>({
let buffer_changes = buffer_changes.clone();
move |_, _| {
// When formatting is requested, trailing whitespace has already been stripped,
// and the trailing newline has already been added.
assert_eq!(
&buffer_changes.lock()[1..],
&[
(
lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(0, 4)),
"".into()
),
(
lsp::Range::new(lsp::Position::new(2, 5), lsp::Position::new(2, 6)),
"".into()
),
(
lsp::Range::new(lsp::Position::new(3, 4), lsp::Position::new(3, 4)),
"\n".into()
),
]
);
// Insert blank lines between each line of the buffer.
async move {
Ok(Some(vec![
lsp::TextEdit {
range: lsp::Range::new(lsp::Position::new(1, 0), lsp::Position::new(1, 0)),
new_text: "\n".into(),
},
lsp::TextEdit {
range: lsp::Range::new(lsp::Position::new(2, 0), lsp::Position::new(2, 0)),
new_text: "\n".into(),
},
]))
// Insert blank lines between each line of the buffer.
async move {
Ok(Some(vec![
lsp::TextEdit {
range: lsp::Range::new(
lsp::Position::new(1, 0),
lsp::Position::new(1, 0),
),
new_text: "\n".into(),
},
lsp::TextEdit {
range: lsp::Range::new(
lsp::Position::new(2, 0),
lsp::Position::new(2, 0),
),
new_text: "\n".into(),
},
]))
}
}
}
});
});
// After formatting the buffer, the trailing whitespace is stripped,
// a newline is appended, and the edits provided by the language server
@ -9425,9 +9437,7 @@ async fn test_completion(cx: &mut TestAppContext) {
cx.set_state("editorˇ");
cx.simulate_keystroke(".");
assert!(cx.editor(|e, _, _| e.context_menu.borrow_mut().is_none()));
cx.simulate_keystroke("c");
cx.simulate_keystroke("l");
cx.simulate_keystroke("o");
cx.simulate_keystrokes("c l o");
cx.assert_editor_state("editor.cloˇ");
assert!(cx.editor(|e, _, _| e.context_menu.borrow_mut().is_none()));
cx.update_editor(|editor, window, cx| {
@ -9745,6 +9755,20 @@ async fn test_word_completions_usually_skip_digits(cx: &mut TestAppContext) {
});
}
fn gen_text_edit(params: &CompletionParams, text: &str) -> Option<lsp::CompletionTextEdit> {
let position = || lsp::Position {
line: params.text_document_position.position.line,
character: params.text_document_position.position.character,
};
Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range: lsp::Range {
start: position(),
end: position(),
},
new_text: text.to_string(),
}))
}
#[gpui::test]
async fn test_multiline_completion(cx: &mut TestAppContext) {
init_test(cx, |_| {});
@ -9839,42 +9863,18 @@ async fn test_multiline_completion(cx: &mut TestAppContext) {
let multiline_description = "d\ne\nf\n";
let multiline_detail_2 = "g\nh\ni\n";
let mut completion_handle =
fake_server.handle_request::<lsp::request::Completion, _, _>(move |params, _| async move {
let mut completion_handle = fake_server.set_request_handler::<lsp::request::Completion, _, _>(
move |params, _| async move {
Ok(Some(lsp::CompletionResponse::Array(vec![
lsp::CompletionItem {
label: multiline_label.to_string(),
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range: lsp::Range {
start: lsp::Position {
line: params.text_document_position.position.line,
character: params.text_document_position.position.character,
},
end: lsp::Position {
line: params.text_document_position.position.line,
character: params.text_document_position.position.character,
},
},
new_text: "new_text_1".to_string(),
})),
text_edit: gen_text_edit(&params, "new_text_1"),
..lsp::CompletionItem::default()
},
lsp::CompletionItem {
label: "single line label 1".to_string(),
detail: Some(multiline_detail.to_string()),
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range: lsp::Range {
start: lsp::Position {
line: params.text_document_position.position.line,
character: params.text_document_position.position.character,
},
end: lsp::Position {
line: params.text_document_position.position.line,
character: params.text_document_position.position.character,
},
},
new_text: "new_text_2".to_string(),
})),
text_edit: gen_text_edit(&params, "new_text_2"),
..lsp::CompletionItem::default()
},
lsp::CompletionItem {
@ -9883,37 +9883,13 @@ async fn test_multiline_completion(cx: &mut TestAppContext) {
description: Some(multiline_description.to_string()),
detail: None,
}),
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range: lsp::Range {
start: lsp::Position {
line: params.text_document_position.position.line,
character: params.text_document_position.position.character,
},
end: lsp::Position {
line: params.text_document_position.position.line,
character: params.text_document_position.position.character,
},
},
new_text: "new_text_2".to_string(),
})),
text_edit: gen_text_edit(&params, "new_text_2"),
..lsp::CompletionItem::default()
},
lsp::CompletionItem {
label: multiline_label_2.to_string(),
detail: Some(multiline_detail_2.to_string()),
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range: lsp::Range {
start: lsp::Position {
line: params.text_document_position.position.line,
character: params.text_document_position.position.character,
},
end: lsp::Position {
line: params.text_document_position.position.line,
character: params.text_document_position.position.character,
},
},
new_text: "new_text_3".to_string(),
})),
text_edit: gen_text_edit(&params, "new_text_3"),
..lsp::CompletionItem::default()
},
lsp::CompletionItem {
@ -9921,23 +9897,12 @@ async fn test_multiline_completion(cx: &mut TestAppContext) {
detail: Some(
"Details with many spaces and \t but without newlines".to_string(),
),
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range: lsp::Range {
start: lsp::Position {
line: params.text_document_position.position.line,
character: params.text_document_position.position.character,
},
end: lsp::Position {
line: params.text_document_position.position.line,
character: params.text_document_position.position.character,
},
},
new_text: "new_text_4".to_string(),
})),
text_edit: gen_text_edit(&params, "new_text_4"),
..lsp::CompletionItem::default()
},
])))
});
},
);
editor.update_in(cx, |editor, window, cx| {
cx.focus_self(window);
@ -9979,7 +9944,6 @@ async fn test_multiline_completion(cx: &mut TestAppContext) {
"Adjusted completion items should still keep their filter ranges for the entire label. Item: {completion:?}"
);
}
} else {
panic!("expected completion menu to be open");
}
@ -10001,7 +9965,7 @@ async fn test_completion_page_up_down_keys(cx: &mut TestAppContext) {
)
.await;
cx.lsp
.handle_request::<lsp::request::Completion, _, _>(move |_, _| async move {
.set_request_handler::<lsp::request::Completion, _, _>(move |_, _| async move {
Ok(Some(lsp::CompletionResponse::Array(vec![
lsp::CompletionItem {
label: "first".into(),
@ -10068,7 +10032,7 @@ async fn test_completion_sort(cx: &mut TestAppContext) {
)
.await;
cx.lsp
.handle_request::<lsp::request::Completion, _, _>(move |_, _| async move {
.set_request_handler::<lsp::request::Completion, _, _>(move |_, _| async move {
Ok(Some(lsp::CompletionResponse::Array(vec![
lsp::CompletionItem {
label: "Range".into(),
@ -10140,7 +10104,7 @@ async fn test_no_duplicated_completion_requests(cx: &mut TestAppContext) {
)
.await;
cx.set_state(indoc! {"fn main() { let a = 2ˇ; }"});
cx.set_state("fn main() { let a = 2ˇ; }");
cx.simulate_keystroke(".");
let completion_item = lsp::CompletionItem {
label: "Some".into(),
@ -10186,7 +10150,7 @@ async fn test_no_duplicated_completion_requests(cx: &mut TestAppContext) {
let closure_completion_item = completion_item.clone();
let counter = Arc::new(AtomicUsize::new(0));
let counter_clone = counter.clone();
let mut request = cx.handle_request::<lsp::request::Completion, _, _>(move |_, _, _| {
let mut request = cx.set_request_handler::<lsp::request::Completion, _, _>(move |_, _, _| {
let task_completion_item = closure_completion_item.clone();
counter_clone.fetch_add(1, atomic::Ordering::Release);
async move {
@ -10198,16 +10162,14 @@ async fn test_no_duplicated_completion_requests(cx: &mut TestAppContext) {
cx.condition(|editor, _| editor.context_menu_visible())
.await;
cx.assert_editor_state(indoc! {"fn main() { let a = 2.ˇ; }"});
cx.assert_editor_state("fn main() { let a = 2.ˇ; }");
assert!(request.next().await.is_some());
assert_eq!(counter.load(atomic::Ordering::Acquire), 1);
cx.simulate_keystroke("S");
cx.simulate_keystroke("o");
cx.simulate_keystroke("m");
cx.simulate_keystrokes("S o m");
cx.condition(|editor, _| editor.context_menu_visible())
.await;
cx.assert_editor_state(indoc! {"fn main() { let a = 2.Somˇ; }"});
cx.assert_editor_state("fn main() { let a = 2.Somˇ; }");
assert!(request.next().await.is_some());
assert!(request.next().await.is_some());
assert!(request.next().await.is_some());
@ -12291,21 +12253,23 @@ async fn test_on_type_formatting_not_triggered(cx: &mut TestAppContext) {
cx.executor().start_waiting();
let fake_server = fake_servers.next().await.unwrap();
fake_server.handle_request::<lsp::request::OnTypeFormatting, _, _>(|params, _| async move {
assert_eq!(
params.text_document_position.text_document.uri,
lsp::Url::from_file_path(path!("/a/main.rs")).unwrap(),
);
assert_eq!(
params.text_document_position.position,
lsp::Position::new(0, 21),
);
fake_server.set_request_handler::<lsp::request::OnTypeFormatting, _, _>(
|params, _| async move {
assert_eq!(
params.text_document_position.text_document.uri,
lsp::Url::from_file_path(path!("/a/main.rs")).unwrap(),
);
assert_eq!(
params.text_document_position.position,
lsp::Position::new(0, 21),
);
Ok(Some(vec![lsp::TextEdit {
new_text: "]".to_string(),
range: lsp::Range::new(lsp::Position::new(0, 22), lsp::Position::new(0, 22)),
}]))
});
Ok(Some(vec![lsp::TextEdit {
new_text: "]".to_string(),
range: lsp::Range::new(lsp::Position::new(0, 22), lsp::Position::new(0, 22)),
}]))
},
);
editor_handle.update_in(cx, |editor, window, cx| {
window.focus(&editor.focus_handle(cx));
@ -12368,7 +12332,7 @@ async fn test_language_server_restart_due_to_settings_change(cx: &mut TestAppCon
})),
initializer: Some(Box::new(move |fake_server| {
let task_restarts = Arc::clone(&closure_restarts);
fake_server.handle_request::<lsp::request::Shutdown, _, _>(move |_, _| {
fake_server.set_request_handler::<lsp::request::Shutdown, _, _>(move |_, _| {
task_restarts.fetch_add(1, atomic::Ordering::Release);
futures::future::ready(Ok(()))
});
@ -12493,7 +12457,7 @@ async fn test_completions_with_additional_edits(cx: &mut TestAppContext) {
)
.await;
cx.set_state(indoc! {"fn main() { let a = 2ˇ; }"});
cx.set_state("fn main() { let a = 2ˇ; }");
cx.simulate_keystroke(".");
let completion_item = lsp::CompletionItem {
label: "some".into(),
@ -12537,7 +12501,7 @@ async fn test_completions_with_additional_edits(cx: &mut TestAppContext) {
};
let closure_completion_item = completion_item.clone();
let mut request = cx.handle_request::<lsp::request::Completion, _, _>(move |_, _, _| {
let mut request = cx.set_request_handler::<lsp::request::Completion, _, _>(move |_, _, _| {
let task_completion_item = closure_completion_item.clone();
async move {
Ok(Some(lsp::CompletionResponse::Array(vec![
@ -12555,9 +12519,9 @@ async fn test_completions_with_additional_edits(cx: &mut TestAppContext) {
.confirm_completion(&ConfirmCompletion::default(), window, cx)
.unwrap()
});
cx.assert_editor_state(indoc! {"fn main() { let a = 2.Some(2)ˇ; }"});
cx.assert_editor_state("fn main() { let a = 2.Some(2)ˇ; }");
cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
cx.set_request_handler::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
let task_completion_item = completion_item.clone();
async move { Ok(task_completion_item) }
})
@ -12565,7 +12529,7 @@ async fn test_completions_with_additional_edits(cx: &mut TestAppContext) {
.await
.unwrap();
apply_additional_edits.await.unwrap();
cx.assert_editor_state(indoc! {"fn main() { let a = Some(2)ˇ; }"});
cx.assert_editor_state("fn main() { let a = Some(2)ˇ; }");
}
#[gpui::test]
@ -12585,7 +12549,7 @@ async fn test_completions_resolve_updates_labels_if_filter_text_matches(cx: &mut
)
.await;
cx.set_state(indoc! {"fn main() { let a = 2ˇ; }"});
cx.set_state("fn main() { let a = 2ˇ; }");
cx.simulate_keystroke(".");
let item1 = lsp::CompletionItem {
@ -12613,7 +12577,7 @@ async fn test_completions_resolve_updates_labels_if_filter_text_matches(cx: &mut
};
let item1 = item1.clone();
cx.handle_request::<lsp::request::Completion, _, _>({
cx.set_request_handler::<lsp::request::Completion, _, _>({
let item1 = item1.clone();
move |_, _, _| {
let item1 = item1.clone();
@ -12646,7 +12610,7 @@ async fn test_completions_resolve_updates_labels_if_filter_text_matches(cx: &mut
}
});
cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>({
cx.set_request_handler::<lsp::request::ResolveCompletionItem, _, _>({
let item1 = item1.clone();
move |_, item_to_resolve, _| {
let item1 = item1.clone();
@ -12720,7 +12684,7 @@ async fn test_completions_resolve_happens_once(cx: &mut TestAppContext) {
)
.await;
cx.set_state(indoc! {"fn main() { let a = 2ˇ; }"});
cx.set_state("fn main() { let a = 2ˇ; }");
cx.simulate_keystroke(".");
let unresolved_item_1 = lsp::CompletionItem {
@ -12793,7 +12757,7 @@ async fn test_completions_resolve_happens_once(cx: &mut TestAppContext) {
})
.detach();
cx.handle_request::<lsp::request::Completion, _, _>(move |_, _, _| {
cx.set_request_handler::<lsp::request::Completion, _, _>(move |_, _, _| {
let unresolved_item_1 = unresolved_item_1.clone();
let unresolved_item_2 = unresolved_item_2.clone();
async move {
@ -12924,13 +12888,13 @@ async fn test_completions_default_resolve_data_handling(cx: &mut TestAppContext)
)
.await;
cx.set_state(indoc! {"fn main() { let a = 2ˇ; }"});
cx.set_state("fn main() { let a = 2ˇ; }");
cx.simulate_keystroke(".");
let completion_data = default_data.clone();
let completion_characters = default_commit_characters.clone();
let completion_items = items.clone();
cx.handle_request::<lsp::request::Completion, _, _>(move |_, _, _| {
cx.set_request_handler::<lsp::request::Completion, _, _>(move |_, _, _| {
let default_data = completion_data.clone();
let default_commit_characters = completion_characters.clone();
let items = completion_items.clone();
@ -13069,7 +13033,7 @@ async fn test_completions_in_languages_with_extra_word_characters(cx: &mut TestA
.await;
cx.lsp
.handle_request::<lsp::request::Completion, _, _>(move |_, _| async move {
.set_request_handler::<lsp::request::Completion, _, _>(move |_, _| async move {
Ok(Some(lsp::CompletionResponse::Array(vec![
lsp::CompletionItem {
label: "bg-blue".into(),
@ -16358,26 +16322,31 @@ async fn test_goto_definition_with_find_all_references_fallback(cx: &mut TestApp
.await;
let set_up_lsp_handlers = |empty_go_to_definition: bool, cx: &mut EditorLspTestContext| {
let go_to_definition = cx.lsp.handle_request::<lsp::request::GotoDefinition, _, _>(
move |params, _| async move {
if empty_go_to_definition {
Ok(None)
} else {
Ok(Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location {
uri: params.text_document_position_params.text_document.uri,
range: lsp::Range::new(lsp::Position::new(4, 3), lsp::Position::new(4, 6)),
})))
}
},
);
let references =
cx.lsp
.handle_request::<lsp::request::References, _, _>(move |params, _| async move {
Ok(Some(vec![lsp::Location {
uri: params.text_document_position.text_document.uri,
range: lsp::Range::new(lsp::Position::new(0, 8), lsp::Position::new(0, 11)),
}]))
});
let go_to_definition = cx
.lsp
.set_request_handler::<lsp::request::GotoDefinition, _, _>(
move |params, _| async move {
if empty_go_to_definition {
Ok(None)
} else {
Ok(Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location {
uri: params.text_document_position_params.text_document.uri,
range: lsp::Range::new(
lsp::Position::new(4, 3),
lsp::Position::new(4, 6),
),
})))
}
},
);
let references = cx
.lsp
.set_request_handler::<lsp::request::References, _, _>(move |params, _| async move {
Ok(Some(vec![lsp::Location {
uri: params.text_document_position.text_document.uri,
range: lsp::Range::new(lsp::Position::new(0, 8), lsp::Position::new(0, 11)),
}]))
});
(go_to_definition, references)
};
@ -17713,19 +17682,21 @@ async fn test_rename_with_duplicate_edits(cx: &mut TestAppContext) {
);
});
let mut prepare_rename_handler =
cx.handle_request::<lsp::request::PrepareRenameRequest, _, _>(move |_, _, _| async move {
Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range {
start: lsp::Position {
line: 0,
character: 7,
},
end: lsp::Position {
line: 0,
character: 10,
},
})))
});
let mut prepare_rename_handler = cx
.set_request_handler::<lsp::request::PrepareRenameRequest, _, _>(
move |_, _, _| async move {
Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range {
start: lsp::Position {
line: 0,
character: 7,
},
end: lsp::Position {
line: 0,
character: 10,
},
})))
},
);
let prepare_rename_task = cx
.update_editor(|e, window, cx| e.rename(&Rename, window, cx))
.expect("Prepare rename was not started");
@ -17733,7 +17704,7 @@ async fn test_rename_with_duplicate_edits(cx: &mut TestAppContext) {
prepare_rename_task.await.expect("Prepare rename failed");
let mut rename_handler =
cx.handle_request::<lsp::request::Rename, _, _>(move |url, _, _| async move {
cx.set_request_handler::<lsp::request::Rename, _, _>(move |url, _, _| async move {
let edit = lsp::TextEdit {
range: lsp::Range {
start: lsp::Position {
@ -17795,7 +17766,7 @@ async fn test_rename_without_prepare(cx: &mut TestAppContext) {
.expect("Prepare rename failed");
let mut rename_handler =
cx.handle_request::<lsp::request::Rename, _, _>(move |url, _, _| async move {
cx.set_request_handler::<lsp::request::Rename, _, _>(move |url, _, _| async move {
let edit = lsp::TextEdit {
range: lsp::Range {
start: lsp::Position {
@ -17946,7 +17917,7 @@ async fn test_apply_code_lens_actions_with_commands(cx: &mut gpui::TestAppContex
.unwrap();
fake_server
.handle_request::<lsp::request::CodeLensRequest, _, _>(|_, _| async move {
.set_request_handler::<lsp::request::CodeLensRequest, _, _>(|_, _| async move {
Ok(Some(vec![
lsp::CodeLens {
range: lsp::Range::default(),
@ -18002,17 +17973,19 @@ async fn test_apply_code_lens_actions_with_commands(cx: &mut gpui::TestAppContex
// Resolving the code action does not populate its edits. In absence of
// edits, we must execute the given command.
fake_server.handle_request::<lsp::request::CodeLensResolve, _, _>(|mut lens, _| async move {
let lens_command = lens.command.as_mut().expect("should have a command");
assert_eq!(lens_command.title, "Code lens command");
lens_command.arguments = Some(vec![json!("the-argument")]);
Ok(lens)
});
fake_server.set_request_handler::<lsp::request::CodeLensResolve, _, _>(
|mut lens, _| async move {
let lens_command = lens.command.as_mut().expect("should have a command");
assert_eq!(lens_command.title, "Code lens command");
lens_command.arguments = Some(vec![json!("the-argument")]);
Ok(lens)
},
);
// While executing the command, the language server sends the editor
// a `workspaceEdit` request.
fake_server
.handle_request::<lsp::request::ExecuteCommand, _, _>({
.set_request_handler::<lsp::request::ExecuteCommand, _, _>({
let fake = fake_server.clone();
move |params, _| {
assert_eq!(params.command, "_the/command");
@ -18321,7 +18294,7 @@ pub fn handle_signature_help_request(
mocked_response: lsp::SignatureHelp,
) -> impl Future<Output = ()> {
let mut request =
cx.handle_request::<lsp::request::SignatureHelpRequest, _, _>(move |_, _, _| {
cx.set_request_handler::<lsp::request::SignatureHelpRequest, _, _>(move |_, _, _| {
let mocked_response = mocked_response.clone();
async move { Ok(Some(mocked_response)) }
});
@ -18352,30 +18325,31 @@ pub fn handle_completion_request(
let replace_range =
cx.to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
let mut request = cx.handle_request::<lsp::request::Completion, _, _>(move |url, params, _| {
let completions = completions.clone();
counter.fetch_add(1, atomic::Ordering::Release);
async move {
assert_eq!(params.text_document_position.text_document.uri, url.clone());
assert_eq!(
params.text_document_position.position,
complete_from_position
);
Ok(Some(lsp::CompletionResponse::Array(
completions
.iter()
.map(|completion_text| lsp::CompletionItem {
label: completion_text.to_string(),
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range: replace_range,
new_text: completion_text.to_string(),
})),
..Default::default()
})
.collect(),
)))
}
});
let mut request =
cx.set_request_handler::<lsp::request::Completion, _, _>(move |url, params, _| {
let completions = completions.clone();
counter.fetch_add(1, atomic::Ordering::Release);
async move {
assert_eq!(params.text_document_position.text_document.uri, url.clone());
assert_eq!(
params.text_document_position.position,
complete_from_position
);
Ok(Some(lsp::CompletionResponse::Array(
completions
.iter()
.map(|completion_text| lsp::CompletionItem {
label: completion_text.to_string(),
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range: replace_range,
new_text: completion_text.to_string(),
})),
..Default::default()
})
.collect(),
)))
}
});
async move {
request.next().await;
@ -18398,7 +18372,7 @@ fn handle_resolve_completion_request(
});
let mut request =
cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
cx.set_request_handler::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
let edits = edits.clone();
async move {
Ok(lsp::CompletionItem {

View file

@ -962,7 +962,7 @@ mod tests {
cx.run_until_parked();
let mut requests =
cx.handle_request::<GotoTypeDefinition, _, _>(move |url, _, _| async move {
cx.set_request_handler::<GotoTypeDefinition, _, _>(move |url, _, _| async move {
Ok(Some(lsp::GotoTypeDefinitionResponse::Link(vec![
lsp::LocationLink {
origin_selection_range: Some(symbol_range),
@ -1037,16 +1037,17 @@ mod tests {
fn «do_work»() { test(); }
"});
let mut requests = cx.handle_request::<GotoDefinition, _, _>(move |url, _, _| async move {
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![
lsp::LocationLink {
origin_selection_range: Some(symbol_range),
target_uri: url.clone(),
target_range,
target_selection_range: target_range,
},
])))
});
let mut requests =
cx.set_request_handler::<GotoDefinition, _, _>(move |url, _, _| async move {
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![
lsp::LocationLink {
origin_selection_range: Some(symbol_range),
target_uri: url.clone(),
target_range,
target_selection_range: target_range,
},
])))
});
cx.simulate_mouse_move(hover_point, None, Modifiers::secondary_key());
requests.next().await;
@ -1063,16 +1064,17 @@ mod tests {
fn do_work() { test(); }
"});
let mut requests = cx.handle_request::<GotoDefinition, _, _>(move |url, _, _| async move {
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![
lsp::LocationLink {
origin_selection_range: Some(symbol_range),
target_uri: url.clone(),
target_range,
target_selection_range: target_range,
},
])))
});
let mut requests =
cx.set_request_handler::<GotoDefinition, _, _>(move |url, _, _| async move {
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![
lsp::LocationLink {
origin_selection_range: Some(symbol_range),
target_uri: url.clone(),
target_range,
target_selection_range: target_range,
},
])))
});
cx.simulate_mouse_move(hover_point, None, Modifiers::secondary_key());
requests.next().await;
@ -1087,12 +1089,12 @@ mod tests {
fˇn test() { do_work(); }
fn do_work() { test(); }
"});
let mut requests = cx
.lsp
.handle_request::<GotoDefinition, _, _>(move |_, _| async move {
// No definitions returned
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![])))
});
let mut requests =
cx.lsp
.set_request_handler::<GotoDefinition, _, _>(move |_, _| async move {
// No definitions returned
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![])))
});
cx.simulate_mouse_move(hover_point, None, Modifiers::secondary_key());
requests.next().await;
@ -1126,16 +1128,17 @@ mod tests {
fn do_work() { test(); }
"});
let mut requests = cx.handle_request::<GotoDefinition, _, _>(move |url, _, _| async move {
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![
lsp::LocationLink {
origin_selection_range: Some(symbol_range),
target_uri: url,
target_range,
target_selection_range: target_range,
},
])))
});
let mut requests =
cx.set_request_handler::<GotoDefinition, _, _>(move |url, _, _| async move {
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![
lsp::LocationLink {
origin_selection_range: Some(symbol_range),
target_uri: url,
target_range,
target_selection_range: target_range,
},
])))
});
cx.simulate_modifiers_change(Modifiers::secondary_key());
@ -1175,7 +1178,7 @@ mod tests {
// Cmd click with existing definition doesn't re-request and dismisses highlight
cx.simulate_click(hover_point, Modifiers::secondary_key());
cx.lsp
.handle_request::<GotoDefinition, _, _>(move |_, _| async move {
.set_request_handler::<GotoDefinition, _, _>(move |_, _| async move {
// Empty definition response to make sure we aren't hitting the lsp and using
// the cached location instead
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![])))
@ -1202,16 +1205,17 @@ mod tests {
fn «do_work»() { test(); }
"});
let mut requests = cx.handle_request::<GotoDefinition, _, _>(move |url, _, _| async move {
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![
lsp::LocationLink {
origin_selection_range: None,
target_uri: url,
target_range,
target_selection_range: target_range,
},
])))
});
let mut requests =
cx.set_request_handler::<GotoDefinition, _, _>(move |url, _, _| async move {
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![
lsp::LocationLink {
origin_selection_range: None,
target_uri: url,
target_range,
target_selection_range: target_range,
},
])))
});
cx.simulate_click(hover_point, Modifiers::secondary_key());
requests.next().await;
cx.background_executor.run_until_parked();
@ -1230,16 +1234,17 @@ mod tests {
fn test() { do_work(); }
fn «do_work»() { test(); }
"});
let mut requests = cx.handle_request::<GotoDefinition, _, _>(move |url, _, _| async move {
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![
lsp::LocationLink {
origin_selection_range: None,
target_uri: url,
target_range,
target_selection_range: target_range,
},
])))
});
let mut requests =
cx.set_request_handler::<GotoDefinition, _, _>(move |url, _, _| async move {
Ok(Some(lsp::GotoDefinitionResponse::Link(vec![
lsp::LocationLink {
origin_selection_range: None,
target_uri: url,
target_range,
target_selection_range: target_range,
},
])))
});
// create a pending selection
let selection_range = cx.ranges(indoc! {"
@ -1315,7 +1320,7 @@ mod tests {
let expected_uri = cx.buffer_lsp_url.clone();
let hint_label = ": TestStruct";
cx.lsp
.handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
.set_request_handler::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
let expected_uri = expected_uri.clone();
async move {
assert_eq!(params.text_document.uri, expected_uri);

View file

@ -1029,7 +1029,7 @@ mod tests {
fn test() { «println!»(); }
"});
let mut requests =
cx.handle_request::<lsp::request::HoverRequest, _, _>(move |_, _, _| async move {
cx.set_request_handler::<lsp::request::HoverRequest, _, _>(move |_, _, _| async move {
Ok(Some(lsp::Hover {
contents: lsp::HoverContents::Markup(lsp::MarkupContent {
kind: lsp::MarkupKind::Markdown,
@ -1109,7 +1109,9 @@ mod tests {
"});
let mut request = cx
.lsp
.handle_request::<lsp::request::HoverRequest, _, _>(|_, _| async move { Ok(None) });
.set_request_handler::<lsp::request::HoverRequest, _, _>(
|_, _| async move { Ok(None) },
);
cx.update_editor(|editor, window, cx| {
let snapshot = editor.snapshot(window, cx);
let anchor = snapshot
@ -1162,7 +1164,7 @@ mod tests {
fn test() { «println!»(); }
"});
let mut requests =
cx.handle_request::<lsp::request::HoverRequest, _, _>(move |_, _, _| async move {
cx.set_request_handler::<lsp::request::HoverRequest, _, _>(move |_, _, _| async move {
Ok(Some(lsp::Hover {
contents: lsp::HoverContents::Markup(lsp::MarkupContent {
kind: lsp::MarkupKind::Markdown,
@ -1199,7 +1201,9 @@ mod tests {
"});
let mut request = cx
.lsp
.handle_request::<lsp::request::HoverRequest, _, _>(|_, _| async move { Ok(None) });
.set_request_handler::<lsp::request::HoverRequest, _, _>(
|_, _| async move { Ok(None) },
);
cx.update_editor(|editor, window, cx| {
let snapshot = editor.snapshot(window, cx);
let anchor = snapshot
@ -1249,7 +1253,7 @@ mod tests {
});
let mut requests =
cx.handle_request::<lsp::request::HoverRequest, _, _>(move |_, _, _| async move {
cx.set_request_handler::<lsp::request::HoverRequest, _, _>(move |_, _, _| async move {
Ok(Some(lsp::Hover {
contents: lsp::HoverContents::Markup(lsp::MarkupContent {
kind: lsp::MarkupKind::Markdown,
@ -1303,7 +1307,7 @@ mod tests {
let symbol_range = cx.lsp_range(indoc! {"
«fn» test() { println!(); }
"});
cx.handle_request::<lsp::request::HoverRequest, _, _>(move |_, _, _| async move {
cx.set_request_handler::<lsp::request::HoverRequest, _, _>(move |_, _, _| async move {
Ok(Some(lsp::Hover {
contents: lsp::HoverContents::Array(vec![
lsp::MarkedString::String("regular text for hover to show".to_string()),
@ -1369,7 +1373,7 @@ mod tests {
let markdown_string = format!("\n```rust\n{code_str}```");
let closure_markdown_string = markdown_string.clone();
cx.handle_request::<lsp::request::HoverRequest, _, _>(move |_, _, _| {
cx.set_request_handler::<lsp::request::HoverRequest, _, _>(move |_, _, _| {
let future_markdown_string = closure_markdown_string.clone();
async move {
Ok(Some(lsp::Hover {
@ -1460,7 +1464,7 @@ mod tests {
let range = cx.lsp_range(indoc! {"
fn «test»() { println!(); }
"});
cx.handle_request::<lsp::request::HoverRequest, _, _>(move |_, _, _| async move {
cx.set_request_handler::<lsp::request::HoverRequest, _, _>(move |_, _, _| async move {
Ok(Some(lsp::Hover {
contents: lsp::HoverContents::Markup(lsp::MarkupContent {
kind: lsp::MarkupKind::Markdown,
@ -1497,13 +1501,14 @@ mod tests {
}
"});
cx.lsp.handle_request::<lsp::request::HoverRequest, _, _>({
|_, _| async move {
Ok(Some(lsp::Hover {
contents: lsp::HoverContents::Markup(lsp::MarkupContent {
kind: lsp::MarkupKind::Markdown,
value: indoc!(
r#"
cx.lsp
.set_request_handler::<lsp::request::HoverRequest, _, _>({
|_, _| async move {
Ok(Some(lsp::Hover {
contents: lsp::HoverContents::Markup(lsp::MarkupContent {
kind: lsp::MarkupKind::Markdown,
value: indoc!(
r#"
### function `errands_data_read`
---
@ -1515,13 +1520,13 @@ mod tests {
static char *errands_data_read()
```
"#
)
.to_string(),
}),
range: None,
}))
}
});
)
.to_string(),
}),
range: None,
}))
}
});
cx.update_editor(|editor, window, cx| hover(editor, &Default::default(), window, cx));
cx.run_until_parked();
@ -1616,7 +1621,7 @@ mod tests {
let entire_hint_label = ": TestNewType<TestStruct>";
let closure_uri = uri.clone();
cx.lsp
.handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
.set_request_handler::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
let task_uri = closure_uri.clone();
async move {
assert_eq!(params.text_document.uri, task_uri);
@ -1692,7 +1697,7 @@ mod tests {
let resolve_closure_uri = uri.clone();
cx.lsp
.handle_request::<lsp::request::InlayHintResolveRequest, _, _>(
.set_request_handler::<lsp::request::InlayHintResolveRequest, _, _>(
move |mut hint_to_resolve, _| {
let mut resolved_hint_positions = BTreeSet::new();
let task_uri = resolve_closure_uri.clone();

View file

@ -1326,26 +1326,28 @@ pub mod tests {
});
let (_, editor, fake_server) = prepare_test_objects(cx, |fake_server, file_with_hints| {
let lsp_request_count = Arc::new(AtomicU32::new(0));
fake_server.handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
let task_lsp_request_count = Arc::clone(&lsp_request_count);
async move {
let i = task_lsp_request_count.fetch_add(1, Ordering::Release) + 1;
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(file_with_hints).unwrap(),
);
Ok(Some(vec![lsp::InlayHint {
position: lsp::Position::new(0, i),
label: lsp::InlayHintLabel::String(i.to_string()),
kind: None,
text_edits: None,
tooltip: None,
padding_left: None,
padding_right: None,
data: None,
}]))
}
});
fake_server.set_request_handler::<lsp::request::InlayHintRequest, _, _>(
move |params, _| {
let task_lsp_request_count = Arc::clone(&lsp_request_count);
async move {
let i = task_lsp_request_count.fetch_add(1, Ordering::Release) + 1;
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(file_with_hints).unwrap(),
);
Ok(Some(vec![lsp::InlayHint {
position: lsp::Position::new(0, i),
label: lsp::InlayHintLabel::String(i.to_string()),
kind: None,
text_edits: None,
tooltip: None,
padding_left: None,
padding_right: None,
data: None,
}]))
}
},
);
})
.await;
cx.executor().run_until_parked();
@ -1431,27 +1433,29 @@ pub mod tests {
let (_, editor, fake_server) = prepare_test_objects(cx, |fake_server, file_with_hints| {
let lsp_request_count = Arc::new(AtomicU32::new(0));
fake_server.handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
let task_lsp_request_count = Arc::clone(&lsp_request_count);
async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(file_with_hints).unwrap(),
);
let current_call_id =
Arc::clone(&task_lsp_request_count).fetch_add(1, Ordering::SeqCst);
Ok(Some(vec![lsp::InlayHint {
position: lsp::Position::new(0, current_call_id),
label: lsp::InlayHintLabel::String(current_call_id.to_string()),
kind: None,
text_edits: None,
tooltip: None,
padding_left: None,
padding_right: None,
data: None,
}]))
}
});
fake_server.set_request_handler::<lsp::request::InlayHintRequest, _, _>(
move |params, _| {
let task_lsp_request_count = Arc::clone(&lsp_request_count);
async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(file_with_hints).unwrap(),
);
let current_call_id =
Arc::clone(&task_lsp_request_count).fetch_add(1, Ordering::SeqCst);
Ok(Some(vec![lsp::InlayHint {
position: lsp::Position::new(0, current_call_id),
label: lsp::InlayHintLabel::String(current_call_id.to_string()),
kind: None,
text_edits: None,
tooltip: None,
padding_left: None,
padding_right: None,
data: None,
}]))
}
},
);
})
.await;
cx.executor().run_until_parked();
@ -1571,43 +1575,48 @@ pub mod tests {
move |fake_server| {
let rs_lsp_request_count = Arc::new(AtomicU32::new(0));
let md_lsp_request_count = Arc::new(AtomicU32::new(0));
fake_server.handle_request::<lsp::request::InlayHintRequest, _, _>(
move |params, _| {
let i = match name {
"Rust" => {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/a/main.rs"))
.unwrap(),
);
rs_lsp_request_count.fetch_add(1, Ordering::Release) + 1
}
"Markdown" => {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/a/other.md"))
.unwrap(),
);
md_lsp_request_count.fetch_add(1, Ordering::Release) + 1
}
unexpected => panic!("Unexpected language: {unexpected}"),
};
fake_server
.set_request_handler::<lsp::request::InlayHintRequest, _, _>(
move |params, _| {
let i = match name {
"Rust" => {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/a/main.rs"))
.unwrap(),
);
rs_lsp_request_count.fetch_add(1, Ordering::Release)
+ 1
}
"Markdown" => {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(path!("/a/other.md"))
.unwrap(),
);
md_lsp_request_count.fetch_add(1, Ordering::Release)
+ 1
}
unexpected => {
panic!("Unexpected language: {unexpected}")
}
};
async move {
let query_start = params.range.start;
Ok(Some(vec![lsp::InlayHint {
position: query_start,
label: lsp::InlayHintLabel::String(i.to_string()),
kind: None,
text_edits: None,
tooltip: None,
padding_left: None,
padding_right: None,
data: None,
}]))
}
},
);
async move {
let query_start = params.range.start;
Ok(Some(vec![lsp::InlayHint {
position: query_start,
label: lsp::InlayHintLabel::String(i.to_string()),
kind: None,
text_edits: None,
tooltip: None,
padding_left: None,
padding_right: None,
data: None,
}]))
}
},
);
}
})),
..Default::default()
@ -1757,7 +1766,7 @@ pub mod tests {
let lsp_request_count = lsp_request_count.clone();
move |fake_server, file_with_hints| {
let lsp_request_count = lsp_request_count.clone();
fake_server.handle_request::<lsp::request::InlayHintRequest, _, _>(
fake_server.set_request_handler::<lsp::request::InlayHintRequest, _, _>(
move |params, _| {
lsp_request_count.fetch_add(1, Ordering::Release);
async move {
@ -2087,7 +2096,7 @@ pub mod tests {
let lsp_request_count = lsp_request_count.clone();
move |fake_server, file_with_hints| {
let lsp_request_count = lsp_request_count.clone();
fake_server.handle_request::<lsp::request::InlayHintRequest, _, _>(
fake_server.set_request_handler::<lsp::request::InlayHintRequest, _, _>(
move |params, _| {
let lsp_request_count = lsp_request_count.clone();
async move {
@ -2244,7 +2253,7 @@ pub mod tests {
move |fake_server| {
let closure_lsp_request_ranges = Arc::clone(&lsp_request_ranges);
let closure_lsp_request_count = Arc::clone(&lsp_request_count);
fake_server.handle_request::<lsp::request::InlayHintRequest, _, _>(
fake_server.set_request_handler::<lsp::request::InlayHintRequest, _, _>(
move |params, _| {
let task_lsp_request_ranges =
Arc::clone(&closure_lsp_request_ranges);
@ -2625,7 +2634,7 @@ pub mod tests {
let fake_server = fake_servers.next().await.unwrap();
let closure_editor_edited = Arc::clone(&editor_edited);
fake_server
.handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
.set_request_handler::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
let task_editor_edited = Arc::clone(&closure_editor_edited);
async move {
let hint_text = if params.text_document.uri
@ -2926,7 +2935,7 @@ pub mod tests {
let fake_server = fake_servers.next().await.unwrap();
let closure_editor_edited = Arc::clone(&editor_edited);
fake_server
.handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
.set_request_handler::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
let task_editor_edited = Arc::clone(&closure_editor_edited);
async move {
let hint_text = if params.text_document.uri
@ -3094,7 +3103,7 @@ pub mod tests {
},
initializer: Some(Box::new(move |fake_server| {
let lsp_request_count = Arc::new(AtomicU32::new(0));
fake_server.handle_request::<lsp::request::InlayHintRequest, _, _>(
fake_server.set_request_handler::<lsp::request::InlayHintRequest, _, _>(
move |params, _| {
let i = lsp_request_count.fetch_add(1, Ordering::Release) + 1;
async move {
@ -3165,27 +3174,29 @@ pub mod tests {
let (_, editor, _fake_server) = prepare_test_objects(cx, |fake_server, file_with_hints| {
let lsp_request_count = Arc::new(AtomicU32::new(0));
fake_server.handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
let lsp_request_count = lsp_request_count.clone();
async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(file_with_hints).unwrap(),
);
fake_server.set_request_handler::<lsp::request::InlayHintRequest, _, _>(
move |params, _| {
let lsp_request_count = lsp_request_count.clone();
async move {
assert_eq!(
params.text_document.uri,
lsp::Url::from_file_path(file_with_hints).unwrap(),
);
let i = lsp_request_count.fetch_add(1, Ordering::SeqCst) + 1;
Ok(Some(vec![lsp::InlayHint {
position: lsp::Position::new(0, i),
label: lsp::InlayHintLabel::String(i.to_string()),
kind: None,
text_edits: None,
tooltip: None,
padding_left: None,
padding_right: None,
data: None,
}]))
}
});
let i = lsp_request_count.fetch_add(1, Ordering::SeqCst) + 1;
Ok(Some(vec![lsp::InlayHint {
position: lsp::Position::new(0, i),
label: lsp::InlayHintLabel::String(i.to_string()),
kind: None,
text_edits: None,
tooltip: None,
padding_left: None,
padding_right: None,
data: None,
}]))
}
},
);
})
.await;
@ -3326,7 +3337,7 @@ pub mod tests {
..Default::default()
},
initializer: Some(Box::new(move |fake_server| {
fake_server.handle_request::<lsp::request::InlayHintRequest, _, _>(
fake_server.set_request_handler::<lsp::request::InlayHintRequest, _, _>(
move |params, _| async move {
assert_eq!(
params.text_document.uri,

View file

@ -337,7 +337,7 @@ impl EditorLspTestContext {
self.workspace.update_in(&mut self.cx.cx, update)
}
pub fn handle_request<T, F, Fut>(
pub fn set_request_handler<T, F, Fut>(
&self,
mut handler: F,
) -> futures::channel::mpsc::UnboundedReceiver<()>
@ -348,7 +348,7 @@ impl EditorLspTestContext {
Fut: 'static + Send + Future<Output = Result<T::Result>>,
{
let url = self.buffer_lsp_url.clone();
self.lsp.handle_request::<T, _, _>(move |params, cx| {
self.lsp.set_request_handler::<T, _, _>(move |params, cx| {
let url = url.clone();
handler(url, params, cx)
})