aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_ide_api/src/call_info.rs34
1 files changed, 28 insertions, 6 deletions
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index c5e8d5843..29fa7d30b 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -28,6 +28,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
28 let function = hir::source_binder::function_from_source(db, symbol.file_id, fn_def)?; 28 let function = hir::source_binder::function_from_source(db, symbol.file_id, fn_def)?;
29 29
30 let mut call_info = CallInfo::new(db, function, fn_def)?; 30 let mut call_info = CallInfo::new(db, function, fn_def)?;
31
31 // If we have a calling expression let's find which argument we are on 32 // If we have a calling expression let's find which argument we are on
32 let num_params = call_info.parameters.len(); 33 let num_params = call_info.parameters.len();
33 let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some(); 34 let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some();
@@ -38,18 +39,28 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
38 } 39 }
39 } else if num_params > 1 { 40 } else if num_params > 1 {
40 // Count how many parameters into the call we are. 41 // Count how many parameters into the call we are.
41 if let Some(ref arg_list) = calling_node.arg_list() { 42 if let Some(arg_list) = calling_node.arg_list() {
43 // Number of arguments specified at the call site
44 let num_args_at_callsite = arg_list.args().count();
45
42 let arg_list_range = arg_list.syntax().range(); 46 let arg_list_range = arg_list.syntax().range();
43 if !arg_list_range.contains_inclusive(position.offset) { 47 if !arg_list_range.contains_inclusive(position.offset) {
44 tested_by!(call_info_bad_offset); 48 tested_by!(call_info_bad_offset);
45 return None; 49 return None;
46 } 50 }
47 51
48 let param = arg_list 52 let mut param = std::cmp::min(
49 .args() 53 num_args_at_callsite,
50 .position(|arg| arg.syntax().range().contains(position.offset)) 54 arg_list
51 .or(Some(num_params - 1)) 55 .args()
52 .unwrap(); 56 .take_while(|arg| arg.syntax().range().end() < position.offset)
57 .count(),
58 );
59
60 // If we are in a method account for `self`
61 if has_self {
62 param = param + 1;
63 }
53 64
54 call_info.active_parameter = Some(param); 65 call_info.active_parameter = Some(param);
55 } 66 }
@@ -156,6 +167,17 @@ fn bar() { foo(3, <|>); }"#,
156 } 167 }
157 168
158 #[test] 169 #[test]
170 fn test_fn_signature_two_args_empty() {
171 let info = call_info(
172 r#"fn foo(x: u32, y: u32) -> u32 {x + y}
173fn bar() { foo(<|>); }"#,
174 );
175
176 assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string()));
177 assert_eq!(info.active_parameter, Some(0));
178 }
179
180 #[test]
159 fn test_fn_signature_for_impl() { 181 fn test_fn_signature_for_impl() {
160 let info = call_info( 182 let info = call_info(
161 r#"struct F; impl F { pub fn new() { F{}} } 183 r#"struct F; impl F { pub fn new() { F{}} }