diff options
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 40 | ||||
-rw-r--r-- | crates/ra_ide_api/src/hover.rs | 23 |
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 | }; |
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 | } |
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 | } |