aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs31
1 files changed, 20 insertions, 11 deletions
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 4b1581499..70baa294f 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -1,5 +1,7 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::iter::successors;
4
3use hir::{db::AstDatabase, Source}; 5use hir::{db::AstDatabase, Source};
4use ra_syntax::{ 6use ra_syntax::{
5 algo::find_node_at_offset, 7 algo::find_node_at_offset,
@@ -18,10 +20,8 @@ pub(crate) fn goto_definition(
18 db: &RootDatabase, 20 db: &RootDatabase,
19 position: FilePosition, 21 position: FilePosition,
20) -> Option<RangeInfo<Vec<NavigationTarget>>> { 22) -> Option<RangeInfo<Vec<NavigationTarget>>> {
21 go(db, Source::new(position.file_id.into(), position.offset)) 23 let offset = descend_into_macros(db, position);
22}
23 24
24fn go(db: &RootDatabase, offset: Source<TextUnit>) -> Option<RangeInfo<Vec<NavigationTarget>>> {
25 let syntax = db.parse_or_expand(offset.file_id)?; 25 let syntax = db.parse_or_expand(offset.file_id)?;
26 26
27 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&syntax, offset.ast) { 27 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&syntax, offset.ast) {
@@ -32,16 +32,25 @@ fn go(db: &RootDatabase, offset: Source<TextUnit>) -> Option<RangeInfo<Vec<Navig
32 let navs = name_definition(db, offset.with_ast(&name))?; 32 let navs = name_definition(db, offset.with_ast(&name))?;
33 return Some(RangeInfo::new(name.syntax().text_range(), navs)); 33 return Some(RangeInfo::new(name.syntax().text_range(), navs));
34 } 34 }
35 if let Some(macro_call) = find_node_at_offset::<ast::MacroCall>(&syntax, offset.ast) { 35 None
36}
37
38fn descend_into_macros(db: &RootDatabase, position: FilePosition) -> Source<TextUnit> {
39 successors(Some(Source::new(position.file_id.into(), position.offset)), |offset| {
40 let syntax = db.parse_or_expand(offset.file_id)?;
41 let macro_call = find_node_at_offset::<ast::MacroCall>(&syntax, offset.ast)?;
42 let tt = macro_call.token_tree()?;
43 if !tt.syntax().text_range().contains(offset.ast) {
44 return None;
45 }
36 let source_analyzer = 46 let source_analyzer =
37 hir::SourceAnalyzer::new(db, offset.with_ast(macro_call.syntax()), None); 47 hir::SourceAnalyzer::new(db, offset.with_ast(macro_call.syntax()), None);
38 if let Some(exp) = source_analyzer.expand(db, &macro_call) { 48 let exp = source_analyzer.expand(db, &macro_call)?;
39 if let Some(offset) = exp.translate_offset(db, offset.ast) { 49 let next_offset = exp.translate_offset(db, offset.ast)?;
40 return go(db, Source::new(exp.file_id(), offset)); 50 Some(Source::new(exp.file_id(), next_offset))
41 } 51 })
42 } 52 .last()
43 } 53 .unwrap()
44 None
45} 54}
46 55
47#[derive(Debug)] 56#[derive(Debug)]