aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkjeremy <[email protected]>2019-11-18 19:57:42 +0000
committerkjeremy <[email protected]>2019-11-18 19:57:42 +0000
commite939f740b3b2223d61d8af2dd2fc3517077083b0 (patch)
tree27a4fdf87eae44030721afcf927779690985ed37
parent7614439033bc8b68d3982d93595161ddfda80837 (diff)
Goto type def through macros
-rw-r--r--crates/ra_ide_api/src/goto_type_definition.rs36
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
3use ra_db::SourceDatabase; 3use hir::db::AstDatabase;
4use ra_syntax::{ast, AstNode}; 4use ra_syntax::{ast, AstNode};
5 5
6use crate::{db::RootDatabase, display::ToNav, FilePosition, NavigationTarget, RangeInfo}; 6use crate::{
7 db::RootDatabase, display::ToNav, expand::descend_into_macros, FilePosition, NavigationTarget,
8 RangeInfo,
9};
7 10
8pub(crate) fn goto_type_definition( 11pub(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}