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.rs48
1 files changed, 26 insertions, 22 deletions
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 70baa294f..b693a4c31 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -4,9 +4,8 @@ use std::iter::successors;
4 4
5use hir::{db::AstDatabase, Source}; 5use hir::{db::AstDatabase, Source};
6use ra_syntax::{ 6use ra_syntax::{
7 algo::find_node_at_offset,
8 ast::{self, DocCommentsOwner}, 7 ast::{self, DocCommentsOwner},
9 match_ast, AstNode, SyntaxNode, TextUnit, 8 match_ast, AstNode, SyntaxNode, SyntaxToken,
10}; 9};
11 10
12use crate::{ 11use crate::{
@@ -20,37 +19,42 @@ pub(crate) fn goto_definition(
20 db: &RootDatabase, 19 db: &RootDatabase,
21 position: FilePosition, 20 position: FilePosition,
22) -> Option<RangeInfo<Vec<NavigationTarget>>> { 21) -> Option<RangeInfo<Vec<NavigationTarget>>> {
23 let offset = descend_into_macros(db, position); 22 let token = descend_into_macros(db, position)?;
24 23
25 let syntax = db.parse_or_expand(offset.file_id)?; 24 let res = match_ast! {
25 match (token.ast.parent()) {
26 ast::NameRef(name_ref) => {
27 let navs = reference_definition(db, token.with_ast(&name_ref)).to_vec();
28 RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec())
29 },
30 ast::Name(name) => {
31 let navs = name_definition(db, token.with_ast(&name))?;
32 RangeInfo::new(name.syntax().text_range(), navs)
26 33
27 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&syntax, offset.ast) { 34 },
28 let navs = reference_definition(db, offset.with_ast(&name_ref)).to_vec(); 35 _ => return None,
29 return Some(RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec())); 36 }
30 } 37 };
31 if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, offset.ast) { 38
32 let navs = name_definition(db, offset.with_ast(&name))?; 39 Some(res)
33 return Some(RangeInfo::new(name.syntax().text_range(), navs));
34 }
35 None
36} 40}
37 41
38fn descend_into_macros(db: &RootDatabase, position: FilePosition) -> Source<TextUnit> { 42fn descend_into_macros(db: &RootDatabase, position: FilePosition) -> Option<Source<SyntaxToken>> {
39 successors(Some(Source::new(position.file_id.into(), position.offset)), |offset| { 43 let file = db.parse_or_expand(position.file_id.into())?;
40 let syntax = db.parse_or_expand(offset.file_id)?; 44 let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?;
41 let macro_call = find_node_at_offset::<ast::MacroCall>(&syntax, offset.ast)?; 45
46 successors(Some(Source::new(position.file_id.into(), token)), |token| {
47 let macro_call = token.ast.ancestors().find_map(ast::MacroCall::cast)?;
42 let tt = macro_call.token_tree()?; 48 let tt = macro_call.token_tree()?;
43 if !tt.syntax().text_range().contains(offset.ast) { 49 if !token.ast.text_range().is_subrange(&tt.syntax().text_range()) {
44 return None; 50 return None;
45 } 51 }
46 let source_analyzer = 52 let source_analyzer =
47 hir::SourceAnalyzer::new(db, offset.with_ast(macro_call.syntax()), None); 53 hir::SourceAnalyzer::new(db, token.with_ast(token.ast.parent()).as_ref(), None);
48 let exp = source_analyzer.expand(db, &macro_call)?; 54 let exp = source_analyzer.expand(db, &macro_call)?;
49 let next_offset = exp.translate_offset(db, offset.ast)?; 55 exp.map_token_down(db, token.as_ref())
50 Some(Source::new(exp.file_id(), next_offset))
51 }) 56 })
52 .last() 57 .last()
53 .unwrap()
54} 58}
55 59
56#[derive(Debug)] 60#[derive(Debug)]