diff options
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r-- | crates/ra_ide_api/src/goto_type_definition.rs | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/crates/ra_ide_api/src/goto_type_definition.rs b/crates/ra_ide_api/src/goto_type_definition.rs index 2327cb1e7..7d694e1f6 100644 --- a/crates/ra_ide_api/src/goto_type_definition.rs +++ b/crates/ra_ide_api/src/goto_type_definition.rs | |||
@@ -1,25 +1,28 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use ra_db::SourceDatabase; | 3 | use hir::db::AstDatabase; |
4 | use ra_syntax::{ast, AstNode}; | 4 | use ra_syntax::{ast, AstNode}; |
5 | 5 | ||
6 | use crate::{db::RootDatabase, display::ToNav, FilePosition, NavigationTarget, RangeInfo}; | 6 | use crate::{ |
7 | db::RootDatabase, display::ToNav, expand::descend_into_macros, FilePosition, NavigationTarget, | ||
8 | RangeInfo, | ||
9 | }; | ||
7 | 10 | ||
8 | pub(crate) fn goto_type_definition( | 11 | pub(crate) fn goto_type_definition( |
9 | db: &RootDatabase, | 12 | db: &RootDatabase, |
10 | position: FilePosition, | 13 | position: FilePosition, |
11 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { | 14 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { |
12 | let parse = db.parse(position.file_id); | 15 | let file = db.parse_or_expand(position.file_id.into())?; |
16 | let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?; | ||
17 | let token = descend_into_macros(db, position.file_id, token); | ||
13 | 18 | ||
14 | let node = parse.tree().syntax().token_at_offset(position.offset).find_map(|token| { | 19 | let node = token.ast.ancestors().find_map(|token| { |
15 | token | 20 | token |
16 | .parent() | ||
17 | .ancestors() | 21 | .ancestors() |
18 | .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()) | 22 | .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()) |
19 | })?; | 23 | })?; |
20 | 24 | ||
21 | let analyzer = | 25 | let analyzer = hir::SourceAnalyzer::new(db, token.with_ast(&node), None); |
22 | hir::SourceAnalyzer::new(db, hir::Source::new(position.file_id.into(), &node), None); | ||
23 | 26 | ||
24 | let ty: hir::Ty = if let Some(ty) = | 27 | let ty: hir::Ty = if let Some(ty) = |
25 | ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) | 28 | ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) |
@@ -80,4 +83,23 @@ mod tests { | |||
80 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", | 83 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", |
81 | ); | 84 | ); |
82 | } | 85 | } |
86 | |||
87 | #[test] | ||
88 | fn goto_type_definition_works_through_macro() { | ||
89 | check_goto( | ||
90 | " | ||
91 | //- /lib.rs | ||
92 | macro_rules! id { | ||
93 | ($($tt:tt)*) => { $($tt)* } | ||
94 | } | ||
95 | struct Foo {} | ||
96 | id! { | ||
97 | fn bar() { | ||
98 | let f<|> = Foo {}; | ||
99 | } | ||
100 | } | ||
101 | ", | ||
102 | "Foo STRUCT_DEF FileId(1) [52; 65) [59; 62)", | ||
103 | ); | ||
104 | } | ||
83 | } | 105 | } |