diff --git a/crates/collab/src/tests/editor_tests.rs b/crates/collab/src/tests/editor_tests.rs index 143c830855..d2bc38be55 100644 --- a/crates/collab/src/tests/editor_tests.rs +++ b/crates/collab/src/tests/editor_tests.rs @@ -348,7 +348,7 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu // Return some completions from the host's language server. cx_a.executor().start_waiting(); fake_language_server - .handle_request::(|params, _| async move { + .set_request_handler::(|params, _| async move { assert_eq!( params.text_document_position.text_document.uri, lsp::Url::from_file_path("/a/main.rs").unwrap(), @@ -412,7 +412,7 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu // Return a resolved completion from the host's language server. // The resolved completion has an additional text edit. - fake_language_server.handle_request::( + fake_language_server.set_request_handler::( |params, _| async move { assert_eq!(params.label, "first_method(…)"); Ok(lsp::CompletionItem { @@ -465,7 +465,7 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu }); let mut completion_response = fake_language_server - .handle_request::(|params, _| async move { + .set_request_handler::(|params, _| async move { assert_eq!( params.text_document_position.text_document.uri, lsp::Url::from_file_path("/a/main.rs").unwrap(), @@ -496,7 +496,7 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu // The completion now gets a new `text_edit.new_text` when resolving the completion item let mut resolve_completion_response = fake_language_server - .handle_request::(|params, _| async move { + .set_request_handler::(|params, _| async move { assert_eq!(params.label, "third_method(…)"); Ok(lsp::CompletionItem { label: "third_method(…)".into(), @@ -589,7 +589,7 @@ async fn test_collaborating_with_code_actions( let mut fake_language_server = fake_language_servers.next().await.unwrap(); let mut requests = fake_language_server - .handle_request::(|params, _| async move { + .set_request_handler::(|params, _| async move { assert_eq!( params.text_document.uri, lsp::Url::from_file_path("/a/main.rs").unwrap(), @@ -611,7 +611,7 @@ async fn test_collaborating_with_code_actions( cx_b.focus(&editor_b); let mut requests = fake_language_server - .handle_request::(|params, _| async move { + .set_request_handler::(|params, _| async move { assert_eq!( params.text_document.uri, lsp::Url::from_file_path("/a/main.rs").unwrap(), @@ -689,7 +689,7 @@ async fn test_collaborating_with_code_actions( Editor::confirm_code_action(editor, &ConfirmCodeAction { item_ix: Some(0) }, window, cx) }) .unwrap(); - fake_language_server.handle_request::( + fake_language_server.set_request_handler::( |_, _| async move { Ok(lsp::CodeAction { title: "Inline into all callers".to_string(), @@ -812,7 +812,7 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T }); fake_language_server - .handle_request::(|params, _| async move { + .set_request_handler::(|params, _| async move { assert_eq!(params.text_document.uri.as_str(), "file:///dir/one.rs"); assert_eq!(params.position, lsp::Position::new(0, 7)); Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range::new( @@ -855,7 +855,7 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T }); fake_language_server - .handle_request::(|params, _| async move { + .set_request_handler::(|params, _| async move { assert_eq!(params.text_document.uri.as_str(), "file:///dir/one.rs"); assert_eq!(params.position, lsp::Position::new(0, 8)); Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range::new( @@ -891,7 +891,7 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T Editor::confirm_rename(editor, &ConfirmRename, window, cx).unwrap() }); fake_language_server - .handle_request::(|params, _| async move { + .set_request_handler::(|params, _| async move { assert_eq!( params.text_document_position.text_document.uri.as_str(), "file:///dir/one.rs" @@ -1321,7 +1321,7 @@ async fn test_on_input_format_from_host_to_guest( // Receive an OnTypeFormatting request as the host's language server. // Return some formatting from the host's language server. - fake_language_server.handle_request::( + fake_language_server.set_request_handler::( |params, _| async move { assert_eq!( params.text_document_position.text_document.uri, @@ -1452,7 +1452,7 @@ async fn test_on_input_format_from_guest_to_host( // Return some formatting from the host's language server. executor.start_waiting(); fake_language_server - .handle_request::(|params, _| async move { + .set_request_handler::(|params, _| async move { assert_eq!( params.text_document_position.text_document.uri, lsp::Url::from_file_path("/a/main.rs").unwrap(), @@ -1624,7 +1624,7 @@ async fn test_mutual_editor_inlay_hint_cache_update( let edits_made = Arc::new(AtomicUsize::new(0)); let closure_edits_made = Arc::clone(&edits_made); fake_language_server - .handle_request::(move |params, _| { + .set_request_handler::(move |params, _| { let task_edits_made = Arc::clone(&closure_edits_made); async move { assert_eq!( @@ -1859,7 +1859,7 @@ async fn test_inlay_hint_refresh_is_forwarded( let fake_language_server = fake_language_servers.next().await.unwrap(); let closure_other_hints = Arc::clone(&other_hints); fake_language_server - .handle_request::(move |params, _| { + .set_request_handler::(move |params, _| { let task_other_hints = Arc::clone(&closure_other_hints); async move { assert_eq!( diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index fdfd51325f..1a91d80afa 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -4480,7 +4480,7 @@ async fn test_formatting_buffer( project.register_buffer_with_language_servers(&buffer_b, cx) }); let fake_language_server = fake_language_servers.next().await.unwrap(); - fake_language_server.handle_request::(|_, _| async move { + fake_language_server.set_request_handler::(|_, _| async move { Ok(Some(vec![ lsp::TextEdit { range: lsp::Range::new(lsp::Position::new(0, 4), lsp::Position::new(0, 4)), @@ -4633,7 +4633,7 @@ async fn test_prettier_formatting_buffer( }); }); let fake_language_server = fake_language_servers.next().await.unwrap(); - fake_language_server.handle_request::(|_, _| async move { + fake_language_server.set_request_handler::(|_, _| async move { panic!( "Unexpected: prettier should be preferred since it's enabled and language supports it" ) @@ -4731,14 +4731,16 @@ async fn test_definition( // Request the definition of a symbol as the guest. let fake_language_server = fake_language_servers.next().await.unwrap(); - fake_language_server.handle_request::(|_, _| async move { - Ok(Some(lsp::GotoDefinitionResponse::Scalar( - lsp::Location::new( - lsp::Url::from_file_path("/root/dir-2/b.rs").unwrap(), - lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)), - ), - ))) - }); + fake_language_server.set_request_handler::( + |_, _| async move { + Ok(Some(lsp::GotoDefinitionResponse::Scalar( + lsp::Location::new( + lsp::Url::from_file_path("/root/dir-2/b.rs").unwrap(), + lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)), + ), + ))) + }, + ); let definitions_1 = project_b .update(cx_b, |p, cx| p.definition(&buffer_b, 23, cx)) @@ -4760,14 +4762,16 @@ async fn test_definition( // Try getting more definitions for the same buffer, ensuring the buffer gets reused from // the previous call to `definition`. - fake_language_server.handle_request::(|_, _| async move { - Ok(Some(lsp::GotoDefinitionResponse::Scalar( - lsp::Location::new( - lsp::Url::from_file_path("/root/dir-2/b.rs").unwrap(), - lsp::Range::new(lsp::Position::new(1, 6), lsp::Position::new(1, 11)), - ), - ))) - }); + fake_language_server.set_request_handler::( + |_, _| async move { + Ok(Some(lsp::GotoDefinitionResponse::Scalar( + lsp::Location::new( + lsp::Url::from_file_path("/root/dir-2/b.rs").unwrap(), + lsp::Range::new(lsp::Position::new(1, 6), lsp::Position::new(1, 11)), + ), + ))) + }, + ); let definitions_2 = project_b .update(cx_b, |p, cx| p.definition(&buffer_b, 33, cx)) @@ -4791,7 +4795,7 @@ async fn test_definition( definitions_2[0].target.buffer ); - fake_language_server.handle_request::( + fake_language_server.set_request_handler::( |req, _| async move { assert_eq!( req.text_document_position_params.position, @@ -4881,7 +4885,7 @@ async fn test_references( // Request references to a symbol as the guest. let fake_language_server = fake_language_servers.next().await.unwrap(); let (lsp_response_tx, rx) = mpsc::unbounded::>>>(); - fake_language_server.handle_request::({ + fake_language_server.set_request_handler::({ let rx = Arc::new(Mutex::new(Some(rx))); move |params, _| { assert_eq!( @@ -5131,7 +5135,7 @@ async fn test_document_highlights( // Request document highlights as the guest. let fake_language_server = fake_language_servers.next().await.unwrap(); - fake_language_server.handle_request::( + fake_language_server.set_request_handler::( |params, _| async move { assert_eq!( params @@ -5268,7 +5272,7 @@ async fn test_lsp_hover( "CrabLang-ls" => { servers_with_hover_requests.insert( new_server_name.clone(), - new_server.handle_request::( + new_server.set_request_handler::( move |params, _| { assert_eq!( params @@ -5294,7 +5298,7 @@ async fn test_lsp_hover( "rust-analyzer" => { servers_with_hover_requests.insert( new_server_name.clone(), - new_server.handle_request::( + new_server.set_request_handler::( |params, _| async move { assert_eq!( params @@ -5432,22 +5436,24 @@ async fn test_project_symbols( .unwrap(); let fake_language_server = fake_language_servers.next().await.unwrap(); - fake_language_server.handle_request::(|_, _| async move { - Ok(Some(lsp::WorkspaceSymbolResponse::Flat(vec![ - #[allow(deprecated)] - lsp::SymbolInformation { - name: "TWO".into(), - location: lsp::Location { - uri: lsp::Url::from_file_path("/code/crate-2/two.rs").unwrap(), - range: lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)), + fake_language_server.set_request_handler::( + |_, _| async move { + Ok(Some(lsp::WorkspaceSymbolResponse::Flat(vec![ + #[allow(deprecated)] + lsp::SymbolInformation { + name: "TWO".into(), + location: lsp::Location { + uri: lsp::Url::from_file_path("/code/crate-2/two.rs").unwrap(), + range: lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)), + }, + kind: lsp::SymbolKind::CONSTANT, + tags: None, + container_name: None, + deprecated: None, }, - kind: lsp::SymbolKind::CONSTANT, - tags: None, - container_name: None, - deprecated: None, - }, - ]))) - }); + ]))) + }, + ); // Request the definition of a symbol as the guest. let symbols = project_b @@ -5529,14 +5535,16 @@ async fn test_open_buffer_while_getting_definition_pointing_to_it( .unwrap(); let fake_language_server = fake_language_servers.next().await.unwrap(); - fake_language_server.handle_request::(|_, _| async move { - Ok(Some(lsp::GotoDefinitionResponse::Scalar( - lsp::Location::new( - lsp::Url::from_file_path("/root/b.rs").unwrap(), - lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)), - ), - ))) - }); + fake_language_server.set_request_handler::( + |_, _| async move { + Ok(Some(lsp::GotoDefinitionResponse::Scalar( + lsp::Location::new( + lsp::Url::from_file_path("/root/b.rs").unwrap(), + lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)), + ), + ))) + }, + ); let definitions; let buffer_b2; diff --git a/crates/collab/src/tests/random_project_collaboration_tests.rs b/crates/collab/src/tests/random_project_collaboration_tests.rs index 37d5cfd1fc..060aec3aeb 100644 --- a/crates/collab/src/tests/random_project_collaboration_tests.rs +++ b/crates/collab/src/tests/random_project_collaboration_tests.rs @@ -1043,7 +1043,7 @@ impl RandomizedTest for ProjectCollaborationTest { initializer: Some(Box::new({ let fs = client.app_state.fs.clone(); move |fake_server: &mut FakeLanguageServer| { - fake_server.handle_request::( + fake_server.set_request_handler::( |_, _| async move { Ok(Some(lsp::CompletionResponse::Array(vec![ lsp::CompletionItem { @@ -1062,7 +1062,7 @@ impl RandomizedTest for ProjectCollaborationTest { }, ); - fake_server.handle_request::( + fake_server.set_request_handler::( |_, _| async move { Ok(Some(vec![lsp::CodeActionOrCommand::CodeAction( lsp::CodeAction { @@ -1073,16 +1073,17 @@ impl RandomizedTest for ProjectCollaborationTest { }, ); - fake_server.handle_request::( - |params, _| async move { - Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range::new( - params.position, - params.position, - )))) - }, - ); + fake_server + .set_request_handler::( + |params, _| async move { + Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range::new( + params.position, + params.position, + )))) + }, + ); - fake_server.handle_request::({ + fake_server.set_request_handler::({ let fs = fs.clone(); move |_, cx| { let background = cx.background_executor(); @@ -1107,32 +1108,34 @@ impl RandomizedTest for ProjectCollaborationTest { } }); - fake_server.handle_request::( - move |_, cx| { - let mut highlights = Vec::new(); - let background = cx.background_executor(); - let mut rng = background.rng(); + fake_server + .set_request_handler::( + move |_, cx| { + let mut highlights = Vec::new(); + let background = cx.background_executor(); + let mut rng = background.rng(); - let highlight_count = rng.gen_range(1..=5); - for _ in 0..highlight_count { - let start_row = rng.gen_range(0..100); - let start_column = rng.gen_range(0..100); - let end_row = rng.gen_range(0..100); - let end_column = rng.gen_range(0..100); - let start = PointUtf16::new(start_row, start_column); - let end = PointUtf16::new(end_row, end_column); - let range = if start > end { end..start } else { start..end }; - highlights.push(lsp::DocumentHighlight { - range: range_to_lsp(range.clone()).unwrap(), - kind: Some(lsp::DocumentHighlightKind::READ), + let highlight_count = rng.gen_range(1..=5); + for _ in 0..highlight_count { + let start_row = rng.gen_range(0..100); + let start_column = rng.gen_range(0..100); + let end_row = rng.gen_range(0..100); + let end_column = rng.gen_range(0..100); + let start = PointUtf16::new(start_row, start_column); + let end = PointUtf16::new(end_row, end_column); + let range = + if start > end { end..start } else { start..end }; + highlights.push(lsp::DocumentHighlight { + range: range_to_lsp(range.clone()).unwrap(), + kind: Some(lsp::DocumentHighlightKind::READ), + }); + } + highlights.sort_unstable_by_key(|highlight| { + (highlight.range.start, highlight.range.end) }); - } - highlights.sort_unstable_by_key(|highlight| { - (highlight.range.start, highlight.range.end) - }); - async move { Ok(Some(highlights)) } - }, - ); + async move { Ok(Some(highlights)) } + }, + ); } })), ..Default::default() diff --git a/crates/collab/src/tests/remote_editing_collaboration_tests.rs b/crates/collab/src/tests/remote_editing_collaboration_tests.rs index bd594b0fa1..bd9c3e2e14 100644 --- a/crates/collab/src/tests/remote_editing_collaboration_tests.rs +++ b/crates/collab/src/tests/remote_editing_collaboration_tests.rs @@ -482,7 +482,7 @@ async fn test_ssh_collaboration_formatting_with_prettier( }); }); let fake_language_server = fake_language_servers.next().await.unwrap(); - fake_language_server.handle_request::(|_, _| async move { + fake_language_server.set_request_handler::(|_, _| async move { panic!( "Unexpected: prettier should be preferred since it's enabled and language supports it" ) diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index d1b686ed1e..5c963399e3 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -1220,7 +1220,7 @@ mod tests { ); // Ensure all previously-registered buffers are closed when signing out. - lsp.handle_request::(|_, _| async { + lsp.set_request_handler::(|_, _| async { Ok(request::SignOutResult {}) }); copilot @@ -1243,7 +1243,7 @@ mod tests { ); // Ensure all previously-registered buffers are re-opened when signing in. - lsp.handle_request::(|_, _| async { + lsp.set_request_handler::(|_, _| async { Ok(request::SignInInitiateResult::AlreadySignedIn { user: "user-1".into(), }) diff --git a/crates/copilot/src/copilot_completion_provider.rs b/crates/copilot/src/copilot_completion_provider.rs index 8c5b1b3bf1..aad74f4744 100644 --- a/crates/copilot/src/copilot_completion_provider.rs +++ b/crates/copilot/src/copilot_completion_provider.rs @@ -1013,7 +1013,7 @@ mod tests { .unwrap(); let mut copilot_requests = copilot_lsp - .handle_request::( + .set_request_handler::( move |_params, _cx| async move { Ok(crate::request::GetCompletionsResult { completions: vec![crate::request::Completion { @@ -1054,7 +1054,7 @@ mod tests { completions: Vec, completions_cycling: Vec, ) { - lsp.handle_request::(move |_params, _cx| { + lsp.set_request_handler::(move |_params, _cx| { let completions = completions.clone(); async move { Ok(crate::request::GetCompletionsResult { @@ -1062,14 +1062,16 @@ mod tests { }) } }); - lsp.handle_request::(move |_params, _cx| { - let completions_cycling = completions_cycling.clone(); - async move { - Ok(crate::request::GetCompletionsResult { - completions: completions_cycling.clone(), - }) - } - }); + lsp.set_request_handler::( + move |_params, _cx| { + let completions_cycling = completions_cycling.clone(); + async move { + Ok(crate::request::GetCompletionsResult { + completions: completions_cycling.clone(), + }) + } + }, + ); } fn handle_completion_request( @@ -1090,7 +1092,7 @@ mod tests { cx.to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone()); let mut request = - cx.handle_request::(move |url, params, _| { + cx.set_request_handler::(move |url, params, _| { let completions = completions.clone(); async move { assert_eq!(params.text_document_position.text_document.uri, url.clone()); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index eb2575ed85..0c8a2a22df 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -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::>(); + .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, - ) -> Option>> { - use language::ToOffset as _; - + ) -> Option>> { 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::(cx); let selections = self.selections.all::(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::(); - 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::>(); + .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 = 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; diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 6691ae0709..58ae55044d 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -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::(move |params, _| async move { + .set_request_handler::(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::(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::( + 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::(move |_, _| async move { + .set_request_handler::(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::(move |params, _| async move { + .set_request_handler::(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::(move |params, _| async move { + .set_request_handler::(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::( + fake_server.set_request_handler::( 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::(move |_, _| async move { + .set_request_handler::(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::(move |params, _| async move { + .set_request_handler::(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::(move |params, _| async move { + .set_request_handler::(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::(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::( + 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::(move |params, _| async move { + .set_request_handler::(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::( + fake_server.set_request_handler::( 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::(move |_, cx| { + .set_request_handler::(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::({ - 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::({ + 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 { + 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::(move |params, _| async move { + let mut completion_handle = fake_server.set_request_handler::( + 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(¶ms, "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(¶ms, "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(¶ms, "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(¶ms, "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(¶ms, "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::(move |_, _| async move { + .set_request_handler::(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::(move |_, _| async move { + .set_request_handler::(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::(move |_, _, _| { + let mut request = cx.set_request_handler::(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::(|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::( + |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::(move |_, _| { + fake_server.set_request_handler::(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::(move |_, _, _| { + let mut request = cx.set_request_handler::(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::(move |_, _, _| { + cx.set_request_handler::(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::({ + cx.set_request_handler::({ 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::({ + cx.set_request_handler::({ 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::(move |_, _, _| { + cx.set_request_handler::(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::(move |_, _, _| { + cx.set_request_handler::(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::(move |_, _| async move { + .set_request_handler::(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::( - 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::(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::( + 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::(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::(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::( + 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::(move |url, _, _| async move { + cx.set_request_handler::(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::(move |url, _, _| async move { + cx.set_request_handler::(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::(|_, _| async move { + .set_request_handler::(|_, _| 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::(|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::( + |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::({ + .set_request_handler::({ 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 { let mut request = - cx.handle_request::(move |_, _, _| { + cx.set_request_handler::(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::(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::(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::(move |_, _, _| { + cx.set_request_handler::(move |_, _, _| { let edits = edits.clone(); async move { Ok(lsp::CompletionItem { diff --git a/crates/editor/src/hover_links.rs b/crates/editor/src/hover_links.rs index 16dfcaa21e..38bac73ee0 100644 --- a/crates/editor/src/hover_links.rs +++ b/crates/editor/src/hover_links.rs @@ -962,7 +962,7 @@ mod tests { cx.run_until_parked(); let mut requests = - cx.handle_request::(move |url, _, _| async move { + cx.set_request_handler::(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::(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::(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::(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::(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::(move |_, _| async move { - // No definitions returned - Ok(Some(lsp::GotoDefinitionResponse::Link(vec![]))) - }); + let mut requests = + cx.lsp + .set_request_handler::(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::(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::(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::(move |_, _| async move { + .set_request_handler::(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::(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::(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::(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::(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::(move |params, _| { + .set_request_handler::(move |params, _| { let expected_uri = expected_uri.clone(); async move { assert_eq!(params.text_document.uri, expected_uri); diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index 65b1d160e6..5670e774c3 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -1029,7 +1029,7 @@ mod tests { fn test() { «println!»(); } "}); let mut requests = - cx.handle_request::(move |_, _, _| async move { + cx.set_request_handler::(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::(|_, _| async move { Ok(None) }); + .set_request_handler::( + |_, _| 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::(move |_, _, _| async move { + cx.set_request_handler::(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::(|_, _| async move { Ok(None) }); + .set_request_handler::( + |_, _| 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::(move |_, _, _| async move { + cx.set_request_handler::(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::(move |_, _, _| async move { + cx.set_request_handler::(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::(move |_, _, _| { + cx.set_request_handler::(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::(move |_, _, _| async move { + cx.set_request_handler::(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::({ - |_, _| async move { - Ok(Some(lsp::Hover { - contents: lsp::HoverContents::Markup(lsp::MarkupContent { - kind: lsp::MarkupKind::Markdown, - value: indoc!( - r#" + cx.lsp + .set_request_handler::({ + |_, _| 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"; let closure_uri = uri.clone(); cx.lsp - .handle_request::(move |params, _| { + .set_request_handler::(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::( + .set_request_handler::( move |mut hint_to_resolve, _| { let mut resolved_hint_positions = BTreeSet::new(); let task_uri = resolve_closure_uri.clone(); diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index 4b5c4c5100..9d237a84d5 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -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::(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::( + 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::(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::( + 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::( - 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::( + 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::( + fake_server.set_request_handler::( 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::( + fake_server.set_request_handler::( 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::( + fake_server.set_request_handler::( 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::(move |params, _| { + .set_request_handler::(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::(move |params, _| { + .set_request_handler::(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::( + fake_server.set_request_handler::( 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::(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::( + 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::( + fake_server.set_request_handler::( move |params, _| async move { assert_eq!( params.text_document.uri, diff --git a/crates/editor/src/test/editor_lsp_test_context.rs b/crates/editor/src/test/editor_lsp_test_context.rs index 05b5e2b258..7031139ca6 100644 --- a/crates/editor/src/test/editor_lsp_test_context.rs +++ b/crates/editor/src/test/editor_lsp_test_context.rs @@ -337,7 +337,7 @@ impl EditorLspTestContext { self.workspace.update_in(&mut self.cx.cx, update) } - pub fn handle_request( + pub fn set_request_handler( &self, mut handler: F, ) -> futures::channel::mpsc::UnboundedReceiver<()> @@ -348,7 +348,7 @@ impl EditorLspTestContext { Fut: 'static + Send + Future>, { let url = self.buffer_lsp_url.clone(); - self.lsp.handle_request::(move |params, cx| { + self.lsp.set_request_handler::(move |params, cx| { let url = url.clone(); handler(url, params, cx) }) diff --git a/crates/extension_host/src/extension_store_test.rs b/crates/extension_host/src/extension_store_test.rs index 9ce6c82e89..84b504be13 100644 --- a/crates/extension_host/src/extension_store_test.rs +++ b/crates/extension_host/src/extension_store_test.rs @@ -670,7 +670,7 @@ async fn test_extension_store_with_test_extension(cx: &mut TestAppContext) { ); // The extension creates custom labels for completion items. - fake_server.handle_request::(|_, _| async move { + fake_server.set_request_handler::(|_, _| async move { Ok(Some(lsp::CompletionResponse::Array(vec![ lsp::CompletionItem { label: "foo".into(), diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 42a5da9163..c076b405d8 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -2160,8 +2160,10 @@ impl Buffer { { // Skip invalid edits and coalesce contiguous ones. let mut edits: Vec<(Range, Arc)> = Vec::new(); + for (range, new_text) in edits_iter { let mut range = range.start.to_offset(self)..range.end.to_offset(self); + if range.start > range.end { mem::swap(&mut range.start, &mut range.end); } diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index f906b5dfaa..486b431547 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -1440,7 +1440,7 @@ impl FakeLanguageServer { }), notifications_rx, }; - fake.handle_request::({ + fake.set_request_handler::({ let capabilities = capabilities; move |_, _| { let capabilities = capabilities.clone(); @@ -1524,7 +1524,7 @@ impl FakeLanguageServer { } /// Registers a handler for a specific kind of request. Removes any existing handler for specified request type. - pub fn handle_request( + pub fn set_request_handler( &self, mut handler: F, ) -> futures::channel::mpsc::UnboundedReceiver<()> @@ -1699,7 +1699,7 @@ mod tests { "file://b/c" ); - fake.handle_request::(|_, _| async move { Ok(()) }); + fake.set_request_handler::(|_, _| async move { Ok(()) }); drop(server); fake.receive_notification::().await; diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index f989736b33..205900dd29 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -832,9 +832,9 @@ async fn test_managing_language_servers(cx: &mut gpui::TestAppContext) { }); let mut rust_shutdown_requests = fake_rust_server - .handle_request::(|_, _| future::ready(Ok(()))); + .set_request_handler::(|_, _| future::ready(Ok(()))); let mut json_shutdown_requests = fake_json_server - .handle_request::(|_, _| future::ready(Ok(()))); + .set_request_handler::(|_, _| future::ready(Ok(()))); futures::join!(rust_shutdown_requests.next(), json_shutdown_requests.next()); let mut fake_rust_server = fake_rust_servers.next().await.unwrap(); @@ -2701,7 +2701,7 @@ async fn test_definition(cx: &mut gpui::TestAppContext) { .unwrap(); let fake_server = fake_servers.next().await.unwrap(); - fake_server.handle_request::(|params, _| async move { + fake_server.set_request_handler::(|params, _| async move { let params = params.text_document_position_params; assert_eq!( params.text_document.uri.to_file_path().unwrap(), @@ -2818,7 +2818,7 @@ async fn test_completions_without_edit_ranges(cx: &mut gpui::TestAppContext) { }); fake_server - .handle_request::(|_, _| async move { + .set_request_handler::(|_, _| async move { Ok(Some(lsp::CompletionResponse::Array(vec![ lsp::CompletionItem { label: "fullyQualifiedName?".into(), @@ -2845,7 +2845,7 @@ async fn test_completions_without_edit_ranges(cx: &mut gpui::TestAppContext) { }); fake_server - .handle_request::(|_, _| async move { + .set_request_handler::(|_, _| async move { Ok(Some(lsp::CompletionResponse::Array(vec![ lsp::CompletionItem { label: "component".into(), @@ -2912,7 +2912,7 @@ async fn test_completions_with_carriage_returns(cx: &mut gpui::TestAppContext) { }); fake_server - .handle_request::(|_, _| async move { + .set_request_handler::(|_, _| async move { Ok(Some(lsp::CompletionResponse::Array(vec![ lsp::CompletionItem { label: "fullyQualifiedName?".into(), @@ -2979,7 +2979,7 @@ async fn test_apply_code_actions_with_commands(cx: &mut gpui::TestAppContext) { project.code_actions(&buffer, 0..0, None, cx) }); fake_server - .handle_request::(|_, _| async move { + .set_request_handler::(|_, _| async move { Ok(Some(vec![ lsp::CodeActionOrCommand::CodeAction(lsp::CodeAction { title: "The code action".into(), @@ -3004,7 +3004,7 @@ async fn test_apply_code_actions_with_commands(cx: &mut gpui::TestAppContext) { // Resolving the code action does not populate its edits. In absence of // edits, we must execute the given command. - fake_server.handle_request::( + fake_server.set_request_handler::( |mut action, _| async move { if action.data.is_some() { action.command = Some(lsp::Command { @@ -3020,7 +3020,7 @@ async fn test_apply_code_actions_with_commands(cx: &mut gpui::TestAppContext) { // While executing the command, the language server sends the editor // a `workspaceEdit` request. fake_server - .handle_request::({ + .set_request_handler::({ let fake = fake_server.clone(); move |params, _| { assert_eq!(params.command, "_the/command"); @@ -4212,7 +4212,7 @@ async fn test_lsp_rename_notifications(cx: &mut gpui::TestAppContext) { }; let resolved_workspace_edit = Arc::new(OnceLock::new()); fake_server - .handle_request::({ + .set_request_handler::({ let resolved_workspace_edit = resolved_workspace_edit.clone(); let expected_edit = expected_edit.clone(); move |params, _| { @@ -4289,7 +4289,7 @@ async fn test_rename(cx: &mut gpui::TestAppContext) { project.prepare_rename(buffer.clone(), 7, cx) }); fake_server - .handle_request::(|params, _| async move { + .set_request_handler::(|params, _| async move { assert_eq!( params.text_document.uri.as_str(), uri!("file:///dir/one.rs") @@ -4314,7 +4314,7 @@ async fn test_rename(cx: &mut gpui::TestAppContext) { project.perform_rename(buffer.clone(), 7, "THREE".to_string(), cx) }); fake_server - .handle_request::(|params, _| async move { + .set_request_handler::(|params, _| async move { assert_eq!( params.text_document_position.text_document.uri.as_str(), uri!("file:///dir/one.rs") @@ -5175,35 +5175,36 @@ async fn test_multiple_language_server_hovers(cx: &mut gpui::TestAppContext) { "TailwindServer" | "TypeScriptServer" => { servers_with_hover_requests.insert( new_server_name.clone(), - new_server.handle_request::(move |_, _| { - let name = new_server_name.clone(); - async move { - Ok(Some(lsp::Hover { - contents: lsp::HoverContents::Scalar(lsp::MarkedString::String( - format!("{name} hover"), - )), - range: None, - })) - } - }), + new_server.set_request_handler::( + move |_, _| { + let name = new_server_name.clone(); + async move { + Ok(Some(lsp::Hover { + contents: lsp::HoverContents::Scalar( + lsp::MarkedString::String(format!("{name} hover")), + ), + range: None, + })) + } + }, + ), ); } "ESLintServer" => { servers_with_hover_requests.insert( new_server_name, - new_server.handle_request::( + new_server.set_request_handler::( |_, _| async move { Ok(None) }, ), ); } "NoHoverCapabilitiesServer" => { - let _never_handled = new_server.handle_request::( - |_, _| async move { + let _never_handled = new_server + .set_request_handler::(|_, _| async move { panic!( "Should not call for hovers server with no corresponding capabilities" ) - }, - ); + }); } unexpected => panic!("Unexpected server name: {unexpected}"), } @@ -5274,8 +5275,8 @@ async fn test_hovers_with_empty_parts(cx: &mut gpui::TestAppContext) { .await .expect("failed to get the language server"); - let mut request_handled = - fake_server.handle_request::(move |_, _| async move { + let mut request_handled = fake_server.set_request_handler::( + move |_, _| async move { Ok(Some(lsp::Hover { contents: lsp::HoverContents::Array(vec![ lsp::MarkedString::String("".to_string()), @@ -5284,7 +5285,8 @@ async fn test_hovers_with_empty_parts(cx: &mut gpui::TestAppContext) { ]), range: None, })) - }); + }, + ); let hover_task = project.update(cx, |project, cx| { project.hover(&buffer, Point::new(0, 0), cx) @@ -5346,8 +5348,8 @@ async fn test_code_actions_only_kinds(cx: &mut gpui::TestAppContext) { .await .expect("failed to get the language server"); - let mut request_handled = fake_server.handle_request::( - move |_, _| async move { + let mut request_handled = fake_server + .set_request_handler::(move |_, _| async move { Ok(Some(vec![ lsp::CodeActionOrCommand::CodeAction(lsp::CodeAction { title: "organize imports".to_string(), @@ -5360,8 +5362,7 @@ async fn test_code_actions_only_kinds(cx: &mut gpui::TestAppContext) { ..lsp::CodeAction::default() }), ])) - }, - ); + }); let code_actions_task = project.update(cx, |project, cx| { project.code_actions( @@ -5482,7 +5483,7 @@ async fn test_multiple_language_server_actions(cx: &mut gpui::TestAppContext) { "TailwindServer" | "TypeScriptServer" => { servers_with_actions_requests.insert( new_server_name.clone(), - new_server.handle_request::( + new_server.set_request_handler::( move |_, _| { let name = new_server_name.clone(); async move { @@ -5500,14 +5501,14 @@ async fn test_multiple_language_server_actions(cx: &mut gpui::TestAppContext) { "ESLintServer" => { servers_with_actions_requests.insert( new_server_name, - new_server.handle_request::( + new_server.set_request_handler::( |_, _| async move { Ok(None) }, ), ); } "NoActionsCapabilitiesServer" => { let _never_handled = new_server - .handle_request::(|_, _| async move { + .set_request_handler::(|_, _| async move { panic!( "Should not call for code actions server with no corresponding capabilities" ) diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index eaabac5d6f..fe0761e7a4 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -316,7 +316,7 @@ mod tests { symbol("uno", path!("/dir/test.rs")), ]; let fake_server = fake_servers.next().await.unwrap(); - fake_server.handle_request::( + fake_server.set_request_handler::( move |params: lsp::WorkspaceSymbolParams, cx| { let executor = cx.background_executor().clone(); let fake_symbols = fake_symbols.clone(); diff --git a/crates/remote_server/src/remote_editing_tests.rs b/crates/remote_server/src/remote_editing_tests.rs index e15ea20c90..5a72a946cf 100644 --- a/crates/remote_server/src/remote_editing_tests.rs +++ b/crates/remote_server/src/remote_editing_tests.rs @@ -483,7 +483,7 @@ async fn test_remote_lsp(cx: &mut TestAppContext, server_cx: &mut TestAppContext assert_eq!(lsp_store.as_local().unwrap().language_servers.len(), 1); }); - fake_lsp.handle_request::(|_, _| async move { + fake_lsp.set_request_handler::(|_, _| async move { Ok(Some(CompletionResponse::Array(vec![lsp::CompletionItem { label: "boop".to_string(), ..Default::default() @@ -514,7 +514,7 @@ async fn test_remote_lsp(cx: &mut TestAppContext, server_cx: &mut TestAppContext vec!["boop".to_string()] ); - fake_lsp.handle_request::(|_, _| async move { + fake_lsp.set_request_handler::(|_, _| async move { Ok(Some(lsp::WorkspaceEdit { changes: Some( [( diff --git a/crates/vim/src/normal/repeat.rs b/crates/vim/src/normal/repeat.rs index 2a0f683bc9..6206688267 100644 --- a/crates/vim/src/normal/repeat.rs +++ b/crates/vim/src/normal/repeat.rs @@ -434,8 +434,8 @@ mod test { Mode::Normal, ); - let mut request = - cx.handle_request::(move |_, params, _| async move { + let mut request = cx.set_request_handler::( + move |_, params, _| async move { let position = params.text_document_position.position; Ok(Some(lsp::CompletionResponse::Array(vec![ lsp::CompletionItem { @@ -455,7 +455,8 @@ mod test { ..Default::default() }, ]))) - }); + }, + ); cx.simulate_keystrokes("a ."); request.next().await; cx.condition(|editor, _| editor.context_menu_visible()) diff --git a/crates/vim/src/test.rs b/crates/vim/src/test.rs index 1278555788..c9664e9346 100644 --- a/crates/vim/src/test.rs +++ b/crates/vim/src/test.rs @@ -917,12 +917,11 @@ async fn test_rename(cx: &mut gpui::TestAppContext) { cx.set_state("const beˇfore = 2; console.log(before)", Mode::Normal); let def_range = cx.lsp_range("const «beforeˇ» = 2; console.log(before)"); let tgt_range = cx.lsp_range("const before = 2; console.log(«beforeˇ»)"); - let mut prepare_request = - cx.handle_request::(move |_, _, _| async move { - Ok(Some(lsp::PrepareRenameResponse::Range(def_range))) - }); + let mut prepare_request = cx.set_request_handler::( + move |_, _, _| async move { Ok(Some(lsp::PrepareRenameResponse::Range(def_range))) }, + ); let mut rename_request = - cx.handle_request::(move |url, params, _| async move { + cx.set_request_handler::(move |url, params, _| async move { Ok(Some(lsp::WorkspaceEdit { changes: Some( [(