diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs index 7d18be483c..c95133343d 100644 --- a/crates/ra_ide_api/src/call_info.rs +++ b/crates/ra_ide_api/src/call_info.rs @@ -2,7 +2,7 @@ use ra_db::SourceDatabase; use ra_syntax::{ - algo::find_node_at_offset, + algo::ancestors_at_offset, ast::{self, ArgListOwner}, AstNode, SyntaxNode, TextUnit, }; @@ -82,13 +82,15 @@ enum FnCallNode { impl FnCallNode { fn with_node(syntax: &SyntaxNode, offset: TextUnit) -> Option { - if let Some(expr) = find_node_at_offset::(syntax, offset) { - return Some(FnCallNode::CallExpr(expr)); - } - if let Some(expr) = find_node_at_offset::(syntax, offset) { - return Some(FnCallNode::MethodCallExpr(expr)); - } - None + ancestors_at_offset(syntax, offset).find_map(|node| { + if let Some(expr) = ast::CallExpr::cast(node.clone()) { + Some(FnCallNode::CallExpr(expr)) + } else if let Some(expr) = ast::MethodCallExpr::cast(node.clone()) { + Some(FnCallNode::MethodCallExpr(expr)) + } else { + None + } + }) } fn name_ref(&self) -> Option { @@ -438,4 +440,26 @@ By default this method stops actor's `Context`."# let call_info = analysis.call_info(position).unwrap(); assert!(call_info.is_none()); } + + #[test] + fn test_nested_method_in_lamba() { + let info = call_info( + r#"struct Foo; + +impl Foo { + fn bar(&self, _: u32) { } +} + +fn bar(_: u32) { } + +fn main() { + let foo = Foo; + std::thread::spawn(move || foo.bar(<|>)); +}"#, + ); + + assert_eq!(info.parameters(), ["&self", "_: u32"]); + assert_eq!(info.active_parameter, Some(1)); + assert_eq!(info.label(), "fn bar(&self, _: u32)"); + } }