aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/goto_definition.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-02-01 22:37:59 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-02-01 22:37:59 +0000
commit4447019f4b5f24728bb7b91b161755ddb373c74c (patch)
treec53ff3531cbbad182e821eb92fa9ad201d2bff0c /crates/ra_ide_api/src/goto_definition.rs
parent2b5c226e86892113bcab478cdf4c9adaf1e7b2f6 (diff)
parentc5852f422ff45adaa21815c1a15e03b067a56a82 (diff)
Merge #693
693: Name resolution refactoring r=matklad a=flodiebold This is still very WIP, but it's becoming quite big and I want to make sure this isn't going in a completely bad direction :sweat_smile:. I'm not really happy with how the path resolution looks, and I'm not sure `PerNs<Resolution>` is the best return type -- there are 'this cannot happen in the (types/values) namespace' cases everywhere. I also want to unify the `resolver` and `nameres` namespaces once I'm done switching everything to `Resolver`. Also, `Resolver` only has a lifetime because it needs to have a reference to the `ItemMap` during import resolution :confused: The differences in the completion snapshots are almost completely just ordering (except it completes `Self` as well now), so I changed it to sort the completions before snapshotting. Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_ide_api/src/goto_definition.rs')
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs50
1 files changed, 31 insertions, 19 deletions
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 2a20c20ee..88efcea2a 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -4,6 +4,7 @@ use ra_syntax::{
4 algo::find_node_at_offset, 4 algo::find_node_at_offset,
5}; 5};
6use test_utils::tested_by; 6use test_utils::tested_by;
7use hir::Resolution;
7 8
8use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; 9use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo};
9 10
@@ -48,14 +49,7 @@ pub(crate) fn reference_definition(
48 if let Some(function) = 49 if let Some(function) =
49 hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax()) 50 hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax())
50 { 51 {
51 let scope = function.scopes(db); 52 // Check if it is a method
52 // First try to resolve the symbol locally
53 if let Some(entry) = scope.resolve_local_name(name_ref) {
54 let nav = NavigationTarget::from_scope_entry(file_id, &entry);
55 return Exact(nav);
56 };
57
58 // Next check if it is a method
59 if let Some(method_call) = name_ref 53 if let Some(method_call) = name_ref
60 .syntax() 54 .syntax()
61 .parent() 55 .parent()
@@ -86,19 +80,37 @@ pub(crate) fn reference_definition(
86 }; 80 };
87 } 81 }
88 } 82 }
89 // Then try module name resolution 83 // Try name resolution
90 if let Some(module) = hir::source_binder::module_from_child_node(db, file_id, name_ref.syntax()) 84 let resolver = hir::source_binder::resolver_for_node(db, file_id, name_ref.syntax());
85 if let Some(path) = name_ref
86 .syntax()
87 .ancestors()
88 .find_map(ast::Path::cast)
89 .and_then(hir::Path::from_ast)
91 { 90 {
92 if let Some(path) = name_ref 91 let resolved = resolver.resolve_path(db, &path);
93 .syntax() 92 match resolved.clone().take_types().or(resolved.take_values()) {
94 .ancestors() 93 Some(Resolution::Def(def)) => return Exact(NavigationTarget::from_def(db, def)),
95 .find_map(ast::Path::cast) 94 Some(Resolution::LocalBinding(pat)) => {
96 .and_then(hir::Path::from_ast) 95 let body = resolver.body().expect("no body for local binding");
97 { 96 let syntax_mapping = body.syntax_mapping(db);
98 let resolved = module.resolve_path(db, &path); 97 let ptr = syntax_mapping
99 if let Some(def_id) = resolved.take_types().or(resolved.take_values()) { 98 .pat_syntax(pat)
100 return Exact(NavigationTarget::from_def(db, def_id)); 99 .expect("pattern not found in syntax mapping");
100 let name = path
101 .as_ident()
102 .cloned()
103 .expect("local binding from a multi-segment path");
104 let nav = NavigationTarget::from_scope_entry(file_id, name, ptr);
105 return Exact(nav);
106 }
107 Some(Resolution::GenericParam(..)) => {
108 // TODO go to the generic param def
109 }
110 Some(Resolution::SelfType(_impl_block)) => {
111 // TODO go to the implemented type
101 } 112 }
113 None => {}
102 } 114 }
103 } 115 }
104 // If that fails try the index based approach. 116 // If that fails try the index based approach.