From 272f6dfd9eceb171b23200601201f3df95aa66c9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 16 Jan 2020 14:31:34 +0100 Subject: Micro-optimize type hints to avoid allocations --- crates/ra_ide/src/inlay_hints.rs | 77 ++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 39 deletions(-) (limited to 'crates/ra_ide') diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index e2da96129..1b631c7cd 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -30,19 +30,20 @@ pub(crate) fn inlay_hints( max_inlay_hint_length: Option, ) -> Vec { let mut sb = SourceBinder::new(db); - file.syntax() - .descendants() - .flat_map(|node| get_inlay_hints(&mut sb, file_id, &node, max_inlay_hint_length)) - .flatten() - .collect() + let mut res = Vec::new(); + for node in file.syntax().descendants() { + get_inlay_hints(&mut res, &mut sb, file_id, &node, max_inlay_hint_length); + } + res } fn get_inlay_hints( + acc: &mut Vec, sb: &mut SourceBinder, file_id: FileId, node: &SyntaxNode, max_inlay_hint_length: Option, -) -> Option> { +) -> Option<()> { let _p = profile("get_inlay_hints"); let db = sb.db; let analyzer = Lazy::new(move || sb.analyze(hir::InFile::new(file_id.into(), node), None)); @@ -53,7 +54,7 @@ fn get_inlay_hints( return None; } let pat = it.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, false, max_inlay_hint_length)) + get_pat_type_hints(acc, db, &analyzer, pat, false, max_inlay_hint_length); }, ast::LambdaExpr(it) => { it.param_list().map(|param_list| { @@ -61,54 +62,50 @@ fn get_inlay_hints( .params() .filter(|closure_param| closure_param.ascribed_type().is_none()) .filter_map(|closure_param| closure_param.pat()) - .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, false, max_inlay_hint_length)) - .flatten() - .collect() - }) + .for_each(|root_pat| get_pat_type_hints(acc, db, &analyzer, root_pat, false, max_inlay_hint_length)) + }); }, ast::ForExpr(it) => { let pat = it.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, false, max_inlay_hint_length)) + get_pat_type_hints(acc, db, &analyzer, pat, false, max_inlay_hint_length); }, ast::IfExpr(it) => { let pat = it.condition()?.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, true, max_inlay_hint_length)) + get_pat_type_hints(acc, db, &analyzer, pat, true, max_inlay_hint_length); }, ast::WhileExpr(it) => { let pat = it.condition()?.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, true, max_inlay_hint_length)) + get_pat_type_hints(acc, db, &analyzer, pat, true, max_inlay_hint_length); }, ast::MatchArmList(it) => { - Some( - it - .arms() - .map(|match_arm| match_arm.pats()) - .flatten() - .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, true, max_inlay_hint_length)) - .flatten() - .collect(), - ) + it.arms() + .map(|match_arm| match_arm.pats()) + .flatten() + .for_each(|root_pat| get_pat_type_hints(acc, db, &analyzer, root_pat, true, max_inlay_hint_length)); }, ast::CallExpr(it) => { - get_param_name_hints(db, &analyzer, ast::Expr::from(it)) + get_param_name_hints(acc, db, &analyzer, ast::Expr::from(it)); }, ast::MethodCallExpr(it) => { - get_param_name_hints(db, &analyzer, ast::Expr::from(it)) + get_param_name_hints(acc, db, &analyzer, ast::Expr::from(it)); }, - _ => None, + _ => (), } - } + }; + Some(()) } + fn get_param_name_hints( + acc: &mut Vec, db: &RootDatabase, analyzer: &SourceAnalyzer, expr: ast::Expr, -) -> Option> { +) -> Option<()> { let args = match &expr { - ast::Expr::CallExpr(expr) => Some(expr.arg_list()?.args()), - ast::Expr::MethodCallExpr(expr) => Some(expr.arg_list()?.args()), - _ => None, - }?; + ast::Expr::CallExpr(expr) => expr.arg_list()?.args(), + ast::Expr::MethodCallExpr(expr) => expr.arg_list()?.args(), + _ => return None, + }; let mut parameters = get_fn_signature(db, analyzer, &expr)?.parameter_names.into_iter(); @@ -129,10 +126,10 @@ fn get_param_name_hints( range, kind: InlayKind::ParameterHint, label: param_name.into(), - }) - .collect(); + }); - Some(hints) + acc.extend(hints); + Some(()) } fn get_fn_signature( @@ -164,15 +161,16 @@ fn get_fn_signature( } fn get_pat_type_hints( + acc: &mut Vec, db: &RootDatabase, analyzer: &SourceAnalyzer, root_pat: ast::Pat, skip_root_pat_hint: bool, max_inlay_hint_length: Option, -) -> Vec { +) { let original_pat = &root_pat.clone(); - get_leaf_pats(root_pat) + let hints = get_leaf_pats(root_pat) .into_iter() .filter(|pat| !skip_root_pat_hint || pat != original_pat) .filter_map(|pat| { @@ -186,8 +184,9 @@ fn get_pat_type_hints( range, kind: InlayKind::TypeHint, label: pat_type.display_truncated(db, max_inlay_hint_length).to_string().into(), - }) - .collect() + }); + + acc.extend(hints); } fn get_leaf_pats(root_pat: ast::Pat) -> Vec { -- cgit v1.2.3