aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/call_info.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/call_info.rs')
-rw-r--r--crates/ra_ide_api/src/call_info.rs43
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;
2use ra_db::SourceDatabase; 2use ra_db::SourceDatabase;
3use ra_syntax::{ 3use 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
76impl<'a> FnCallNode<'a> { 82impl<'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}
148fn bar() { foo(<|>3, ); }"#, 154fn 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#"
385pub trait WriteHandler<E> 391struct WriteHandler<E>;
386where 392
387 Self: Actor, 393impl<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
406pub fn foo() { 410pub fn foo(mut r: WriteHandler<()>) {
407 WriteHandler r;
408 r.finished(<|>); 411 r.finished(<|>);
409} 412}
410 413