diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs index c5e8d5843ca6..29fa7d30b438 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 Option 1 { // Count how many parameters into the call we are. - if let Some(ref arg_list) = calling_node.arg_list() { + if let Some(arg_list) = calling_node.arg_list() { + // Number of arguments specified at the call site + let num_args_at_callsite = arg_list.args().count(); + let arg_list_range = arg_list.syntax().range(); if !arg_list_range.contains_inclusive(position.offset) { tested_by!(call_info_bad_offset); return None; } - let param = arg_list - .args() - .position(|arg| arg.syntax().range().contains(position.offset)) - .or(Some(num_params - 1)) - .unwrap(); + let mut param = std::cmp::min( + num_args_at_callsite, + arg_list + .args() + .take_while(|arg| arg.syntax().range().end() < position.offset) + .count(), + ); + + // If we are in a method account for `self` + if has_self { + param = param + 1; + } call_info.active_parameter = Some(param); } @@ -155,6 +166,17 @@ fn bar() { foo(3, <|>); }"#, assert_eq!(info.active_parameter, Some(1)); } + #[test] + fn test_fn_signature_two_args_empty() { + let info = call_info( + r#"fn foo(x: u32, y: u32) -> u32 {x + y} +fn bar() { foo(<|>); }"#, + ); + + assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string())); + assert_eq!(info.active_parameter, Some(0)); + } + #[test] fn test_fn_signature_for_impl() { let info = call_info(