diff options
Diffstat (limited to 'crates/ra_ide/src/inlay_hints.rs')
-rw-r--r-- | crates/ra_ide/src/inlay_hints.rs | 68 |
1 files changed, 49 insertions, 19 deletions
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 45149bf0c..c5e406977 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs | |||
@@ -1,12 +1,15 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use crate::{db::RootDatabase, FileId}; | ||
4 | use hir::{HirDisplay, SourceAnalyzer}; | 3 | use hir::{HirDisplay, SourceAnalyzer}; |
4 | use once_cell::unsync::Lazy; | ||
5 | use ra_prof::profile; | ||
5 | use ra_syntax::{ | 6 | use ra_syntax::{ |
6 | ast::{self, AstNode, TypeAscriptionOwner}, | 7 | ast::{self, AstNode, TypeAscriptionOwner}, |
7 | match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange, | 8 | match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange, |
8 | }; | 9 | }; |
9 | 10 | ||
11 | use crate::{db::RootDatabase, FileId}; | ||
12 | |||
10 | #[derive(Debug, PartialEq, Eq)] | 13 | #[derive(Debug, PartialEq, Eq)] |
11 | pub enum InlayKind { | 14 | pub enum InlayKind { |
12 | TypeHint, | 15 | TypeHint, |
@@ -27,7 +30,7 @@ pub(crate) fn inlay_hints( | |||
27 | ) -> Vec<InlayHint> { | 30 | ) -> Vec<InlayHint> { |
28 | file.syntax() | 31 | file.syntax() |
29 | .descendants() | 32 | .descendants() |
30 | .map(|node| get_inlay_hints(db, file_id, &node, max_inlay_hint_length).unwrap_or_default()) | 33 | .flat_map(|node| get_inlay_hints(db, file_id, &node, max_inlay_hint_length)) |
31 | .flatten() | 34 | .flatten() |
32 | .collect() | 35 | .collect() |
33 | } | 36 | } |
@@ -38,7 +41,9 @@ fn get_inlay_hints( | |||
38 | node: &SyntaxNode, | 41 | node: &SyntaxNode, |
39 | max_inlay_hint_length: Option<usize>, | 42 | max_inlay_hint_length: Option<usize>, |
40 | ) -> Option<Vec<InlayHint>> { | 43 | ) -> Option<Vec<InlayHint>> { |
41 | let analyzer = SourceAnalyzer::new(db, hir::Source::new(file_id.into(), node), None); | 44 | let _p = profile("get_inlay_hints"); |
45 | let analyzer = | ||
46 | Lazy::new(|| SourceAnalyzer::new(db, hir::InFile::new(file_id.into(), node), None)); | ||
42 | match_ast! { | 47 | match_ast! { |
43 | match node { | 48 | match node { |
44 | ast::LetStmt(it) => { | 49 | ast::LetStmt(it) => { |
@@ -122,18 +127,11 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec<ast::Pat> { | |||
122 | 127 | ||
123 | while let Some(maybe_leaf_pat) = pats_to_process.pop_front() { | 128 | while let Some(maybe_leaf_pat) = pats_to_process.pop_front() { |
124 | match &maybe_leaf_pat { | 129 | match &maybe_leaf_pat { |
125 | ast::Pat::BindPat(bind_pat) => { | 130 | ast::Pat::BindPat(bind_pat) => match bind_pat.pat() { |
126 | if let Some(pat) = bind_pat.pat() { | 131 | Some(pat) => pats_to_process.push_back(pat), |
127 | pats_to_process.push_back(pat); | 132 | _ => leaf_pats.push(maybe_leaf_pat), |
128 | } else { | 133 | }, |
129 | leaf_pats.push(maybe_leaf_pat); | 134 | ast::Pat::TuplePat(tuple_pat) => pats_to_process.extend(tuple_pat.args()), |
130 | } | ||
131 | } | ||
132 | ast::Pat::TuplePat(tuple_pat) => { | ||
133 | for arg_pat in tuple_pat.args() { | ||
134 | pats_to_process.push_back(arg_pat); | ||
135 | } | ||
136 | } | ||
137 | ast::Pat::RecordPat(record_pat) => { | 135 | ast::Pat::RecordPat(record_pat) => { |
138 | if let Some(pat_list) = record_pat.record_field_pat_list() { | 136 | if let Some(pat_list) = record_pat.record_field_pat_list() { |
139 | pats_to_process.extend( | 137 | pats_to_process.extend( |
@@ -151,10 +149,9 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec<ast::Pat> { | |||
151 | } | 149 | } |
152 | } | 150 | } |
153 | ast::Pat::TupleStructPat(tuple_struct_pat) => { | 151 | ast::Pat::TupleStructPat(tuple_struct_pat) => { |
154 | for arg_pat in tuple_struct_pat.args() { | 152 | pats_to_process.extend(tuple_struct_pat.args()) |
155 | pats_to_process.push_back(arg_pat); | ||
156 | } | ||
157 | } | 153 | } |
154 | ast::Pat::RefPat(ref_pat) => pats_to_process.extend(ref_pat.pat()), | ||
158 | _ => (), | 155 | _ => (), |
159 | } | 156 | } |
160 | } | 157 | } |
@@ -163,9 +160,36 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec<ast::Pat> { | |||
163 | 160 | ||
164 | #[cfg(test)] | 161 | #[cfg(test)] |
165 | mod tests { | 162 | mod tests { |
166 | use crate::mock_analysis::single_file; | ||
167 | use insta::assert_debug_snapshot; | 163 | use insta::assert_debug_snapshot; |
168 | 164 | ||
165 | use crate::mock_analysis::single_file; | ||
166 | |||
167 | #[test] | ||
168 | fn default_generic_types_should_not_be_displayed() { | ||
169 | let (analysis, file_id) = single_file( | ||
170 | r#" | ||
171 | struct Test<K, T = u8> { | ||
172 | k: K, | ||
173 | t: T, | ||
174 | } | ||
175 | |||
176 | fn main() { | ||
177 | let zz = Test { t: 23, k: 33 }; | ||
178 | }"#, | ||
179 | ); | ||
180 | |||
181 | assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" | ||
182 | [ | ||
183 | InlayHint { | ||
184 | range: [69; 71), | ||
185 | kind: TypeHint, | ||
186 | label: "Test<i32>", | ||
187 | }, | ||
188 | ] | ||
189 | "### | ||
190 | ); | ||
191 | } | ||
192 | |||
169 | #[test] | 193 | #[test] |
170 | fn let_statement() { | 194 | fn let_statement() { |
171 | let (analysis, file_id) = single_file( | 195 | let (analysis, file_id) = single_file( |
@@ -202,6 +226,7 @@ fn main() { | |||
202 | 226 | ||
203 | let test = (42, 'a'); | 227 | let test = (42, 'a'); |
204 | let (a, (b, c, (d, e), f)) = (2, (3, 4, (6.6, 7.7), 5)); | 228 | let (a, (b, c, (d, e), f)) = (2, (3, 4, (6.6, 7.7), 5)); |
229 | let &x = &92; | ||
205 | }"#, | 230 | }"#, |
206 | ); | 231 | ); |
207 | 232 | ||
@@ -257,6 +282,11 @@ fn main() { | |||
257 | kind: TypeHint, | 282 | kind: TypeHint, |
258 | label: "f64", | 283 | label: "f64", |
259 | }, | 284 | }, |
285 | InlayHint { | ||
286 | range: [627; 628), | ||
287 | kind: TypeHint, | ||
288 | label: "i32", | ||
289 | }, | ||
260 | ] | 290 | ] |
261 | "### | 291 | "### |
262 | ); | 292 | ); |