aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-07-10 13:47:23 +0100
committerGitHub <[email protected]>2020-07-10 13:47:23 +0100
commit0f7770ae43dd0d97686eb85fccb38801ff30117b (patch)
tree754d726b02595db4dcc4594712e30ca97a336988 /crates/ra_ide/src
parent5fa8f8e3761363098c80e11842682dffcee171d8 (diff)
parent075380dd56439cdaf1967b7298e10b96b995fc07 (diff)
Merge #5292
5292: Goto type definition improvements r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r--crates/ra_ide/src/goto_definition.rs10
-rw-r--r--crates/ra_ide/src/goto_type_definition.rs132
2 files changed, 76 insertions, 66 deletions
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs
index 4c78fa214..8fc33d031 100644
--- a/crates/ra_ide/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -7,7 +7,7 @@ use ra_syntax::{
7 ast::{self}, 7 ast::{self},
8 match_ast, AstNode, 8 match_ast, AstNode,
9 SyntaxKind::*, 9 SyntaxKind::*,
10 SyntaxToken, TokenAtOffset, 10 SyntaxToken, TokenAtOffset, T,
11}; 11};
12 12
13use crate::{ 13use crate::{
@@ -32,9 +32,10 @@ pub(crate) fn goto_definition(
32 let file = sema.parse(position.file_id).syntax().clone(); 32 let file = sema.parse(position.file_id).syntax().clone();
33 let original_token = pick_best(file.token_at_offset(position.offset))?; 33 let original_token = pick_best(file.token_at_offset(position.offset))?;
34 let token = sema.descend_into_macros(original_token.clone()); 34 let token = sema.descend_into_macros(original_token.clone());
35 let parent = token.parent();
35 36
36 let nav_targets = match_ast! { 37 let nav_targets = match_ast! {
37 match (token.parent()) { 38 match parent {
38 ast::NameRef(name_ref) => { 39 ast::NameRef(name_ref) => {
39 reference_definition(&sema, &name_ref).to_vec() 40 reference_definition(&sema, &name_ref).to_vec()
40 }, 41 },
@@ -57,7 +58,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
57 return tokens.max_by_key(priority); 58 return tokens.max_by_key(priority);
58 fn priority(n: &SyntaxToken) -> usize { 59 fn priority(n: &SyntaxToken) -> usize {
59 match n.kind() { 60 match n.kind() {
60 IDENT | INT_NUMBER => 2, 61 IDENT | INT_NUMBER | T![self] => 2,
61 kind if kind.is_trivia() => 0, 62 kind if kind.is_trivia() => 0,
62 _ => 1, 63 _ => 1,
63 } 64 }
@@ -121,7 +122,8 @@ mod tests {
121 data => panic!("bad data: {}", data), 122 data => panic!("bad data: {}", data),
122 } 123 }
123 124
124 let mut navs = analysis.goto_definition(position).unwrap().unwrap().info; 125 let mut navs =
126 analysis.goto_definition(position).unwrap().expect("no definition found").info;
125 if navs.len() == 0 { 127 if navs.len() == 0 {
126 panic!("unresolved reference") 128 panic!("unresolved reference")
127 } 129 }
diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs
index 7eb40d637..069cb283e 100644
--- a/crates/ra_ide/src/goto_type_definition.rs
+++ b/crates/ra_ide/src/goto_type_definition.rs
@@ -1,5 +1,5 @@
1use ra_ide_db::RootDatabase; 1use ra_ide_db::RootDatabase;
2use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; 2use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
3 3
4use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; 4use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo};
5 5
@@ -25,8 +25,9 @@ pub(crate) fn goto_type_definition(
25 let (ty, node) = sema.ancestors_with_macros(token.parent()).find_map(|node| { 25 let (ty, node) = sema.ancestors_with_macros(token.parent()).find_map(|node| {
26 let ty = match_ast! { 26 let ty = match_ast! {
27 match node { 27 match node {
28 ast::Expr(expr) => sema.type_of_expr(&expr)?, 28 ast::Expr(it) => sema.type_of_expr(&it)?,
29 ast::Pat(pat) => sema.type_of_pat(&pat)?, 29 ast::Pat(it) => sema.type_of_pat(&it)?,
30 ast::SelfParam(it) => sema.type_of_self(&it)?,
30 _ => return None, 31 _ => return None,
31 } 32 }
32 }; 33 };
@@ -34,7 +35,7 @@ pub(crate) fn goto_type_definition(
34 Some((ty, node)) 35 Some((ty, node))
35 })?; 36 })?;
36 37
37 let adt_def = ty.autoderef(db).find_map(|ty| ty.as_adt())?; 38 let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?;
38 39
39 let nav = adt_def.to_nav(db); 40 let nav = adt_def.to_nav(db);
40 Some(RangeInfo::new(node.text_range(), vec![nav])) 41 Some(RangeInfo::new(node.text_range(), vec![nav]))
@@ -44,7 +45,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
44 return tokens.max_by_key(priority); 45 return tokens.max_by_key(priority);
45 fn priority(n: &SyntaxToken) -> usize { 46 fn priority(n: &SyntaxToken) -> usize {
46 match n.kind() { 47 match n.kind() {
47 IDENT | INT_NUMBER => 2, 48 IDENT | INT_NUMBER | T![self] => 2,
48 kind if kind.is_trivia() => 0, 49 kind if kind.is_trivia() => 0,
49 _ => 1, 50 _ => 1,
50 } 51 }
@@ -53,91 +54,98 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
53 54
54#[cfg(test)] 55#[cfg(test)]
55mod tests { 56mod tests {
56 use crate::mock_analysis::analysis_and_position; 57 use ra_db::FileRange;
57 58
58 fn check_goto(ra_fixture: &str, expected: &str) { 59 use crate::mock_analysis::MockAnalysis;
59 let (analysis, pos) = analysis_and_position(ra_fixture);
60 60
61 let mut navs = analysis.goto_type_definition(pos).unwrap().unwrap().info; 61 fn check(ra_fixture: &str) {
62 let (mock, position) = MockAnalysis::with_files_and_position(ra_fixture);
63 let (expected, data) = mock.annotation();
64 assert!(data.is_empty());
65 let analysis = mock.analysis();
66
67 let mut navs = analysis.goto_type_definition(position).unwrap().unwrap().info;
62 assert_eq!(navs.len(), 1); 68 assert_eq!(navs.len(), 1);
63 let nav = navs.pop().unwrap(); 69 let nav = navs.pop().unwrap();
64 nav.assert_match(expected); 70 assert_eq!(expected, FileRange { file_id: nav.file_id(), range: nav.range() });
65 } 71 }
66 72
67 #[test] 73 #[test]
68 fn goto_type_definition_works_simple() { 74 fn goto_type_definition_works_simple() {
69 check_goto( 75 check(
70 r" 76 r#"
71 //- /lib.rs 77struct Foo;
72 struct Foo; 78 //^^^
73 fn foo() { 79fn foo() {
74 let f: Foo; 80 let f: Foo; f<|>
75 f<|> 81}
76 } 82"#,
77 ",
78 "Foo STRUCT_DEF FileId(1) 0..11 7..10",
79 ); 83 );
80 } 84 }
81 85
82 #[test] 86 #[test]
83 fn goto_type_definition_works_simple_ref() { 87 fn goto_type_definition_works_simple_ref() {
84 check_goto( 88 check(
85 r" 89 r#"
86 //- /lib.rs 90struct Foo;
87 struct Foo; 91 //^^^
88 fn foo() { 92fn foo() {
89 let f: &Foo; 93 let f: &Foo; f<|>
90 f<|> 94}
91 } 95"#,
92 ",
93 "Foo STRUCT_DEF FileId(1) 0..11 7..10",
94 ); 96 );
95 } 97 }
96 98
97 #[test] 99 #[test]
98 fn goto_type_definition_works_through_macro() { 100 fn goto_type_definition_works_through_macro() {
99 check_goto( 101 check(
100 r" 102 r#"
101 //- /lib.rs 103macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
102 macro_rules! id { 104struct Foo {}
103 ($($tt:tt)*) => { $($tt)* } 105 //^^^
104 } 106id! {
105 struct Foo {} 107 fn bar() { let f<|> = Foo {}; }
106 id! { 108}
107 fn bar() { 109"#,
108 let f<|> = Foo {};
109 }
110 }
111 ",
112 "Foo STRUCT_DEF FileId(1) 52..65 59..62",
113 ); 110 );
114 } 111 }
115 112
116 #[test] 113 #[test]
117 fn goto_type_definition_for_param() { 114 fn goto_type_definition_for_param() {
118 check_goto( 115 check(
119 r" 116 r#"
120 //- /lib.rs 117struct Foo;
121 struct Foo; 118 //^^^
122 fn foo(<|>f: Foo) {} 119fn foo(<|>f: Foo) {}
123 ", 120"#,
124 "Foo STRUCT_DEF FileId(1) 0..11 7..10",
125 ); 121 );
126 } 122 }
127 123
128 #[test] 124 #[test]
129 fn goto_type_definition_for_tuple_field() { 125 fn goto_type_definition_for_tuple_field() {
130 check_goto( 126 check(
131 r" 127 r#"
132 //- /lib.rs 128struct Foo;
133 struct Foo; 129 //^^^
134 struct Bar(Foo); 130struct Bar(Foo);
135 fn foo() { 131fn foo() {
136 let bar = Bar(Foo); 132 let bar = Bar(Foo);
137 bar.<|>0; 133 bar.<|>0;
138 } 134}
139 ", 135"#,
140 "Foo STRUCT_DEF FileId(1) 0..11 7..10",
141 ); 136 );
142 } 137 }
138
139 #[test]
140 fn goto_def_for_self_param() {
141 check(
142 r#"
143struct Foo;
144 //^^^
145impl Foo {
146 fn f(&self<|>) {}
147}
148"#,
149 )
150 }
143} 151}