diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index db1ce41b73409e..5e4d6551c8f1b5 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -8026,6 +8026,11 @@ impl Editor { return None; } let rename = self.take_rename(false, window, cx)?; + let new_name = rename.editor.read(cx).text(cx); + if new_name.trim().is_empty() { + return Some(Task::ready(Ok(()))); + } + let workspace = self.workspace()?.downgrade(); let (buffer, start) = self .buffer @@ -8040,7 +8045,6 @@ impl Editor { } let old_name = rename.old_name; - let new_name = rename.editor.read(cx).text(cx); let rename = self.semantics_provider.as_ref()?.perform_rename( &buffer, diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 7188130b8a411d..ad84ff1dc52993 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -33205,6 +33205,88 @@ async fn test_go_to_bookmark_with_out_of_order_bookmarks(cx: &mut TestAppContext assert_eq!(ctx.cursor_row(), 1, "Prev from row 5 should go to row 1"); } +#[gpui::test] +async fn test_empty_rename_is_no_op(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + let capabilities = lsp::ServerCapabilities { + rename_provider: Some(lsp::OneOf::Right(lsp::RenameOptions { + prepare_provider: Some(true), + work_done_progress_options: Default::default(), + })), + ..Default::default() + }; + let mut cx = EditorLspTestContext::new_rust(capabilities, cx).await; + + cx.set_state("let aˇbc = 1;"); + + let rename_request_count = Arc::new(AtomicUsize::new(0)); + let _rename_handler = cx.set_request_handler::({ + let rename_request_count = rename_request_count.clone(); + move |_, _, _| { + rename_request_count.fetch_add(1, atomic::Ordering::SeqCst); + async { Ok(None) } + } + }); + 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: 4, + }, + end: lsp::Position { + line: 0, + character: 7, + }, + }))) + }, + ); + + for new_name in ["", " "] { + let prepare_rename_task = cx + .update_editor(|editor, window, cx| editor.rename(&Rename, window, cx)) + .expect("Prepare rename was not started"); + prepare_rename_handler.next().await.unwrap(); + prepare_rename_task.await.expect("Prepare rename failed"); + + let rename_editor = cx.editor(|editor, _, _| { + editor + .pending_rename() + .expect("Rename should still be pending") + .editor + .clone() + }); + rename_editor.update_in(&mut cx.cx.cx, |editor, window, cx| { + editor.backspace(&Backspace, window, cx); + editor.insert(new_name, window, cx); + }); + assert_eq!( + cx.editor(|editor, _, cx| { + editor + .pending_rename() + .expect("Rename should still be pending") + .editor + .read(cx) + .text(cx) + }), + new_name + ); + + cx.update_editor(|editor, window, cx| { + editor + .confirm_rename(&ConfirmRename, window, cx) + .expect("Confirm rename should consume the action") + }) + .await + .expect("Confirm rename failed"); + + assert_eq!(rename_request_count.load(atomic::Ordering::SeqCst), 0); + assert!(cx.editor(|editor, _, _| editor.pending_rename().is_none())); + assert_eq!(cx.buffer_text(), "let abc = 1;"); + } +} + #[gpui::test] async fn test_rename_with_duplicate_edits(cx: &mut TestAppContext) { init_test(cx, |_| {});