From 584c8d987501273b7341685d52b71bdaa1c2461e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 29 Feb 2020 23:24:50 +0100 Subject: Slightly refactor inlay hints --- crates/ra_ide/src/inlay_hints.rs | 127 ++++++++++++++++++--------------------- crates/ra_syntax/src/ast.rs | 2 +- 2 files changed, 59 insertions(+), 70 deletions(-) diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 35e3f782d..69098a630 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -5,7 +5,7 @@ use ra_ide_db::RootDatabase; use ra_prof::profile; use ra_syntax::{ ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner}, - match_ast, SmolStr, SyntaxNode, TextRange, + match_ast, SmolStr, TextRange, }; use crate::{FileId, FunctionSignature}; @@ -28,50 +28,76 @@ pub(crate) fn inlay_hints( file_id: FileId, max_inlay_hint_length: Option, ) -> Vec { + let _p = profile("inlay_hints"); let sema = Semantics::new(db); let file = sema.parse(file_id); + let mut res = Vec::new(); for node in file.syntax().descendants() { - get_inlay_hints(&mut res, &sema, &node, max_inlay_hint_length); + match_ast! { + match node { + ast::CallExpr(it) => { get_param_name_hints(&mut res, &sema, ast::Expr::from(it)); }, + ast::MethodCallExpr(it) => { get_param_name_hints(&mut res, &sema, ast::Expr::from(it)); }, + ast::BindPat(it) => { get_bind_pat_hints(&mut res, &sema, max_inlay_hint_length, it); }, + _ => (), + } + } } res } -fn get_inlay_hints( +fn get_param_name_hints( + acc: &mut Vec, + sema: &Semantics, + expr: ast::Expr, +) -> Option<()> { + let args = match &expr { + ast::Expr::CallExpr(expr) => expr.arg_list()?.args(), + ast::Expr::MethodCallExpr(expr) => expr.arg_list()?.args(), + _ => return None, + }; + let args_count = args.clone().count(); + + let fn_signature = get_fn_signature(sema, &expr)?; + let n_params_to_skip = + if fn_signature.has_self_param && fn_signature.parameter_names.len() > args_count { + 1 + } else { + 0 + }; + let hints = fn_signature + .parameter_names + .iter() + .skip(n_params_to_skip) + .zip(args) + .filter(|(param, arg)| should_show_param_hint(&fn_signature, param, &arg)) + .map(|(param_name, arg)| InlayHint { + range: arg.syntax().text_range(), + kind: InlayKind::ParameterHint, + label: param_name.into(), + }); + + acc.extend(hints); + Some(()) +} + +fn get_bind_pat_hints( acc: &mut Vec, sema: &Semantics, - node: &SyntaxNode, max_inlay_hint_length: Option, + pat: ast::BindPat, ) -> Option<()> { - let _p = profile("get_inlay_hints"); - let db = sema.db; - match_ast! { - match node { - ast::CallExpr(it) => { - get_param_name_hints(acc, sema, ast::Expr::from(it)); - }, - ast::MethodCallExpr(it) => { - get_param_name_hints(acc, sema, ast::Expr::from(it)); - }, - ast::BindPat(it) => { - let pat = ast::Pat::from(it.clone()); - let ty = sema.type_of_pat(&pat)?; - - if should_not_display_type_hint(db, &it, &ty) { - return None; - } + let ty = sema.type_of_pat(&pat.clone().into())?; - acc.push( - InlayHint { - range: pat.syntax().text_range(), - kind: InlayKind::TypeHint, - label: ty.display_truncated(db, max_inlay_hint_length).to_string().into(), - } - ); - }, - _ => (), - } - }; + if should_not_display_type_hint(sema.db, &pat, &ty) { + return None; + } + + acc.push(InlayHint { + range: pat.syntax().text_range(), + kind: InlayKind::TypeHint, + label: ty.display_truncated(sema.db, max_inlay_hint_length).to_string().into(), + }); Some(()) } @@ -120,43 +146,6 @@ fn should_not_display_type_hint(db: &RootDatabase, bind_pat: &ast::BindPat, pat_ false } -fn get_param_name_hints( - acc: &mut Vec, - sema: &Semantics, - expr: ast::Expr, -) -> Option<()> { - let args = match &expr { - ast::Expr::CallExpr(expr) => expr.arg_list()?.args(), - ast::Expr::MethodCallExpr(expr) => expr.arg_list()?.args(), - _ => return None, - } - .into_iter() - // we need args len to determine whether to skip or not the &self parameter - .collect::>(); - - let fn_signature = get_fn_signature(sema, &expr)?; - let n_params_to_skip = - if fn_signature.has_self_param && fn_signature.parameter_names.len() > args.len() { - 1 - } else { - 0 - }; - let hints = fn_signature - .parameter_names - .iter() - .skip(n_params_to_skip) - .zip(args) - .filter(|(param, arg)| should_show_param_hint(&fn_signature, param, &arg)) - .map(|(param_name, arg)| InlayHint { - range: arg.syntax().text_range(), - kind: InlayKind::ParameterHint, - label: param_name.into(), - }); - - acc.extend(hints); - Some(()) -} - fn should_show_param_hint( fn_signature: &FunctionSignature, param_name: &str, diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 9cc7930f7..4a70c712f 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -59,7 +59,7 @@ pub trait AstToken { } /// An iterator over `SyntaxNode` children of a particular AST type. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AstChildren { inner: SyntaxNodeChildren, ph: PhantomData, -- cgit v1.2.3