aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/goto_definition.rs66
1 files changed, 18 insertions, 48 deletions
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index a1d2bce1d..9c7b360bb 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,28 +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 }, 53 },
58 _ => return None, 54 _ => return None,
59 } 55 }
60 }; 56 };
61 57
62 Some(RangeInfo::new(original_token.text_range(), nav_targets)) 58 Some(RangeInfo::new(original_token.text_range(), nav.into_iter().collect()))
63} 59}
64 60
65fn def_for_doc_comment( 61fn def_for_doc_comment(
@@ -120,42 +116,16 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
120 } 116 }
121} 117}
122 118
123#[derive(Debug)]
124pub(crate) enum ReferenceResult {
125 Exact(NavigationTarget),
126 Approximate(Vec<NavigationTarget>),
127}
128
129impl ReferenceResult {
130 fn to_vec(self) -> Vec<NavigationTarget> {
131 match self {
132 ReferenceResult::Exact(target) => vec![target],
133 ReferenceResult::Approximate(vec) => vec,
134 }
135 }
136}
137
138pub(crate) fn reference_definition( 119pub(crate) fn reference_definition(
139 sema: &Semantics<RootDatabase>, 120 sema: &Semantics<RootDatabase>,
140 name_ref: Either<&ast::Lifetime, &ast::NameRef>, 121 name_ref: Either<&ast::Lifetime, &ast::NameRef>,
141) -> ReferenceResult { 122) -> Option<NavigationTarget> {
142 let name_kind = name_ref.either( 123 let name_kind = name_ref.either(
143 |lifetime| NameRefClass::classify_lifetime(sema, lifetime), 124 |lifetime| NameRefClass::classify_lifetime(sema, lifetime),
144 |name_ref| NameRefClass::classify(sema, name_ref), 125 |name_ref| NameRefClass::classify(sema, name_ref),
145 ); 126 )?;
146 if let Some(def) = name_kind { 127 let def = name_kind.referenced(sema.db);
147 let def = def.referenced(sema.db); 128 def.try_to_nav(sema.db)
148 return match def.try_to_nav(sema.db) {
149 Some(nav) => ReferenceResult::Exact(nav),
150 None => ReferenceResult::Approximate(Vec::new()),
151 };
152 }
153
154 // Fallback index based approach:
155 let name = name_ref.either(ast::Lifetime::text, ast::NameRef::text);
156 let navs =
157 symbol_index::index_resolve(sema.db, name).into_iter().map(|s| s.to_nav(sema.db)).collect();
158 ReferenceResult::Approximate(navs)
159} 129}
160 130
161#[cfg(test)] 131#[cfg(test)]
@@ -297,13 +267,13 @@ fn bar() {
297 fn goto_def_for_macros_from_other_crates() { 267 fn goto_def_for_macros_from_other_crates() {
298 check( 268 check(
299 r#" 269 r#"
300//- /lib.rs 270//- /lib.rs crate:main deps:foo
301use foo::foo; 271use foo::foo;
302fn bar() { 272fn bar() {
303 $0foo!(); 273 $0foo!();
304} 274}
305 275
306//- /foo/lib.rs 276//- /foo/lib.rs crate:foo
307#[macro_export] 277#[macro_export]
308macro_rules! foo { () => { () } } 278macro_rules! foo { () => { () } }
309 //^^^ 279 //^^^
@@ -315,10 +285,10 @@ macro_rules! foo { () => { () } }
315 fn goto_def_for_macros_in_use_tree() { 285 fn goto_def_for_macros_in_use_tree() {
316 check( 286 check(
317 r#" 287 r#"
318//- /lib.rs 288//- /lib.rs crate:main deps:foo
319use foo::foo$0; 289use foo::foo$0;
320 290
321//- /foo/lib.rs 291//- /foo/lib.rs crate:foo
322#[macro_export] 292#[macro_export]
323macro_rules! foo { () => { () } } 293macro_rules! foo { () => { () } }
324 //^^^ 294 //^^^
@@ -976,10 +946,10 @@ type Alias<T> = T$0;
976 fn goto_def_for_macro_container() { 946 fn goto_def_for_macro_container() {
977 check( 947 check(
978 r#" 948 r#"
979//- /lib.rs 949//- /lib.rs crate:main deps:foo
980foo::module$0::mac!(); 950foo::module$0::mac!();
981 951
982//- /foo/lib.rs 952//- /foo/lib.rs crate:foo
983pub mod module { 953pub mod module {
984 //^^^^^^ 954 //^^^^^^
985 #[macro_export] 955 #[macro_export]