aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/rust-analyzer/src/caps.rs24
-rw-r--r--crates/rust-analyzer/src/handlers.rs24
-rw-r--r--crates/rust-analyzer/tests/rust-analyzer/main.rs144
3 files changed, 178 insertions, 14 deletions
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index 3db0d55c5..f148521a2 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -75,14 +75,24 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
75 will_create: None, 75 will_create: None,
76 did_rename: None, 76 did_rename: None,
77 will_rename: Some(FileOperationRegistrationOptions { 77 will_rename: Some(FileOperationRegistrationOptions {
78 filters: vec![FileOperationFilter { 78 filters: vec![
79 scheme: Some(String::from("file")), 79 FileOperationFilter {
80 pattern: FileOperationPattern { 80 scheme: Some(String::from("file")),
81 glob: String::from("**/*.rs"), 81 pattern: FileOperationPattern {
82 matches: Some(FileOperationPatternKind::File), 82 glob: String::from("**/*.rs"),
83 options: None, 83 matches: Some(FileOperationPatternKind::File),
84 options: None,
85 },
84 }, 86 },
85 }], 87 FileOperationFilter {
88 scheme: Some(String::from("file")),
89 pattern: FileOperationPattern {
90 glob: String::from("**"),
91 matches: Some(FileOperationPatternKind::Folder),
92 options: None,
93 },
94 },
95 ],
86 }), 96 }),
87 did_delete: None, 97 did_delete: None,
88 will_delete: None, 98 will_delete: None,
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 70dd51911..dc81f55d6 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -432,9 +432,27 @@ pub(crate) fn handle_will_rename_files(
432 // Limit to single-level moves for now. 432 // Limit to single-level moves for now.
433 match (from_path.parent(), to_path.parent()) { 433 match (from_path.parent(), to_path.parent()) {
434 (Some(p1), Some(p2)) if p1 == p2 => { 434 (Some(p1), Some(p2)) if p1 == p2 => {
435 let new_name = to_path.file_stem()?; 435 if from_path.is_dir() {
436 let new_name = new_name.to_str()?; 436 // add '/' to end of url -- from `file://path/to/folder` to `file://path/to/folder/`
437 Some((snap.url_to_file_id(&from).ok()?, new_name.to_string())) 437 let mut old_folder_name = from_path.file_stem()?.to_str()?.to_string();
438 old_folder_name.push('/');
439 let from_with_trailing_slash = from.join(&old_folder_name).ok()?;
440
441 let imitate_from_url = from_with_trailing_slash.join("mod.rs").ok()?;
442 let new_file_name = to_path.file_name()?.to_str()?;
443 Some((
444 snap.url_to_file_id(&imitate_from_url).ok()?,
445 new_file_name.to_string(),
446 ))
447 } else {
448 let old_name = from_path.file_stem()?.to_str()?;
449 let new_name = to_path.file_stem()?.to_str()?;
450 match (old_name, new_name) {
451 ("mod", _) => None,
452 (_, "mod") => None,
453 _ => Some((snap.url_to_file_id(&from).ok()?, new_name.to_string())),
454 }
455 }
438 } 456 }
439 _ => None, 457 _ => None,
440 } 458 }
diff --git a/crates/rust-analyzer/tests/rust-analyzer/main.rs b/crates/rust-analyzer/tests/rust-analyzer/main.rs
index f5c5c63e5..80bde29b9 100644
--- a/crates/rust-analyzer/tests/rust-analyzer/main.rs
+++ b/crates/rust-analyzer/tests/rust-analyzer/main.rs
@@ -16,11 +16,14 @@ use std::{collections::HashMap, path::PathBuf, time::Instant};
16use expect_test::expect; 16use expect_test::expect;
17use lsp_types::{ 17use lsp_types::{
18 notification::DidOpenTextDocument, 18 notification::DidOpenTextDocument,
19 request::{CodeActionRequest, Completion, Formatting, GotoTypeDefinition, HoverRequest}, 19 request::{
20 CodeActionRequest, Completion, Formatting, GotoTypeDefinition, HoverRequest,
21 WillRenameFiles,
22 },
20 CodeActionContext, CodeActionParams, CompletionParams, DidOpenTextDocumentParams, 23 CodeActionContext, CodeActionParams, CompletionParams, DidOpenTextDocumentParams,
21 DocumentFormattingParams, FormattingOptions, GotoDefinitionParams, HoverParams, 24 DocumentFormattingParams, FileRename, FormattingOptions, GotoDefinitionParams, HoverParams,
22 PartialResultParams, Position, Range, TextDocumentItem, TextDocumentPositionParams, 25 PartialResultParams, Position, Range, RenameFilesParams, TextDocumentItem,
23 WorkDoneProgressParams, 26 TextDocumentPositionParams, WorkDoneProgressParams,
24}; 27};
25use rust_analyzer::lsp_ext::{OnEnter, Runnables, RunnablesParams}; 28use rust_analyzer::lsp_ext::{OnEnter, Runnables, RunnablesParams};
26use serde_json::json; 29use serde_json::json;
@@ -745,3 +748,136 @@ pub fn foo(_input: TokenStream) -> TokenStream {
745 ```"#]] 748 ```"#]]
746 .assert_eq(&value); 749 .assert_eq(&value);
747} 750}
751
752#[test]
753fn test_will_rename_files_same_level() {
754 if skip_slow_tests() {
755 return;
756 }
757
758 let tmp_dir = TestDir::new();
759 let tmp_dir_path = tmp_dir.path().to_owned();
760 let tmp_dir_str = tmp_dir_path.to_str().unwrap();
761 let base_path = PathBuf::from(format!("file://{}", tmp_dir_str));
762
763 let code = r#"
764//- /Cargo.toml
765[package]
766name = "foo"
767version = "0.0.0"
768
769//- /src/lib.rs
770mod old_file;
771mod from_mod;
772mod to_mod;
773mod old_folder;
774fn main() {}
775
776//- /src/old_file.rs
777
778//- /src/old_folder/mod.rs
779
780//- /src/from_mod/mod.rs
781
782//- /src/to_mod/foo.rs
783
784"#;
785 let server =
786 Project::with_fixture(&code).tmp_dir(tmp_dir).server().wait_until_workspace_is_loaded();
787
788 //rename same level file
789 server.request::<WillRenameFiles>(
790 RenameFilesParams {
791 files: vec![FileRename {
792 old_uri: base_path.join("src/old_file.rs").to_str().unwrap().to_string(),
793 new_uri: base_path.join("src/new_file.rs").to_str().unwrap().to_string(),
794 }],
795 },
796 json!({
797 "documentChanges": [
798 {
799 "textDocument": {
800 "uri": format!("file://{}", tmp_dir_path.join("src").join("lib.rs").to_str().unwrap().to_string().replace("C:\\", "/c:/").replace("\\", "/")),
801 "version": null
802 },
803 "edits": [
804 {
805 "range": {
806 "start": {
807 "line": 0,
808 "character": 4
809 },
810 "end": {
811 "line": 0,
812 "character": 12
813 }
814 },
815 "newText": "new_file"
816 }
817 ]
818 }
819 ]
820 }),
821 );
822
823 //rename file from mod.rs to foo.rs
824 server.request::<WillRenameFiles>(
825 RenameFilesParams {
826 files: vec![FileRename {
827 old_uri: base_path.join("src/from_mod/mod.rs").to_str().unwrap().to_string(),
828 new_uri: base_path.join("src/from_mod/foo.rs").to_str().unwrap().to_string(),
829 }],
830 },
831 json!({
832 "documentChanges": []
833 }),
834 );
835
836 //rename file from foo.rs to mod.rs
837 server.request::<WillRenameFiles>(
838 RenameFilesParams {
839 files: vec![FileRename {
840 old_uri: base_path.join("src/to_mod/foo.rs").to_str().unwrap().to_string(),
841 new_uri: base_path.join("src/to_mod/mod.rs").to_str().unwrap().to_string(),
842 }],
843 },
844 json!({
845 "documentChanges": []
846 }),
847 );
848
849 //rename same level file
850 server.request::<WillRenameFiles>(
851 RenameFilesParams {
852 files: vec![FileRename {
853 old_uri: base_path.join("src/old_folder").to_str().unwrap().to_string(),
854 new_uri: base_path.join("src/new_folder").to_str().unwrap().to_string(),
855 }],
856 },
857 json!({
858 "documentChanges": [
859 {
860 "textDocument": {
861 "uri": format!("file://{}", tmp_dir_path.join("src").join("lib.rs").to_str().unwrap().to_string().replace("C:\\", "/c:/").replace("\\", "/")),
862 "version": null
863 },
864 "edits": [
865 {
866 "range": {
867 "start": {
868 "line": 3,
869 "character": 4
870 },
871 "end": {
872 "line": 3,
873 "character": 14
874 }
875 },
876 "newText": "new_folder"
877 }
878 ]
879 }
880 ]
881 }),
882 );
883}