aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/goto_definition.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/goto_definition.rs')
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs33
1 files changed, 15 insertions, 18 deletions
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index e0f3deb0b..b1becca03 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -1,4 +1,4 @@
1use ra_db::{FileId, Cancelable, SyntaxDatabase}; 1use ra_db::{FileId, SyntaxDatabase};
2use ra_syntax::{ 2use ra_syntax::{
3 AstNode, ast, 3 AstNode, ast,
4 algo::find_node_at_offset, 4 algo::find_node_at_offset,
@@ -9,21 +9,18 @@ use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo};
9pub(crate) fn goto_definition( 9pub(crate) fn goto_definition(
10 db: &RootDatabase, 10 db: &RootDatabase,
11 position: FilePosition, 11 position: FilePosition,
12) -> Cancelable<Option<RangeInfo<Vec<NavigationTarget>>>> { 12) -> Option<RangeInfo<Vec<NavigationTarget>>> {
13 let file = db.source_file(position.file_id); 13 let file = db.source_file(position.file_id);
14 let syntax = file.syntax(); 14 let syntax = file.syntax();
15 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { 15 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
16 let navs = reference_definition(db, position.file_id, name_ref)?.to_vec(); 16 let navs = reference_definition(db, position.file_id, name_ref).to_vec();
17 return Ok(Some(RangeInfo::new( 17 return Some(RangeInfo::new(name_ref.syntax().range(), navs.to_vec()));
18 name_ref.syntax().range(),
19 navs.to_vec(),
20 )));
21 } 18 }
22 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { 19 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) {
23 let navs = ctry!(name_definition(db, position.file_id, name)?); 20 let navs = name_definition(db, position.file_id, name)?;
24 return Ok(Some(RangeInfo::new(name.syntax().range(), navs))); 21 return Some(RangeInfo::new(name.syntax().range(), navs));
25 } 22 }
26 Ok(None) 23 None
27} 24}
28 25
29pub(crate) enum ReferenceResult { 26pub(crate) enum ReferenceResult {
@@ -45,7 +42,7 @@ pub(crate) fn reference_definition(
45 db: &RootDatabase, 42 db: &RootDatabase,
46 file_id: FileId, 43 file_id: FileId,
47 name_ref: &ast::NameRef, 44 name_ref: &ast::NameRef,
48) -> Cancelable<ReferenceResult> { 45) -> ReferenceResult {
49 use self::ReferenceResult::*; 46 use self::ReferenceResult::*;
50 if let Some(function) = 47 if let Some(function) =
51 hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax()) 48 hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax())
@@ -54,7 +51,7 @@ pub(crate) fn reference_definition(
54 // First try to resolve the symbol locally 51 // First try to resolve the symbol locally
55 if let Some(entry) = scope.resolve_local_name(name_ref) { 52 if let Some(entry) = scope.resolve_local_name(name_ref) {
56 let nav = NavigationTarget::from_scope_entry(file_id, &entry); 53 let nav = NavigationTarget::from_scope_entry(file_id, &entry);
57 return Ok(Exact(nav)); 54 return Exact(nav);
58 }; 55 };
59 56
60 // Next check if it is a method 57 // Next check if it is a method
@@ -71,7 +68,7 @@ pub(crate) fn reference_definition(
71 .and_then(|it| infer_result.method_resolution(it)) 68 .and_then(|it| infer_result.method_resolution(it))
72 { 69 {
73 if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) { 70 if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) {
74 return Ok(Exact(target)); 71 return Exact(target);
75 } 72 }
76 }; 73 };
77 } 74 }
@@ -88,7 +85,7 @@ pub(crate) fn reference_definition(
88 let resolved = module.resolve_path(db, &path); 85 let resolved = module.resolve_path(db, &path);
89 if let Some(def_id) = resolved.take_types().or(resolved.take_values()) { 86 if let Some(def_id) = resolved.take_types().or(resolved.take_values()) {
90 if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) { 87 if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) {
91 return Ok(Exact(target)); 88 return Exact(target);
92 } 89 }
93 } 90 }
94 } 91 }
@@ -99,25 +96,25 @@ pub(crate) fn reference_definition(
99 .into_iter() 96 .into_iter()
100 .map(NavigationTarget::from_symbol) 97 .map(NavigationTarget::from_symbol)
101 .collect(); 98 .collect();
102 Ok(Approximate(navs)) 99 Approximate(navs)
103} 100}
104 101
105fn name_definition( 102fn name_definition(
106 db: &RootDatabase, 103 db: &RootDatabase,
107 file_id: FileId, 104 file_id: FileId,
108 name: &ast::Name, 105 name: &ast::Name,
109) -> Cancelable<Option<Vec<NavigationTarget>>> { 106) -> Option<Vec<NavigationTarget>> {
110 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { 107 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
111 if module.has_semi() { 108 if module.has_semi() {
112 if let Some(child_module) = 109 if let Some(child_module) =
113 hir::source_binder::module_from_declaration(db, file_id, module) 110 hir::source_binder::module_from_declaration(db, file_id, module)
114 { 111 {
115 let nav = NavigationTarget::from_module(db, child_module); 112 let nav = NavigationTarget::from_module(db, child_module);
116 return Ok(Some(vec![nav])); 113 return Some(vec![nav]);
117 } 114 }
118 } 115 }
119 } 116 }
120 Ok(None) 117 None
121} 118}
122 119
123#[cfg(test)] 120#[cfg(test)]