about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/ide/src/rename.rs74
-rw-r--r--crates/ide_assists/src/tests.rs4
-rw-r--r--crates/ide_db/src/rename.rs26
-rw-r--r--crates/ide_db/src/source_change.rs1
-rw-r--r--crates/rust-analyzer/src/to_proto.rs14
5 files changed, 106 insertions, 13 deletions
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index 83bc299adcc..b850908ce55 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -963,15 +963,21 @@ mod fo$0o;
                         },
                     },
                     file_system_edits: [
-                        MoveFile {
-                            src: FileId(
+                        MoveDir {
+                            src: AnchoredPathBuf {
+                                anchor: FileId(
+                                    1,
+                                ),
+                                path: "foo",
+                            },
+                            src_id: FileId(
                                 1,
                             ),
                             dst: AnchoredPathBuf {
                                 anchor: FileId(
                                     1,
                                 ),
-                                path: "../foo2/mod.rs",
+                                path: "foo2",
                             },
                         },
                     ],
@@ -1109,6 +1115,68 @@ pub mod foo$0;
     }
 
     #[test]
+    fn test_rename_mod_recursive() {
+        check_expect(
+            "foo2",
+            r#"
+//- /lib.rs
+mod foo$0;
+
+//- /foo.rs
+mod bar;
+mod corge;
+
+//- /foo/bar.rs
+mod qux;
+
+//- /foo/bar/qux.rs
+mod quux;
+
+//- /foo/bar/qux/quux/mod.rs
+// empty
+
+//- /foo/corge.rs
+// empty
+"#,
+            expect![[r#"
+                SourceChange {
+                    source_file_edits: {
+                        FileId(
+                            0,
+                        ): TextEdit {
+                            indels: [
+                                Indel {
+                                    insert: "foo2",
+                                    delete: 4..7,
+                                },
+                            ],
+                        },
+                    },
+                    file_system_edits: [
+                        MoveDir {
+                            src: AnchoredPathBuf {
+                                anchor: FileId(
+                                    1,
+                                ),
+                                path: "foo",
+                            },
+                            src_id: FileId(
+                                1,
+                            ),
+                            dst: AnchoredPathBuf {
+                                anchor: FileId(
+                                    1,
+                                ),
+                                path: "foo2",
+                            },
+                        },
+                    ],
+                    is_snippet: false,
+                }
+            "#]],
+        )
+    }
+    #[test]
     fn test_rename_mod_ref_by_super() {
         check(
             "baz",
diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs
index 09260c12ed9..b3a0bd27730 100644
--- a/crates/ide_assists/src/tests.rs
+++ b/crates/ide_assists/src/tests.rs
@@ -162,6 +162,10 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
                     FileSystemEdit::MoveFile { src, dst } => {
                         (dst, db.file_text(src).as_ref().to_owned())
                     }
+                    FileSystemEdit::MoveDir { src, src_id, dst } => {
+                        // temporary placeholder for MoveDir since we are not using MoveDir in ide assists yet.
+                        (dst, format!("{:?}\n{:?}", src_id, src))
+                    }
                 };
                 let sr = db.file_source_root(dst.anchor);
                 let sr = db.source_root(sr);
diff --git a/crates/ide_db/src/rename.rs b/crates/ide_db/src/rename.rs
index 13234a817b2..589975406a4 100644
--- a/crates/ide_db/src/rename.rs
+++ b/crates/ide_db/src/rename.rs
@@ -178,17 +178,23 @@ fn rename_mod(
     let mut source_change = SourceChange::default();
 
     let InFile { file_id, value: def_source } = module.definition_source(sema.db);
-    let file_id = file_id.original_file(sema.db);
     if let ModuleSource::SourceFile(..) = def_source {
-        // mod is defined in path/to/dir/mod.rs
-        let path = if module.is_mod_rs(sema.db) {
-            format!("../{}/mod.rs", new_name)
-        } else {
-            format!("{}.rs", new_name)
-        };
-        let dst = AnchoredPathBuf { anchor: file_id, path };
-        let move_file = FileSystemEdit::MoveFile { src: file_id, dst };
-        source_change.push_file_system_edit(move_file);
+        let anchor = file_id.original_file(sema.db);
+        // not mod.rs and doesn't has children, rename file only
+        if !module.is_mod_rs(sema.db) && module.children(sema.db).next().is_none() {
+            let path = format!("{}.rs", new_name);
+            let dst = AnchoredPathBuf { anchor, path };
+            source_change.push_file_system_edit(FileSystemEdit::MoveFile { src: anchor, dst })
+        } else if let Some(mod_name) = module.name(sema.db) {
+            // is mod.rs or has children, rename dir
+            let src = AnchoredPathBuf { anchor, path: mod_name.to_string() };
+            let dst = AnchoredPathBuf { anchor, path: new_name.to_string() };
+            source_change.push_file_system_edit(FileSystemEdit::MoveDir {
+                src,
+                src_id: anchor,
+                dst,
+            })
+        }
     }
 
     if let Some(src) = module.declaration_source(sema.db) {
diff --git a/crates/ide_db/src/source_change.rs b/crates/ide_db/src/source_change.rs
index aa910eb3254..8132c73ef26 100644
--- a/crates/ide_db/src/source_change.rs
+++ b/crates/ide_db/src/source_change.rs
@@ -85,6 +85,7 @@ impl From<FxHashMap<FileId, TextEdit>> for SourceChange {
 pub enum FileSystemEdit {
     CreateFile { dst: AnchoredPathBuf, initial_contents: String },
     MoveFile { src: FileId, dst: AnchoredPathBuf },
+    MoveDir { src: AnchoredPathBuf, src_id: FileId, dst: AnchoredPathBuf },
 }
 
 impl From<FileSystemEdit> for SourceChange {
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 9b377f742b3..779f7d24ef6 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -864,6 +864,20 @@ pub(crate) fn snippet_text_document_ops(
                 rename_file,
             )))
         }
+        FileSystemEdit::MoveDir { src, src_id, dst } => {
+            let old_uri = snap.anchored_path(&src);
+            let new_uri = snap.anchored_path(&dst);
+            let mut rename_file =
+                lsp_types::RenameFile { old_uri, new_uri, options: None, annotation_id: None };
+            if snap.analysis.is_library_file(src_id).ok() == Some(true)
+                && snap.config.change_annotation_support()
+            {
+                rename_file.annotation_id = Some(outside_workspace_annotation_id())
+            }
+            ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(lsp_types::ResourceOp::Rename(
+                rename_file,
+            )))
+        }
     }
     Ok(ops)
 }