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.rs40
1 files changed, 12 insertions, 28 deletions
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 69f2d2bf6..413720960 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -50,18 +50,13 @@ pub(crate) fn reference_definition(
50 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())
51 { 51 {
52 // Check if it is a method 52 // Check if it is a method
53 if let Some(method_call) = name_ref 53 if let Some(method_call) = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast) {
54 .syntax()
55 .parent()
56 .and_then(ast::MethodCallExpr::cast)
57 {
58 tested_by!(goto_definition_works_for_methods); 54 tested_by!(goto_definition_works_for_methods);
59 let infer_result = function.infer(db); 55 let infer_result = function.infer(db);
60 let syntax_mapping = function.body_syntax_mapping(db); 56 let syntax_mapping = function.body_syntax_mapping(db);
61 let expr = ast::Expr::cast(method_call.syntax()).unwrap(); 57 let expr = ast::Expr::cast(method_call.syntax()).unwrap();
62 if let Some(func) = syntax_mapping 58 if let Some(func) =
63 .node_expr(expr) 59 syntax_mapping.node_expr(expr).and_then(|it| infer_result.method_resolution(it))
64 .and_then(|it| infer_result.method_resolution(it))
65 { 60 {
66 return Exact(NavigationTarget::from_function(db, func)); 61 return Exact(NavigationTarget::from_function(db, func));
67 }; 62 };
@@ -72,9 +67,8 @@ pub(crate) fn reference_definition(
72 let infer_result = function.infer(db); 67 let infer_result = function.infer(db);
73 let syntax_mapping = function.body_syntax_mapping(db); 68 let syntax_mapping = function.body_syntax_mapping(db);
74 let expr = ast::Expr::cast(field_expr.syntax()).unwrap(); 69 let expr = ast::Expr::cast(field_expr.syntax()).unwrap();
75 if let Some(field) = syntax_mapping 70 if let Some(field) =
76 .node_expr(expr) 71 syntax_mapping.node_expr(expr).and_then(|it| infer_result.field_resolution(it))
77 .and_then(|it| infer_result.field_resolution(it))
78 { 72 {
79 return Exact(NavigationTarget::from_field(db, field)); 73 return Exact(NavigationTarget::from_field(db, field));
80 }; 74 };
@@ -82,29 +76,19 @@ pub(crate) fn reference_definition(
82 } 76 }
83 // Try name resolution 77 // Try name resolution
84 let resolver = hir::source_binder::resolver_for_node(db, file_id, name_ref.syntax()); 78 let resolver = hir::source_binder::resolver_for_node(db, file_id, name_ref.syntax());
85 if let Some(path) = name_ref 79 if let Some(path) =
86 .syntax() 80 name_ref.syntax().ancestors().find_map(ast::Path::cast).and_then(hir::Path::from_ast)
87 .ancestors()
88 .find_map(ast::Path::cast)
89 .and_then(hir::Path::from_ast)
90 { 81 {
91 let resolved = resolver.resolve_path(db, &path); 82 let resolved = resolver.resolve_path(db, &path);
92 match resolved 83 match resolved.clone().take_types().or_else(|| resolved.take_values()) {
93 .clone()
94 .take_types()
95 .or_else(|| resolved.take_values())
96 {
97 Some(Resolution::Def(def)) => return Exact(NavigationTarget::from_def(db, def)), 84 Some(Resolution::Def(def)) => return Exact(NavigationTarget::from_def(db, def)),
98 Some(Resolution::LocalBinding(pat)) => { 85 Some(Resolution::LocalBinding(pat)) => {
99 let body = resolver.body().expect("no body for local binding"); 86 let body = resolver.body().expect("no body for local binding");
100 let syntax_mapping = body.syntax_mapping(db); 87 let syntax_mapping = body.syntax_mapping(db);
101 let ptr = syntax_mapping 88 let ptr =
102 .pat_syntax(pat) 89 syntax_mapping.pat_syntax(pat).expect("pattern not found in syntax mapping");
103 .expect("pattern not found in syntax mapping"); 90 let name =
104 let name = path 91 path.as_ident().cloned().expect("local binding from a multi-segment path");
105 .as_ident()
106 .cloned()
107 .expect("local binding from a multi-segment path");
108 let nav = NavigationTarget::from_scope_entry(file_id, name, ptr); 92 let nav = NavigationTarget::from_scope_entry(file_id, name, ptr);
109 return Exact(nav); 93 return Exact(nav);
110 } 94 }