From 3af69b535992203c2582433d968eed22a7e7fe69 Mon Sep 17 00:00:00 2001
From: Lukas Wirth <lukastw97@gmail.com>
Date: Wed, 10 Mar 2021 15:49:01 +0100
Subject: Avoid double text edits when renaming mod declaration

---
 crates/hir/src/lib.rs                |  1 -
 crates/ide/src/references/rename.rs  |  1 +
 crates/rust-analyzer/src/config.rs   |  3 +++
 crates/rust-analyzer/src/handlers.rs | 12 +++++++++++-
 4 files changed, 15 insertions(+), 2 deletions(-)

(limited to 'crates')

diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 4ef38c0f0..58adc8fd3 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -305,7 +305,6 @@ impl ModuleDef {
             ModuleDef::Module(it) => it.name(db),
             ModuleDef::Const(it) => it.name(db),
             ModuleDef::Static(it) => it.name(db),
-
             ModuleDef::BuiltinType(it) => Some(it.name()),
         }
     }
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index 05c73de88..bb68bcc78 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -94,6 +94,7 @@ pub(crate) fn rename_with_semantics(
     }
 }
 
+/// Called by the client when it is about to rename a file.
 pub(crate) fn will_rename_file(
     db: &RootDatabase,
     file_id: FileId,
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 25df13554..8af7871ac 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -395,6 +395,9 @@ impl Config {
     pub fn work_done_progress(&self) -> bool {
         try_or!(self.caps.window.as_ref()?.work_done_progress?, false)
     }
+    pub fn will_rename(&self) -> bool {
+        try_or!(self.caps.workspace.as_ref()?.file_operations.as_ref()?.will_rename?, false)
+    }
     pub fn code_action_resolve(&self) -> bool {
         try_or!(
             self.caps
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index b5b2ffe50..6cc433cb8 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -799,8 +799,18 @@ pub(crate) fn handle_rename(
     let _p = profile::span("handle_rename");
     let position = from_proto::file_position(&snap, params.text_document_position)?;
 
-    let change =
+    let mut change =
         snap.analysis.rename(position, &*params.new_name)?.map_err(to_proto::rename_error)?;
+
+    // this is kind of a hack to prevent double edits from happening when moving files
+    // When a module gets renamed by renaming the mod declaration this causes the file to move
+    // which in turn will trigger a WillRenameFiles request to the server for which we reply with a
+    // a second identical set of renames, the client will then apply both edits causing incorrect edits
+    // with this we only emit source_file_edits in the WillRenameFiles response which will do the rename instead
+    // See https://github.com/microsoft/vscode-languageserver-node/issues/752 for more info
+    if !change.file_system_edits.is_empty() && snap.config.will_rename() {
+        change.source_file_edits.clear();
+    }
     let workspace_edit = to_proto::workspace_edit(&snap, change)?;
     Ok(Some(workspace_edit))
 }
-- 
cgit v1.2.3