diff options
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 50 |
1 files changed, 40 insertions, 10 deletions
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 821796e5f..4b1581499 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -1,11 +1,10 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::Source; | 3 | use hir::{db::AstDatabase, Source}; |
4 | use ra_db::SourceDatabase; | ||
5 | use ra_syntax::{ | 4 | use ra_syntax::{ |
6 | algo::find_node_at_offset, | 5 | algo::find_node_at_offset, |
7 | ast::{self, DocCommentsOwner}, | 6 | ast::{self, DocCommentsOwner}, |
8 | match_ast, AstNode, SyntaxNode, | 7 | match_ast, AstNode, SyntaxNode, TextUnit, |
9 | }; | 8 | }; |
10 | 9 | ||
11 | use crate::{ | 10 | use crate::{ |
@@ -19,17 +18,29 @@ pub(crate) fn goto_definition( | |||
19 | db: &RootDatabase, | 18 | db: &RootDatabase, |
20 | position: FilePosition, | 19 | position: FilePosition, |
21 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { | 20 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { |
22 | let parse = db.parse(position.file_id); | 21 | go(db, Source::new(position.file_id.into(), position.offset)) |
23 | let syntax = parse.tree().syntax().clone(); | 22 | } |
24 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&syntax, position.offset) { | 23 | |
25 | let navs = | 24 | fn go(db: &RootDatabase, offset: Source<TextUnit>) -> Option<RangeInfo<Vec<NavigationTarget>>> { |
26 | reference_definition(db, Source::new(position.file_id.into(), &name_ref)).to_vec(); | 25 | let syntax = db.parse_or_expand(offset.file_id)?; |
26 | |||
27 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&syntax, offset.ast) { | ||
28 | let navs = reference_definition(db, offset.with_ast(&name_ref)).to_vec(); | ||
27 | return Some(RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec())); | 29 | return Some(RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec())); |
28 | } | 30 | } |
29 | if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, position.offset) { | 31 | if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, offset.ast) { |
30 | let navs = name_definition(db, Source::new(position.file_id.into(), &name))?; | 32 | let navs = name_definition(db, offset.with_ast(&name))?; |
31 | return Some(RangeInfo::new(name.syntax().text_range(), navs)); | 33 | return Some(RangeInfo::new(name.syntax().text_range(), navs)); |
32 | } | 34 | } |
35 | if let Some(macro_call) = find_node_at_offset::<ast::MacroCall>(&syntax, offset.ast) { | ||
36 | let source_analyzer = | ||
37 | hir::SourceAnalyzer::new(db, offset.with_ast(macro_call.syntax()), None); | ||
38 | if let Some(exp) = source_analyzer.expand(db, ¯o_call) { | ||
39 | if let Some(offset) = exp.translate_offset(db, offset.ast) { | ||
40 | return go(db, Source::new(exp.file_id(), offset)); | ||
41 | } | ||
42 | } | ||
43 | } | ||
33 | None | 44 | None |
34 | } | 45 | } |
35 | 46 | ||
@@ -677,4 +688,23 @@ mod tests { | |||
677 | "bar MODULE FileId(1) [0; 11) [4; 7)", | 688 | "bar MODULE FileId(1) [0; 11) [4; 7)", |
678 | ); | 689 | ); |
679 | } | 690 | } |
691 | |||
692 | #[test] | ||
693 | fn goto_from_macro() { | ||
694 | check_goto( | ||
695 | " | ||
696 | //- /lib.rs | ||
697 | macro_rules! id { | ||
698 | ($($tt:tt)*) => { $($tt)* } | ||
699 | } | ||
700 | fn foo() {} | ||
701 | id! { | ||
702 | fn bar() { | ||
703 | fo<|>o(); | ||
704 | } | ||
705 | } | ||
706 | ", | ||
707 | "foo FN_DEF FileId(1) [52; 63) [55; 58)", | ||
708 | ); | ||
709 | } | ||
680 | } | 710 | } |