diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 31 |
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 | ||
3 | use std::iter::successors; | ||
4 | |||
3 | use hir::{db::AstDatabase, Source}; | 5 | use hir::{db::AstDatabase, Source}; |
4 | use ra_syntax::{ | 6 | use 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 | ||
24 | fn 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 | |||
38 | fn 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, ¯o_call) { | 48 | let exp = source_analyzer.expand(db, ¯o_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)] |