1 //! This module provides functionality for querying callable information about a token.
4 use hir::{Semantics, Type};
6 ast::{self, HasArgList, HasName},
10 use crate::RootDatabase;
13 pub struct ActiveParameter {
15 pub pat: Either<ast::SelfParam, ast::Pat>,
18 impl ActiveParameter {
19 /// Returns information about the call argument this token is part of.
20 pub fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> {
21 let (signature, active_parameter) = callable_for_token(sema, token)?;
23 let idx = active_parameter?;
24 let mut params = signature.params(sema.db);
25 if !(idx < params.len()) {
26 cov_mark::hit!(too_many_arguments);
29 let (pat, ty) = params.swap_remove(idx);
30 pat.map(|pat| ActiveParameter { ty, pat })
33 pub fn ident(&self) -> Option<ast::Name> {
34 self.pat.as_ref().right().and_then(|param| match param {
35 ast::Pat::IdentPat(ident) => ident.name(),
41 /// Returns a [`hir::Callable`] this token is a part of and its argument index of said callable.
42 pub fn callable_for_token(
43 sema: &Semantics<RootDatabase>,
45 ) -> Option<(hir::Callable, Option<usize>)> {
46 // Find the calling expression and it's NameRef
47 let parent = token.parent()?;
48 let calling_node = parent.ancestors().filter_map(ast::CallableExpr::cast).find(|it| {
50 .map_or(false, |it| it.syntax().text_range().contains(token.text_range().start()))
53 let callable = match &calling_node {
54 ast::CallableExpr::Call(call) => {
55 let expr = call.expr()?;
56 sema.type_of_expr(&expr)?.adjusted().as_callable(sema.db)
58 ast::CallableExpr::MethodCall(call) => sema.resolve_method_call_as_callable(call),
60 let active_param = if let Some(arg_list) = calling_node.arg_list() {
63 .take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start())
69 Some((callable, active_param))