about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-04-12 15:17:00 +0000
committerGitHub <noreply@github.com>2022-04-12 15:17:00 +0000
commit49847a25ae086549ef940f0c176f21f4f32ef83b (patch)
tree8dbcc59691a4072267a34a126f68112e8b314473
parent12fb8ab3b2dd5544e3a67be63e1bf569b0c944c5 (diff)
parent3dd581b97d051e091037abca62564630d51bfea8 (diff)
downloadrust-49847a25ae086549ef940f0c176f21f4f32ef83b.tar.gz
rust-49847a25ae086549ef940f0c176f21f4f32ef83b.zip
Merge #11883
11883: fix(ide): move moudle directory when rename r=rainy-me a=rainy-me

fix: #10992

Added `FileSystemEdit::MoveDir` variant for move dirs. Original implemented as recursively move child mod files but had many issues like

1. left empty dir after rename file
2. only affect rust file
3. not performant

so changed to current version

Co-authored-by: rainy-me <github@yue.coffee>
-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 1bb3cdb9073..f5bff5fd918 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -968,15 +968,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",
                             },
                         },
                     ],
@@ -1114,6 +1120,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 0588f00678a..3d83f090e2e 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -866,6 +866,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)
 }