diff options
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 29 | ||||
-rw-r--r-- | crates/ra_ide_api/src/hover.rs | 22 | ||||
-rw-r--r-- | crates/ra_ide_api/src/navigation_target.rs | 16 | ||||
-rw-r--r-- | crates/ra_ide_api/src/symbol_index.rs | 9 |
4 files changed, 70 insertions, 6 deletions
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 9ec179593..364263d9b 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -47,9 +47,10 @@ pub(crate) fn reference_definition( | |||
47 | name_ref: &ast::NameRef, | 47 | name_ref: &ast::NameRef, |
48 | ) -> ReferenceResult { | 48 | ) -> ReferenceResult { |
49 | use self::ReferenceResult::*; | 49 | use self::ReferenceResult::*; |
50 | if let Some(function) = | 50 | |
51 | hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax()) | 51 | let function = hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax()); |
52 | { | 52 | |
53 | if let Some(function) = function { | ||
53 | // Check if it is a method | 54 | // Check if it is a method |
54 | if let Some(method_call) = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast) { | 55 | if let Some(method_call) = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast) { |
55 | tested_by!(goto_definition_works_for_methods); | 56 | tested_by!(goto_definition_works_for_methods); |
@@ -122,9 +123,29 @@ pub(crate) fn reference_definition( | |||
122 | Some(Resolution::SelfType(_impl_block)) => { | 123 | Some(Resolution::SelfType(_impl_block)) => { |
123 | // TODO: go to the implemented type | 124 | // TODO: go to the implemented type |
124 | } | 125 | } |
125 | None => {} | 126 | None => { |
127 | // If we failed to resolve then check associated items | ||
128 | if let Some(function) = function { | ||
129 | // Should we do this above and then grab path from the PathExpr? | ||
130 | if let Some(path_expr) = | ||
131 | name_ref.syntax().ancestors().find_map(ast::PathExpr::cast) | ||
132 | { | ||
133 | let infer_result = function.infer(db); | ||
134 | let source_map = function.body_source_map(db); | ||
135 | let expr = ast::Expr::cast(path_expr.syntax()).unwrap(); | ||
136 | |||
137 | if let Some(res) = source_map | ||
138 | .node_expr(expr) | ||
139 | .and_then(|it| infer_result.assoc_resolutions_for_expr(it.into())) | ||
140 | { | ||
141 | return Exact(NavigationTarget::from_impl_item(db, res)); | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | } | ||
126 | } | 146 | } |
127 | } | 147 | } |
148 | |||
128 | // If that fails try the index based approach. | 149 | // If that fails try the index based approach. |
129 | let navs = crate::symbol_index::index_resolve(db, name_ref) | 150 | let navs = crate::symbol_index::index_resolve(db, name_ref) |
130 | .into_iter() | 151 | .into_iter() |
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 8ec60090d..bcd052c8b 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs | |||
@@ -512,4 +512,26 @@ mod tests { | |||
512 | let hover = analysis.hover(position).unwrap().unwrap(); | 512 | let hover = analysis.hover(position).unwrap().unwrap(); |
513 | assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); | 513 | assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); |
514 | } | 514 | } |
515 | |||
516 | #[test] | ||
517 | fn test_hover_infer_associated_method_exact() { | ||
518 | let (analysis, position) = single_file_with_position( | ||
519 | " | ||
520 | struct Thing { x: u32 } | ||
521 | |||
522 | impl Thing { | ||
523 | fn new() -> Thing { | ||
524 | Thing { x: 0 } | ||
525 | } | ||
526 | } | ||
527 | |||
528 | fn main() { | ||
529 | let foo_test = Thing::new<|>(); | ||
530 | } | ||
531 | ", | ||
532 | ); | ||
533 | let hover = analysis.hover(position).unwrap().unwrap(); | ||
534 | assert_eq!(trim_markup_opt(hover.info.first()), Some("fn new() -> Thing")); | ||
535 | assert_eq!(hover.info.is_exact(), true); | ||
536 | } | ||
515 | } | 537 | } |
diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index 6538081ac..d806cb368 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs | |||
@@ -3,7 +3,7 @@ use ra_syntax::{ | |||
3 | SyntaxNode, SyntaxNodePtr, AstNode, SmolStr, TextRange, ast, | 3 | SyntaxNode, SyntaxNodePtr, AstNode, SmolStr, TextRange, ast, |
4 | SyntaxKind::{self, NAME}, | 4 | SyntaxKind::{self, NAME}, |
5 | }; | 5 | }; |
6 | use hir::{ModuleSource, FieldSource, Name}; | 6 | use hir::{ModuleSource, FieldSource, Name, ImplItem}; |
7 | 7 | ||
8 | use crate::{FileSymbol, db::RootDatabase}; | 8 | use crate::{FileSymbol, db::RootDatabase}; |
9 | 9 | ||
@@ -174,6 +174,20 @@ impl NavigationTarget { | |||
174 | ) | 174 | ) |
175 | } | 175 | } |
176 | 176 | ||
177 | pub(crate) fn from_impl_item(db: &RootDatabase, impl_item: hir::ImplItem) -> NavigationTarget { | ||
178 | match impl_item { | ||
179 | ImplItem::Method(f) => NavigationTarget::from_function(db, f), | ||
180 | ImplItem::Const(c) => { | ||
181 | let (file_id, node) = c.source(db); | ||
182 | NavigationTarget::from_named(file_id.original_file(db), &*node) | ||
183 | } | ||
184 | ImplItem::TypeAlias(a) => { | ||
185 | let (file_id, node) = a.source(db); | ||
186 | NavigationTarget::from_named(file_id.original_file(db), &*node) | ||
187 | } | ||
188 | } | ||
189 | } | ||
190 | |||
177 | #[cfg(test)] | 191 | #[cfg(test)] |
178 | pub(crate) fn assert_match(&self, expected: &str) { | 192 | pub(crate) fn assert_match(&self, expected: &str) { |
179 | let actual = self.debug_render(); | 193 | let actual = self.debug_render(); |
diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide_api/src/symbol_index.rs index 414327ac2..94fe1d6d7 100644 --- a/crates/ra_ide_api/src/symbol_index.rs +++ b/crates/ra_ide_api/src/symbol_index.rs | |||
@@ -24,6 +24,7 @@ use std::{ | |||
24 | hash::{Hash, Hasher}, | 24 | hash::{Hash, Hasher}, |
25 | sync::Arc, | 25 | sync::Arc, |
26 | mem, | 26 | mem, |
27 | fmt, | ||
27 | }; | 28 | }; |
28 | 29 | ||
29 | use fst::{self, Streamer}; | 30 | use fst::{self, Streamer}; |
@@ -113,12 +114,18 @@ pub(crate) fn index_resolve(db: &RootDatabase, name_ref: &ast::NameRef) -> Vec<F | |||
113 | crate::symbol_index::world_symbols(db, query) | 114 | crate::symbol_index::world_symbols(db, query) |
114 | } | 115 | } |
115 | 116 | ||
116 | #[derive(Default, Debug)] | 117 | #[derive(Default)] |
117 | pub(crate) struct SymbolIndex { | 118 | pub(crate) struct SymbolIndex { |
118 | symbols: Vec<FileSymbol>, | 119 | symbols: Vec<FileSymbol>, |
119 | map: fst::Map, | 120 | map: fst::Map, |
120 | } | 121 | } |
121 | 122 | ||
123 | impl fmt::Debug for SymbolIndex { | ||
124 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
125 | f.debug_struct("SymbolIndex").field("n_symbols", &self.symbols.len()).finish() | ||
126 | } | ||
127 | } | ||
128 | |||
122 | impl PartialEq for SymbolIndex { | 129 | impl PartialEq for SymbolIndex { |
123 | fn eq(&self, other: &SymbolIndex) -> bool { | 130 | fn eq(&self, other: &SymbolIndex) -> bool { |
124 | self.symbols == other.symbols | 131 | self.symbols == other.symbols |