aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs50
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
3use hir::Source; 3use hir::{db::AstDatabase, Source};
4use ra_db::SourceDatabase;
5use ra_syntax::{ 4use 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
11use crate::{ 10use 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 = 24fn 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, &macro_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}