aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs40
-rw-r--r--crates/ra_ide_api/src/hover.rs23
3 files changed, 56 insertions, 9 deletions
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index a6e744ea7..74c718e72 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -60,7 +60,7 @@ pub use self::{
60 impl_block::{ImplBlock, ImplItem}, 60 impl_block::{ImplBlock, ImplItem},
61 docs::{Docs, Documentation}, 61 docs::{Docs, Documentation},
62 adt::AdtDef, 62 adt::AdtDef,
63 expr::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax}, 63 expr::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax, Pat},
64 resolve::{Resolver, Resolution}, 64 resolve::{Resolver, Resolution},
65}; 65};
66 66
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};
7use test_utils::tested_by; 7use test_utils::tested_by;
8use hir::Resolution; 8use hir::{Pat, Resolution};
9 9
10use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; 10use 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 }
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index bcd052c8b..638c24e31 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -534,4 +534,27 @@ mod tests {
534 assert_eq!(trim_markup_opt(hover.info.first()), Some("fn new() -> Thing")); 534 assert_eq!(trim_markup_opt(hover.info.first()), Some("fn new() -> Thing"));
535 assert_eq!(hover.info.is_exact(), true); 535 assert_eq!(hover.info.is_exact(), true);
536 } 536 }
537
538 #[test]
539 fn test_hover_infer_associated_const_in_pattern() {
540 let (analysis, position) = single_file_with_position(
541 "
542 struct X;
543 impl X {
544 const C: u32 = 1;
545 }
546
547 fn main() {
548 match 1 {
549 X::C<|> => {},
550 2 => {},
551 _ => {}
552 };
553 }
554 ",
555 );
556 let hover = analysis.hover(position).unwrap().unwrap();
557 assert_eq!(trim_markup_opt(hover.info.first()), Some("const C: u32"));
558 assert_eq!(hover.info.is_exact(), true);
559 }
537} 560}