]> git.lizzy.rs Git - rust.git/commitdiff
Fix rename trying to edit the same range multiple times
authorLukas Wirth <lukastw97@gmail.com>
Sat, 2 Oct 2021 16:50:21 +0000 (18:50 +0200)
committerLukas Wirth <lukastw97@gmail.com>
Sat, 2 Oct 2021 16:50:21 +0000 (18:50 +0200)
crates/ide/src/rename.rs
crates/ide_db/src/rename.rs

index a495e6c5432d93842ed2e6c0a0ed14d223422d2e..cce342272f78722c2591eb81459f9f3c60f72bb6 100644 (file)
@@ -1899,6 +1899,51 @@ fn func$0() {
 fn function() {
     function();
 }
+"#,
+        )
+    }
+
+    #[test]
+    fn in_macro_multi_mapping() {
+        check(
+            "a",
+            r#"
+fn foo() {
+    macro_rules! match_ast2 {
+        ($node:ident {
+            $( $res:expr, )*
+        }) => {{
+            $( if $node { $res } else )*
+            { loop {} }
+        }};
+    }
+    let $0d = 3;
+    match_ast2! {
+        d {
+            d,
+            d,
+        }
+    };
+}
+"#,
+            r#"
+fn foo() {
+    macro_rules! match_ast2 {
+        ($node:ident {
+            $( $res:expr, )*
+        }) => {{
+            $( if $node { $res } else )*
+            { loop {} }
+        }};
+    }
+    let a = 3;
+    match_ast2! {
+        a {
+            a,
+            a,
+        }
+    };
+}
 "#,
         )
     }
index 0ca0dc8c6b1b4e49257a313dcf70955a3252f43b..fcf1a654b044d5b307592bfd4c357d513a5ea495 100644 (file)
@@ -291,23 +291,26 @@ pub fn source_edit_from_references(
     new_name: &str,
 ) -> TextEdit {
     let mut edit = TextEdit::builder();
-    for reference in references {
-        let has_emitted_edit = match &reference.name {
+    // macros can cause multiple refs to occur for the same text range, so keep track of what we have edited so far
+    let mut edited_ranges = Vec::new();
+    for &FileReference { range, ref name, .. } in references {
+        let has_emitted_edit = match name {
             // if the ranges differ then the node is inside a macro call, we can't really attempt
             // to make special rewrites like shorthand syntax and such, so just rename the node in
             // the macro input
-            ast::NameLike::NameRef(name_ref)
-                if name_ref.syntax().text_range() == reference.range =>
-            {
+            ast::NameLike::NameRef(name_ref) if name_ref.syntax().text_range() == range => {
                 source_edit_from_name_ref(&mut edit, name_ref, new_name, def)
             }
-            ast::NameLike::Name(name) if name.syntax().text_range() == reference.range => {
+            ast::NameLike::Name(name) if name.syntax().text_range() == range => {
                 source_edit_from_name(&mut edit, name, new_name)
             }
             _ => false,
         };
         if !has_emitted_edit {
-            edit.replace(reference.range, new_name.to_string());
+            if !edited_ranges.contains(&range.start()) {
+                edit.replace(range, new_name.to_string());
+                edited_ranges.push(range.start());
+            }
         }
     }