about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEdwin Cheng <edwin0cheng@gmail.com>2020-02-09 17:17:56 +0800
committerEdwin Cheng <edwin0cheng@gmail.com>2020-02-09 17:17:56 +0800
commitdd0421e587bf312bd79eb98c821e0be437f6b361 (patch)
treef6ea75230ca12ba8d18666b62f3f1bf451df5af2
parent3e1d97790be166f8735607c552a94a28ab9b09b8 (diff)
downloadrust-dd0421e587bf312bd79eb98c821e0be437f6b361.tar.gz
rust-dd0421e587bf312bd79eb98c821e0be437f6b361.zip
Handle macro token cases for rename
-rw-r--r--crates/ra_ide/src/references.rs75
-rw-r--r--crates/ra_ide/src/references/rename.rs19
2 files changed, 69 insertions, 25 deletions
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs
index a6320bd2f57..bc241fb5a5d 100644
--- a/crates/ra_ide/src/references.rs
+++ b/crates/ra_ide/src/references.rs
@@ -13,6 +13,7 @@ mod classify;
 mod rename;
 mod search_scope;
 
+use crate::expand::descend_into_macros_with_analyzer;
 use hir::{InFile, SourceBinder};
 use once_cell::unsync::Lazy;
 use ra_db::{SourceDatabase, SourceDatabaseExt};
@@ -192,39 +193,63 @@ fn process_definition(
 
         let parse = Lazy::new(|| SourceFile::parse(&text));
         let mut sb = Lazy::new(|| SourceBinder::new(db));
+        let mut analyzer = None;
 
         for (idx, _) in text.match_indices(pat) {
             let offset = TextUnit::from_usize(idx);
 
-            if let Some(name_ref) =
+            let (name_ref, range) = if let Some(name_ref) =
                 find_node_at_offset::<ast::NameRef>(parse.tree().syntax(), offset)
             {
                 let range = name_ref.syntax().text_range();
-                if let Some(search_range) = search_range {
-                    if !range.is_subrange(&search_range) {
-                        continue;
-                    }
+                (InFile::new(file_id.into(), name_ref), range)
+            } else {
+                // Handle macro token cases
+                let t = match parse.tree().syntax().token_at_offset(offset) {
+                    TokenAtOffset::None => continue,
+                    TokenAtOffset::Single(t) => t,
+                    TokenAtOffset::Between(_, t) => t,
+                };
+                let range = t.text_range();
+                let analyzer = analyzer.get_or_insert(
+                    sb.analyze(InFile::new(file_id.into(), parse.tree().syntax()), None),
+                );
+
+                let expanded = descend_into_macros_with_analyzer(
+                    db,
+                    &analyzer,
+                    InFile::new(file_id.into(), t),
+                );
+                if let Some(token) = ast::NameRef::cast(expanded.value.parent()) {
+                    (expanded.with_value(token), range)
+                } else {
+                    continue;
                 }
-                // FIXME: reuse sb
-                // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098
-
-                if let Some(d) = classify_name_ref(&mut sb, InFile::new(file_id.into(), &name_ref))
-                {
-                    if d == def {
-                        let kind = if is_record_lit_name_ref(&name_ref)
-                            || is_call_expr_name_ref(&name_ref)
-                        {
-                            ReferenceKind::StructLiteral
-                        } else {
-                            ReferenceKind::Other
-                        };
-
-                        refs.push(Reference {
-                            file_range: FileRange { file_id, range },
-                            kind,
-                            access: reference_access(&d.kind, &name_ref),
-                        });
-                    }
+            };
+
+            if let Some(search_range) = search_range {
+                if !range.is_subrange(&search_range) {
+                    continue;
+                }
+            }
+            // FIXME: reuse sb
+            // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098
+
+            if let Some(d) = classify_name_ref(&mut sb, name_ref.as_ref()) {
+                if d == def {
+                    let kind = if is_record_lit_name_ref(&name_ref.value)
+                        || is_call_expr_name_ref(&name_ref.value)
+                    {
+                        ReferenceKind::StructLiteral
+                    } else {
+                        ReferenceKind::Other
+                    };
+
+                    refs.push(Reference {
+                        file_range: FileRange { file_id, range },
+                        kind,
+                        access: reference_access(&d.kind, &name_ref.value),
+                    });
                 }
             }
         }
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs
index 08e77c01fbd..c46b78cb6f6 100644
--- a/crates/ra_ide/src/references/rename.rs
+++ b/crates/ra_ide/src/references/rename.rs
@@ -211,6 +211,25 @@ mod tests {
     }
 
     #[test]
+    fn test_rename_for_macro_args() {
+        test_rename(
+            r#"
+    macro_rules! foo {($i:ident) => {$i} }
+    fn main() {
+        let a<|> = "test";
+        foo!(a);
+    }"#,
+            "b",
+            r#"
+    macro_rules! foo {($i:ident) => {$i} }
+    fn main() {
+        let b = "test";
+        foo!(b);
+    }"#,
+        );
+    }
+
+    #[test]
     fn test_rename_for_param_inside() {
         test_rename(
             r#"