about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAnatol Ulrich <anatol.ulrich@ferrous-systems.com>2021-10-26 19:31:49 +0200
committerAnatol Ulrich <anatol.ulrich@ferrous-systems.com>2021-10-26 19:31:49 +0200
commitd8ed15b6a67bb4dd04ebc6548253b9eb553ad023 (patch)
tree8795a66683c819989b802823ef5eff388b736a89
parentee1d6cffbfbecc99a70be77fe697af817ed6cfac (diff)
downloadrust-d8ed15b6a67bb4dd04ebc6548253b9eb553ad023.tar.gz
rust-d8ed15b6a67bb4dd04ebc6548253b9eb553ad023.zip
fix: make `goto_declaration` multi-token mapping aware
-rw-r--r--crates/ide/src/goto_declaration.rs51
1 files changed, 29 insertions, 22 deletions
diff --git a/crates/ide/src/goto_declaration.rs b/crates/ide/src/goto_declaration.rs
index 2c5a24b1d2e..c79015c7160 100644
--- a/crates/ide/src/goto_declaration.rs
+++ b/crates/ide/src/goto_declaration.rs
@@ -19,28 +19,35 @@ pub(crate) fn goto_declaration(
     let original_token = file
         .token_at_offset(position.offset)
         .find(|it| matches!(it.kind(), IDENT | T![self] | T![super] | T![crate]))?;
-    let token = sema.descend_into_macros_single(original_token.clone());
-    let parent = token.parent()?;
-    let def = match_ast! {
-        match parent {
-            ast::NameRef(name_ref) => match NameRefClass::classify(&sema, &name_ref)? {
-                NameRefClass::Definition(it) => Some(it),
-                _ => None
-            },
-            ast::Name(name) => match NameClass::classify(&sema, &name)? {
-                NameClass::Definition(it) => Some(it),
-                _ => None
-            },
-            _ => None,
-        }
-    };
-    match def? {
-        Definition::ModuleDef(hir::ModuleDef::Module(module)) => Some(RangeInfo::new(
-            original_token.text_range(),
-            vec![NavigationTarget::from_module_to_decl(db, module)],
-        )),
-        _ => None,
-    }
+    let range = original_token.text_range();
+    let info: Vec<NavigationTarget> = sema
+        .descend_into_macros(original_token)
+        .iter()
+        .filter_map(|token| {
+            let parent = token.parent()?;
+            let def = match_ast! {
+                match parent {
+                    ast::NameRef(name_ref) => match NameRefClass::classify(&sema, &name_ref)? {
+                        NameRefClass::Definition(it) => Some(it),
+                        _ => None
+                    },
+                    ast::Name(name) => match NameClass::classify(&sema, &name)? {
+                        NameClass::Definition(it) => Some(it),
+                        _ => None
+                    },
+                    _ => None
+                }
+            };
+            match def? {
+                Definition::ModuleDef(hir::ModuleDef::Module(module)) => {
+                    Some(NavigationTarget::from_module_to_decl(db, module))
+                }
+                _ => None,
+            }
+        })
+        .collect();
+
+    Some(RangeInfo::new(range, info))
 }
 
 #[cfg(test)]