diff options
Diffstat (limited to 'crates/ra_ide_api/src/call_info.rs')
-rw-r--r-- | crates/ra_ide_api/src/call_info.rs | 43 |
1 files changed, 23 insertions, 20 deletions
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs index dbb3853d0..4413aec73 100644 --- a/crates/ra_ide_api/src/call_info.rs +++ b/crates/ra_ide_api/src/call_info.rs | |||
@@ -2,7 +2,6 @@ use test_utils::tested_by; | |||
2 | use ra_db::SourceDatabase; | 2 | use ra_db::SourceDatabase; |
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | AstNode, SyntaxNode, TextUnit, | 4 | AstNode, SyntaxNode, TextUnit, |
5 | SyntaxKind::FN_DEF, | ||
6 | ast::{self, ArgListOwner}, | 5 | ast::{self, ArgListOwner}, |
7 | algo::find_node_at_offset, | 6 | algo::find_node_at_offset, |
8 | }; | 7 | }; |
@@ -18,19 +17,26 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
18 | let calling_node = FnCallNode::with_node(syntax, position.offset)?; | 17 | let calling_node = FnCallNode::with_node(syntax, position.offset)?; |
19 | let name_ref = calling_node.name_ref()?; | 18 | let name_ref = calling_node.name_ref()?; |
20 | 19 | ||
21 | // Resolve the function's NameRef (NOTE: this isn't entirely accurate). | 20 | let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None); |
22 | let file_symbols = crate::symbol_index::index_resolve(db, name_ref); | 21 | let function = match calling_node { |
23 | let symbol = file_symbols.into_iter().find(|it| it.ptr.kind() == FN_DEF)?; | 22 | FnCallNode::CallExpr(expr) => { |
24 | let fn_file = db.parse(symbol.file_id); | 23 | //FIXME: apply subst |
25 | let fn_def = symbol.ptr.to_node(&fn_file); | 24 | let (callable_def, _subst) = |
26 | let fn_def = ast::FnDef::cast(fn_def).unwrap(); | 25 | analyzer.type_of(db, expr.expr()?.into())?.as_callable()?; |
27 | let function = hir::source_binder::function_from_source(db, symbol.file_id, fn_def)?; | 26 | match callable_def { |
27 | hir::CallableDef::Function(it) => it, | ||
28 | //FIXME: handle other callables | ||
29 | _ => return None, | ||
30 | } | ||
31 | } | ||
32 | FnCallNode::MethodCallExpr(expr) => analyzer.resolve_method_call(expr)?, | ||
33 | }; | ||
28 | 34 | ||
29 | let mut call_info = CallInfo::new(db, function); | 35 | let mut call_info = CallInfo::new(db, function); |
30 | 36 | ||
31 | // If we have a calling expression let's find which argument we are on | 37 | // If we have a calling expression let's find which argument we are on |
32 | let num_params = call_info.parameters().len(); | 38 | let num_params = call_info.parameters().len(); |
33 | let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some(); | 39 | let has_self = function.signature(db).has_self_param(); |
34 | 40 | ||
35 | if num_params == 1 { | 41 | if num_params == 1 { |
36 | if !has_self { | 42 | if !has_self { |
@@ -74,7 +80,7 @@ enum FnCallNode<'a> { | |||
74 | } | 80 | } |
75 | 81 | ||
76 | impl<'a> FnCallNode<'a> { | 82 | impl<'a> FnCallNode<'a> { |
77 | pub fn with_node(syntax: &'a SyntaxNode, offset: TextUnit) -> Option<FnCallNode<'a>> { | 83 | fn with_node(syntax: &'a SyntaxNode, offset: TextUnit) -> Option<FnCallNode<'a>> { |
78 | if let Some(expr) = find_node_at_offset::<ast::CallExpr>(syntax, offset) { | 84 | if let Some(expr) = find_node_at_offset::<ast::CallExpr>(syntax, offset) { |
79 | return Some(FnCallNode::CallExpr(expr)); | 85 | return Some(FnCallNode::CallExpr(expr)); |
80 | } | 86 | } |
@@ -84,7 +90,7 @@ impl<'a> FnCallNode<'a> { | |||
84 | None | 90 | None |
85 | } | 91 | } |
86 | 92 | ||
87 | pub fn name_ref(&self) -> Option<&'a ast::NameRef> { | 93 | fn name_ref(&self) -> Option<&'a ast::NameRef> { |
88 | match *self { | 94 | match *self { |
89 | FnCallNode::CallExpr(call_expr) => Some(match call_expr.expr()?.kind() { | 95 | FnCallNode::CallExpr(call_expr) => Some(match call_expr.expr()?.kind() { |
90 | ast::ExprKind::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?, | 96 | ast::ExprKind::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?, |
@@ -97,7 +103,7 @@ impl<'a> FnCallNode<'a> { | |||
97 | } | 103 | } |
98 | } | 104 | } |
99 | 105 | ||
100 | pub fn arg_list(&self) -> Option<&'a ast::ArgList> { | 106 | fn arg_list(&self) -> Option<&'a ast::ArgList> { |
101 | match *self { | 107 | match *self { |
102 | FnCallNode::CallExpr(expr) => expr.arg_list(), | 108 | FnCallNode::CallExpr(expr) => expr.arg_list(), |
103 | FnCallNode::MethodCallExpr(expr) => expr.arg_list(), | 109 | FnCallNode::MethodCallExpr(expr) => expr.arg_list(), |
@@ -142,7 +148,7 @@ mod tests { | |||
142 | } | 148 | } |
143 | 149 | ||
144 | #[test] | 150 | #[test] |
145 | fn test_fn_signature_two_args_first() { | 151 | fn test_fn_signature_two_args_firstx() { |
146 | let info = call_info( | 152 | let info = call_info( |
147 | r#"fn foo(x: u32, y: u32) -> u32 {x + y} | 153 | r#"fn foo(x: u32, y: u32) -> u32 {x + y} |
148 | fn bar() { foo(<|>3, ); }"#, | 154 | fn bar() { foo(<|>3, ); }"#, |
@@ -382,11 +388,9 @@ assert_eq!(6, my_crate::add_one(5)); | |||
382 | fn test_fn_signature_with_docs_from_actix() { | 388 | fn test_fn_signature_with_docs_from_actix() { |
383 | let info = call_info( | 389 | let info = call_info( |
384 | r#" | 390 | r#" |
385 | pub trait WriteHandler<E> | 391 | struct WriteHandler<E>; |
386 | where | 392 | |
387 | Self: Actor, | 393 | impl<E> WriteHandler<E> { |
388 | Self::Context: ActorContext, | ||
389 | { | ||
390 | /// Method is called when writer emits error. | 394 | /// Method is called when writer emits error. |
391 | /// | 395 | /// |
392 | /// If this method returns `ErrorAction::Continue` writer processing | 396 | /// If this method returns `ErrorAction::Continue` writer processing |
@@ -403,8 +407,7 @@ where | |||
403 | } | 407 | } |
404 | } | 408 | } |
405 | 409 | ||
406 | pub fn foo() { | 410 | pub fn foo(mut r: WriteHandler<()>) { |
407 | WriteHandler r; | ||
408 | r.finished(<|>); | 411 | r.finished(<|>); |
409 | } | 412 | } |
410 | 413 | ||