diff options
Diffstat (limited to 'crates/ra_ide/src/goto_type_definition.rs')
-rw-r--r-- | crates/ra_ide/src/goto_type_definition.rs | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs index 992a08809..ce8b6c72a 100644 --- a/crates/ra_ide/src/goto_type_definition.rs +++ b/crates/ra_ide/src/goto_type_definition.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::db::AstDatabase; | 3 | use hir::db::AstDatabase; |
4 | use ra_syntax::{ast, AstNode}; | 4 | use ra_syntax::{ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | db::RootDatabase, display::ToNav, expand::descend_into_macros, FilePosition, NavigationTarget, | 7 | db::RootDatabase, display::ToNav, expand::descend_into_macros, FilePosition, NavigationTarget, |
@@ -13,7 +13,7 @@ pub(crate) fn goto_type_definition( | |||
13 | position: FilePosition, | 13 | position: FilePosition, |
14 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { | 14 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { |
15 | let file = db.parse_or_expand(position.file_id.into())?; | 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()?; | 16 | let token = pick_best(file.token_at_offset(position.offset))?; |
17 | let token = descend_into_macros(db, position.file_id, token); | 17 | let token = descend_into_macros(db, position.file_id, token); |
18 | 18 | ||
19 | let node = token.value.ancestors().find_map(|token| { | 19 | let node = token.value.ancestors().find_map(|token| { |
@@ -41,6 +41,17 @@ pub(crate) fn goto_type_definition( | |||
41 | Some(RangeInfo::new(node.text_range(), vec![nav])) | 41 | Some(RangeInfo::new(node.text_range(), vec![nav])) |
42 | } | 42 | } |
43 | 43 | ||
44 | fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | ||
45 | return tokens.max_by_key(priority); | ||
46 | fn priority(n: &SyntaxToken) -> usize { | ||
47 | match n.kind() { | ||
48 | IDENT | INT_NUMBER => 2, | ||
49 | kind if kind.is_trivia() => 0, | ||
50 | _ => 1, | ||
51 | } | ||
52 | } | ||
53 | } | ||
54 | |||
44 | #[cfg(test)] | 55 | #[cfg(test)] |
45 | mod tests { | 56 | mod tests { |
46 | use crate::mock_analysis::analysis_and_position; | 57 | use crate::mock_analysis::analysis_and_position; |
@@ -102,4 +113,32 @@ mod tests { | |||
102 | "Foo STRUCT_DEF FileId(1) [52; 65) [59; 62)", | 113 | "Foo STRUCT_DEF FileId(1) [52; 65) [59; 62)", |
103 | ); | 114 | ); |
104 | } | 115 | } |
116 | |||
117 | #[test] | ||
118 | fn goto_type_definition_for_param() { | ||
119 | check_goto( | ||
120 | " | ||
121 | //- /lib.rs | ||
122 | struct Foo; | ||
123 | fn foo(<|>f: Foo) {} | ||
124 | ", | ||
125 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", | ||
126 | ); | ||
127 | } | ||
128 | |||
129 | #[test] | ||
130 | fn goto_type_definition_for_tuple_field() { | ||
131 | check_goto( | ||
132 | " | ||
133 | //- /lib.rs | ||
134 | struct Foo; | ||
135 | struct Bar(Foo); | ||
136 | fn foo() { | ||
137 | let bar = Bar(Foo); | ||
138 | bar.<|>0; | ||
139 | } | ||
140 | ", | ||
141 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", | ||
142 | ); | ||
143 | } | ||
105 | } | 144 | } |