Unnamed repository; edit this file 'description' to name the repository.
Fix rename trying to edit the same range multiple times
Lukas Wirth 2021-10-02
parent 745fd99 · commit 86e5406
-rw-r--r--crates/ide/src/rename.rs45
-rw-r--r--crates/ide_db/src/rename.rs17
2 files changed, 55 insertions, 7 deletions
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index a495e6c543..cce342272f 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -1902,4 +1902,49 @@ fn 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,
+ }
+ };
+}
+"#,
+ )
+ }
}
diff --git a/crates/ide_db/src/rename.rs b/crates/ide_db/src/rename.rs
index 0ca0dc8c6b..fcf1a654b0 100644
--- a/crates/ide_db/src/rename.rs
+++ b/crates/ide_db/src/rename.rs
@@ -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());
+ }
}
}