diff options
Diffstat (limited to 'crates/ra_ide_api/src/goto_definition.rs')
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 364263d9b..286ade0a4 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -5,7 +5,7 @@ use ra_syntax::{ | |||
5 | SyntaxNode, | 5 | SyntaxNode, |
6 | }; | 6 | }; |
7 | use test_utils::tested_by; | 7 | use test_utils::tested_by; |
8 | use hir::Resolution; | 8 | use hir::{Pat, Resolution}; |
9 | 9 | ||
10 | use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; | 10 | use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; |
11 | 11 | ||
@@ -100,6 +100,7 @@ pub(crate) fn reference_definition( | |||
100 | } | 100 | } |
101 | } | 101 | } |
102 | } | 102 | } |
103 | |||
103 | // Try name resolution | 104 | // Try name resolution |
104 | let resolver = hir::source_binder::resolver_for_node(db, file_id, name_ref.syntax()); | 105 | let resolver = hir::source_binder::resolver_for_node(db, file_id, name_ref.syntax()); |
105 | if let Some(path) = | 106 | if let Some(path) = |
@@ -126,19 +127,42 @@ pub(crate) fn reference_definition( | |||
126 | None => { | 127 | None => { |
127 | // If we failed to resolve then check associated items | 128 | // If we failed to resolve then check associated items |
128 | if let Some(function) = function { | 129 | if let Some(function) = function { |
129 | // Should we do this above and then grab path from the PathExpr? | 130 | // Resolve associated item for path expressions |
130 | if let Some(path_expr) = | 131 | if let Some(path_expr) = |
131 | name_ref.syntax().ancestors().find_map(ast::PathExpr::cast) | 132 | name_ref.syntax().ancestors().find_map(ast::PathExpr::cast) |
132 | { | 133 | { |
133 | let infer_result = function.infer(db); | 134 | let infer_result = function.infer(db); |
134 | let source_map = function.body_source_map(db); | 135 | let source_map = function.body_source_map(db); |
135 | let expr = ast::Expr::cast(path_expr.syntax()).unwrap(); | ||
136 | 136 | ||
137 | if let Some(res) = source_map | 137 | if let Some(expr) = ast::Expr::cast(path_expr.syntax()) { |
138 | .node_expr(expr) | 138 | if let Some(res) = source_map |
139 | .and_then(|it| infer_result.assoc_resolutions_for_expr(it.into())) | 139 | .node_expr(expr) |
140 | { | 140 | .and_then(|it| infer_result.assoc_resolutions_for_expr(it.into())) |
141 | return Exact(NavigationTarget::from_impl_item(db, res)); | 141 | { |
142 | return Exact(NavigationTarget::from_impl_item(db, res)); | ||
143 | } | ||
144 | } | ||
145 | } | ||
146 | |||
147 | // Resolve associated item for path patterns | ||
148 | if let Some(path_pat) = | ||
149 | name_ref.syntax().ancestors().find_map(ast::PathPat::cast) | ||
150 | { | ||
151 | let infer_result = function.infer(db); | ||
152 | |||
153 | if let Some(p) = path_pat.path().and_then(hir::Path::from_ast) { | ||
154 | if let Some(pat_id) = | ||
155 | function.body(db).pats().find_map(|(pat_id, pat)| match pat { | ||
156 | Pat::Path(ref path) if *path == p => Some(pat_id), | ||
157 | _ => None, | ||
158 | }) | ||
159 | { | ||
160 | if let Some(res) = | ||
161 | infer_result.assoc_resolutions_for_pat(pat_id.into()) | ||
162 | { | ||
163 | return Exact(NavigationTarget::from_impl_item(db, res)); | ||
164 | } | ||
165 | } | ||
142 | } | 166 | } |
143 | } | 167 | } |
144 | } | 168 | } |