Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide_db/src/call_info.rs')
| -rw-r--r-- | crates/ide_db/src/call_info.rs | 94 |
1 files changed, 17 insertions, 77 deletions
diff --git a/crates/ide_db/src/call_info.rs b/crates/ide_db/src/call_info.rs index e1d85f0411..922a411aed 100644 --- a/crates/ide_db/src/call_info.rs +++ b/crates/ide_db/src/call_info.rs @@ -6,7 +6,7 @@ use stdx::format_to; use syntax::{ algo, ast::{self, HasArgList, HasName}, - match_ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextSize, + AstNode, Direction, SyntaxToken, TextRange, TextSize, }; use crate::RootDatabase; @@ -25,9 +25,11 @@ impl CallInfo { pub fn parameter_labels(&self) -> impl Iterator<Item = &str> + '_ { self.parameters.iter().map(move |&it| &self.signature[it]) } + pub fn parameter_ranges(&self) -> &[TextRange] { &self.parameters } + fn push_param(&mut self, param: &str) { if !self.signature.ends_with('(') { self.signature.push_str(", "); @@ -115,31 +117,24 @@ fn call_info_impl( token: SyntaxToken, ) -> Option<(hir::Callable, Option<usize>)> { // Find the calling expression and it's NameRef - let calling_node = FnCallNode::with_node(&token.parent()?)?; + let parent = token.parent()?; + let calling_node = parent.ancestors().filter_map(ast::CallableExpr::cast).find(|it| { + it.arg_list() + .map_or(false, |it| it.syntax().text_range().contains(token.text_range().start())) + })?; let callable = match &calling_node { - FnCallNode::CallExpr(call) => { - sema.type_of_expr(&call.expr()?)?.adjusted().as_callable(sema.db)? + ast::CallableExpr::Call(call) => { + let expr = call.expr()?; + sema.type_of_expr(&expr)?.adjusted().as_callable(sema.db) } - FnCallNode::MethodCallExpr(call) => sema.resolve_method_call_as_callable(call)?, - }; + ast::CallableExpr::MethodCall(call) => sema.resolve_method_call_as_callable(call), + }?; let active_param = 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().text_range(); - if !arg_list_range.contains_inclusive(token.text_range().start()) { - cov_mark::hit!(call_info_bad_offset); - return None; - } - let param = std::cmp::min( - num_args_at_callsite, - arg_list - .args() - .take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start()) - .count(), - ); - + let param = arg_list + .args() + .take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start()) + .count(); Some(param) } else { None @@ -175,60 +170,5 @@ impl ActiveParameter { } } -#[derive(Debug)] -pub enum FnCallNode { - CallExpr(ast::CallExpr), - MethodCallExpr(ast::MethodCallExpr), -} - -impl FnCallNode { - fn with_node(syntax: &SyntaxNode) -> Option<FnCallNode> { - syntax.ancestors().find_map(|node| { - match_ast! { - match node { - ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)), - ast::MethodCallExpr(it) => { - let arg_list = it.arg_list()?; - if !arg_list.syntax().text_range().contains_range(syntax.text_range()) { - return None; - } - Some(FnCallNode::MethodCallExpr(it)) - }, - _ => None, - } - } - }) - } - - pub fn with_node_exact(node: &SyntaxNode) -> Option<FnCallNode> { - match_ast! { - match node { - ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)), - ast::MethodCallExpr(it) => Some(FnCallNode::MethodCallExpr(it)), - _ => None, - } - } - } - - pub fn name_ref(&self) -> Option<ast::NameRef> { - match self { - FnCallNode::CallExpr(call_expr) => Some(match call_expr.expr()? { - ast::Expr::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?, - _ => return None, - }), - FnCallNode::MethodCallExpr(call_expr) => { - call_expr.syntax().children().find_map(ast::NameRef::cast) - } - } - } - - fn arg_list(&self) -> Option<ast::ArgList> { - match self { - FnCallNode::CallExpr(expr) => expr.arg_list(), - FnCallNode::MethodCallExpr(expr) => expr.arg_list(), - } - } -} - #[cfg(test)] mod tests; |