aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/goto_definition.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/goto_definition.rs')
-rw-r--r--crates/ide/src/goto_definition.rs95
1 files changed, 30 insertions, 65 deletions
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 988a5668f..1a997fa40 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -2,16 +2,14 @@ use either::Either;
2use hir::{HasAttrs, ModuleDef, Semantics}; 2use hir::{HasAttrs, ModuleDef, Semantics};
3use ide_db::{ 3use ide_db::{
4 defs::{Definition, NameClass, NameRefClass}, 4 defs::{Definition, NameClass, NameRefClass},
5 symbol_index, RootDatabase, 5 RootDatabase,
6}; 6};
7use syntax::{ 7use syntax::{
8 ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextSize, TokenAtOffset, T, 8 ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextSize, TokenAtOffset, T,
9}; 9};
10 10
11use crate::{ 11use crate::{
12 display::{ToNav, TryToNav}, 12 display::TryToNav, doc_links::extract_definitions_from_markdown, runnables::doc_owner_to_def,
13 doc_links::extract_definitions_from_markdown,
14 runnables::doc_owner_to_def,
15 FilePosition, NavigationTarget, RangeInfo, 13 FilePosition, NavigationTarget, RangeInfo,
16}; 14};
17 15
@@ -38,33 +36,26 @@ pub(crate) fn goto_definition(
38 return Some(RangeInfo::new(original_token.text_range(), vec![nav])); 36 return Some(RangeInfo::new(original_token.text_range(), vec![nav]));
39 } 37 }
40 38
41 let nav_targets = match_ast! { 39 let nav = match_ast! {
42 match parent { 40 match parent {
43 ast::NameRef(name_ref) => { 41 ast::NameRef(name_ref) => {
44 reference_definition(&sema, Either::Right(&name_ref)).to_vec() 42 reference_definition(&sema, Either::Right(&name_ref))
45 }, 43 },
46 ast::Name(name) => { 44 ast::Name(name) => {
47 let def = NameClass::classify(&sema, &name)?.referenced_or_defined(sema.db); 45 let def = NameClass::classify(&sema, &name)?.referenced_or_defined(sema.db);
48 let nav = def.try_to_nav(sema.db)?; 46 def.try_to_nav(sema.db)
49 vec![nav]
50 }, 47 },
51 ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) { 48 ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) {
52 let def = name_class.referenced_or_defined(sema.db); 49 let def = name_class.referenced_or_defined(sema.db);
53 let nav = def.try_to_nav(sema.db)?; 50 def.try_to_nav(sema.db)
54 vec![nav]
55 } else { 51 } else {
56 reference_definition(&sema, Either::Left(&lt)).to_vec() 52 reference_definition(&sema, Either::Left(&lt))
57 },
58 ast::SelfParam(self_param) => {
59 let def = NameClass::classify_self_param(&sema, &self_param)?.referenced_or_defined(sema.db);
60 let nav = def.try_to_nav(sema.db)?;
61 vec![nav]
62 }, 53 },
63 _ => return None, 54 _ => return None,
64 } 55 }
65 }; 56 };
66 57
67 Some(RangeInfo::new(original_token.text_range(), nav_targets)) 58 Some(RangeInfo::new(original_token.text_range(), nav.into_iter().collect()))
68} 59}
69 60
70fn def_for_doc_comment( 61fn def_for_doc_comment(
@@ -125,42 +116,16 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
125 } 116 }
126} 117}
127 118
128#[derive(Debug)]
129pub(crate) enum ReferenceResult {
130 Exact(NavigationTarget),
131 Approximate(Vec<NavigationTarget>),
132}
133
134impl ReferenceResult {
135 fn to_vec(self) -> Vec<NavigationTarget> {
136 match self {
137 ReferenceResult::Exact(target) => vec![target],
138 ReferenceResult::Approximate(vec) => vec,
139 }
140 }
141}
142
143pub(crate) fn reference_definition( 119pub(crate) fn reference_definition(
144 sema: &Semantics<RootDatabase>, 120 sema: &Semantics<RootDatabase>,
145 name_ref: Either<&ast::Lifetime, &ast::NameRef>, 121 name_ref: Either<&ast::Lifetime, &ast::NameRef>,
146) -> ReferenceResult { 122) -> Option<NavigationTarget> {
147 let name_kind = name_ref.either( 123 let name_kind = name_ref.either(
148 |lifetime| NameRefClass::classify_lifetime(sema, lifetime), 124 |lifetime| NameRefClass::classify_lifetime(sema, lifetime),
149 |name_ref| NameRefClass::classify(sema, name_ref), 125 |name_ref| NameRefClass::classify(sema, name_ref),
150 ); 126 )?;
151 if let Some(def) = name_kind { 127 let def = name_kind.referenced(sema.db);
152 let def = def.referenced(sema.db); 128 def.try_to_nav(sema.db)
153 return match def.try_to_nav(sema.db) {
154 Some(nav) => ReferenceResult::Exact(nav),
155 None => ReferenceResult::Approximate(Vec::new()),
156 };
157 }
158
159 // Fallback index based approach:
160 let name = name_ref.either(ast::Lifetime::text, ast::NameRef::text);
161 let navs =
162 symbol_index::index_resolve(sema.db, name).into_iter().map(|s| s.to_nav(sema.db)).collect();
163 ReferenceResult::Approximate(navs)
164} 129}
165 130
166#[cfg(test)] 131#[cfg(test)]
@@ -197,12 +162,12 @@ mod tests {
197 fn goto_def_for_extern_crate() { 162 fn goto_def_for_extern_crate() {
198 check( 163 check(
199 r#" 164 r#"
200 //- /main.rs crate:main deps:std 165//- /main.rs crate:main deps:std
201 extern crate std$0; 166extern crate std$0;
202 //- /std/lib.rs crate:std 167//- /std/lib.rs crate:std
203 // empty 168// empty
204 //^ file 169//^ file
205 "#, 170"#,
206 ) 171 )
207 } 172 }
208 173
@@ -210,12 +175,12 @@ mod tests {
210 fn goto_def_for_renamed_extern_crate() { 175 fn goto_def_for_renamed_extern_crate() {
211 check( 176 check(
212 r#" 177 r#"
213 //- /main.rs crate:main deps:std 178//- /main.rs crate:main deps:std
214 extern crate std as abc$0; 179extern crate std as abc$0;
215 //- /std/lib.rs crate:std 180//- /std/lib.rs crate:std
216 // empty 181// empty
217 //^ file 182//^ file
218 "#, 183"#,
219 ) 184 )
220 } 185 }
221 186
@@ -302,13 +267,13 @@ fn bar() {
302 fn goto_def_for_macros_from_other_crates() { 267 fn goto_def_for_macros_from_other_crates() {
303 check( 268 check(
304 r#" 269 r#"
305//- /lib.rs 270//- /lib.rs crate:main deps:foo
306use foo::foo; 271use foo::foo;
307fn bar() { 272fn bar() {
308 $0foo!(); 273 $0foo!();
309} 274}
310 275
311//- /foo/lib.rs 276//- /foo/lib.rs crate:foo
312#[macro_export] 277#[macro_export]
313macro_rules! foo { () => { () } } 278macro_rules! foo { () => { () } }
314 //^^^ 279 //^^^
@@ -320,10 +285,10 @@ macro_rules! foo { () => { () } }
320 fn goto_def_for_macros_in_use_tree() { 285 fn goto_def_for_macros_in_use_tree() {
321 check( 286 check(
322 r#" 287 r#"
323//- /lib.rs 288//- /lib.rs crate:main deps:foo
324use foo::foo$0; 289use foo::foo$0;
325 290
326//- /foo/lib.rs 291//- /foo/lib.rs crate:foo
327#[macro_export] 292#[macro_export]
328macro_rules! foo { () => { () } } 293macro_rules! foo { () => { () } }
329 //^^^ 294 //^^^
@@ -981,10 +946,10 @@ type Alias<T> = T$0;
981 fn goto_def_for_macro_container() { 946 fn goto_def_for_macro_container() {
982 check( 947 check(
983 r#" 948 r#"
984//- /lib.rs 949//- /lib.rs crate:main deps:foo
985foo::module$0::mac!(); 950foo::module$0::mac!();
986 951
987//- /foo/lib.rs 952//- /foo/lib.rs crate:foo
988pub mod module { 953pub mod module {
989 //^^^^^^ 954 //^^^^^^
990 #[macro_export] 955 #[macro_export]