diff options
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r-- | crates/ra_ide_api/src/call_info.rs | 34 |
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} | ||
173 | fn 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{}} } |