aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-01-16 13:31:34 +0000
committerAleksey Kladov <[email protected]>2020-01-16 13:31:34 +0000
commit272f6dfd9eceb171b23200601201f3df95aa66c9 (patch)
treedfb27036b4cbb872b62b764d4c60c3aee60b1b6f /crates/ra_ide/src
parentbd96d0b258437cbfcaba5d0a6a79813eaa5f29fe (diff)
Micro-optimize type hints to avoid allocations
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r--crates/ra_ide/src/inlay_hints.rs77
1 files changed, 38 insertions, 39 deletions
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(
30 max_inlay_hint_length: Option<usize>, 30 max_inlay_hint_length: Option<usize>,
31) -> Vec<InlayHint> { 31) -> Vec<InlayHint> {
32 let mut sb = SourceBinder::new(db); 32 let mut sb = SourceBinder::new(db);
33 file.syntax() 33 let mut res = Vec::new();
34 .descendants() 34 for node in file.syntax().descendants() {
35 .flat_map(|node| get_inlay_hints(&mut sb, file_id, &node, max_inlay_hint_length)) 35 get_inlay_hints(&mut res, &mut sb, file_id, &node, max_inlay_hint_length);
36 .flatten() 36 }
37 .collect() 37 res
38} 38}
39 39
40fn get_inlay_hints( 40fn get_inlay_hints(
41 acc: &mut Vec<InlayHint>,
41 sb: &mut SourceBinder<RootDatabase>, 42 sb: &mut SourceBinder<RootDatabase>,
42 file_id: FileId, 43 file_id: FileId,
43 node: &SyntaxNode, 44 node: &SyntaxNode,
44 max_inlay_hint_length: Option<usize>, 45 max_inlay_hint_length: Option<usize>,
45) -> Option<Vec<InlayHint>> { 46) -> Option<()> {
46 let _p = profile("get_inlay_hints"); 47 let _p = profile("get_inlay_hints");
47 let db = sb.db; 48 let db = sb.db;
48 let analyzer = Lazy::new(move || sb.analyze(hir::InFile::new(file_id.into(), node), None)); 49 let analyzer = Lazy::new(move || sb.analyze(hir::InFile::new(file_id.into(), node), None));
@@ -53,7 +54,7 @@ fn get_inlay_hints(
53 return None; 54 return None;
54 } 55 }
55 let pat = it.pat()?; 56 let pat = it.pat()?;
56 Some(get_pat_type_hints(db, &analyzer, pat, false, max_inlay_hint_length)) 57 get_pat_type_hints(acc, db, &analyzer, pat, false, max_inlay_hint_length);
57 }, 58 },
58 ast::LambdaExpr(it) => { 59 ast::LambdaExpr(it) => {
59 it.param_list().map(|param_list| { 60 it.param_list().map(|param_list| {
@@ -61,54 +62,50 @@ fn get_inlay_hints(
61 .params() 62 .params()
62 .filter(|closure_param| closure_param.ascribed_type().is_none()) 63 .filter(|closure_param| closure_param.ascribed_type().is_none())
63 .filter_map(|closure_param| closure_param.pat()) 64 .filter_map(|closure_param| closure_param.pat())
64 .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, false, max_inlay_hint_length)) 65 .for_each(|root_pat| get_pat_type_hints(acc, db, &analyzer, root_pat, false, max_inlay_hint_length))
65 .flatten() 66 });
66 .collect()
67 })
68 }, 67 },
69 ast::ForExpr(it) => { 68 ast::ForExpr(it) => {
70 let pat = it.pat()?; 69 let pat = it.pat()?;
71 Some(get_pat_type_hints(db, &analyzer, pat, false, max_inlay_hint_length)) 70 get_pat_type_hints(acc, db, &analyzer, pat, false, max_inlay_hint_length);
72 }, 71 },
73 ast::IfExpr(it) => { 72 ast::IfExpr(it) => {
74 let pat = it.condition()?.pat()?; 73 let pat = it.condition()?.pat()?;
75 Some(get_pat_type_hints(db, &analyzer, pat, true, max_inlay_hint_length)) 74 get_pat_type_hints(acc, db, &analyzer, pat, true, max_inlay_hint_length);
76 }, 75 },
77 ast::WhileExpr(it) => { 76 ast::WhileExpr(it) => {
78 let pat = it.condition()?.pat()?; 77 let pat = it.condition()?.pat()?;
79 Some(get_pat_type_hints(db, &analyzer, pat, true, max_inlay_hint_length)) 78 get_pat_type_hints(acc, db, &analyzer, pat, true, max_inlay_hint_length);
80 }, 79 },
81 ast::MatchArmList(it) => { 80 ast::MatchArmList(it) => {
82 Some( 81 it.arms()
83 it 82 .map(|match_arm| match_arm.pats())
84 .arms() 83 .flatten()
85 .map(|match_arm| match_arm.pats()) 84 .for_each(|root_pat| get_pat_type_hints(acc, db, &analyzer, root_pat, true, max_inlay_hint_length));
86 .flatten()
87 .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, true, max_inlay_hint_length))
88 .flatten()
89 .collect(),
90 )
91 }, 85 },
92 ast::CallExpr(it) => { 86 ast::CallExpr(it) => {
93 get_param_name_hints(db, &analyzer, ast::Expr::from(it)) 87 get_param_name_hints(acc, db, &analyzer, ast::Expr::from(it));
94 }, 88 },
95 ast::MethodCallExpr(it) => { 89 ast::MethodCallExpr(it) => {
96 get_param_name_hints(db, &analyzer, ast::Expr::from(it)) 90 get_param_name_hints(acc, db, &analyzer, ast::Expr::from(it));
97 }, 91 },
98 _ => None, 92 _ => (),
99 } 93 }
100 } 94 };
95 Some(())
101} 96}
97
102fn get_param_name_hints( 98fn get_param_name_hints(
99 acc: &mut Vec<InlayHint>,
103 db: &RootDatabase, 100 db: &RootDatabase,
104 analyzer: &SourceAnalyzer, 101 analyzer: &SourceAnalyzer,
105 expr: ast::Expr, 102 expr: ast::Expr,
106) -> Option<Vec<InlayHint>> { 103) -> Option<()> {
107 let args = match &expr { 104 let args = match &expr {
108 ast::Expr::CallExpr(expr) => Some(expr.arg_list()?.args()), 105 ast::Expr::CallExpr(expr) => expr.arg_list()?.args(),
109 ast::Expr::MethodCallExpr(expr) => Some(expr.arg_list()?.args()), 106 ast::Expr::MethodCallExpr(expr) => expr.arg_list()?.args(),
110 _ => None, 107 _ => return None,
111 }?; 108 };
112 109
113 let mut parameters = get_fn_signature(db, analyzer, &expr)?.parameter_names.into_iter(); 110 let mut parameters = get_fn_signature(db, analyzer, &expr)?.parameter_names.into_iter();
114 111
@@ -129,10 +126,10 @@ fn get_param_name_hints(
129 range, 126 range,
130 kind: InlayKind::ParameterHint, 127 kind: InlayKind::ParameterHint,
131 label: param_name.into(), 128 label: param_name.into(),
132 }) 129 });
133 .collect();
134 130
135 Some(hints) 131 acc.extend(hints);
132 Some(())
136} 133}
137 134
138fn get_fn_signature( 135fn get_fn_signature(
@@ -164,15 +161,16 @@ fn get_fn_signature(
164} 161}
165 162
166fn get_pat_type_hints( 163fn get_pat_type_hints(
164 acc: &mut Vec<InlayHint>,
167 db: &RootDatabase, 165 db: &RootDatabase,
168 analyzer: &SourceAnalyzer, 166 analyzer: &SourceAnalyzer,
169 root_pat: ast::Pat, 167 root_pat: ast::Pat,
170 skip_root_pat_hint: bool, 168 skip_root_pat_hint: bool,
171 max_inlay_hint_length: Option<usize>, 169 max_inlay_hint_length: Option<usize>,
172) -> Vec<InlayHint> { 170) {
173 let original_pat = &root_pat.clone(); 171 let original_pat = &root_pat.clone();
174 172
175 get_leaf_pats(root_pat) 173 let hints = get_leaf_pats(root_pat)
176 .into_iter() 174 .into_iter()
177 .filter(|pat| !skip_root_pat_hint || pat != original_pat) 175 .filter(|pat| !skip_root_pat_hint || pat != original_pat)
178 .filter_map(|pat| { 176 .filter_map(|pat| {
@@ -186,8 +184,9 @@ fn get_pat_type_hints(
186 range, 184 range,
187 kind: InlayKind::TypeHint, 185 kind: InlayKind::TypeHint,
188 label: pat_type.display_truncated(db, max_inlay_hint_length).to_string().into(), 186 label: pat_type.display_truncated(db, max_inlay_hint_length).to_string().into(),
189 }) 187 });
190 .collect() 188
189 acc.extend(hints);
191} 190}
192 191
193fn get_leaf_pats(root_pat: ast::Pat) -> Vec<ast::Pat> { 192fn get_leaf_pats(root_pat: ast::Pat) -> Vec<ast::Pat> {