aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/inlay_hints.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-08-06 17:50:49 +0100
committerbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-08-06 17:50:49 +0100
commit7e12422fa2c8ba7b3df63b4e4297464a0071a359 (patch)
treef88de34c48e08ea8cf481a29f5764f13492a9ac9 /crates/ra_ide_api/src/inlay_hints.rs
parent811492aa546d83daf56f61d334d6ee295651f111 (diff)
parentc5598d9ade92e9ec4474a14229bb34a44a4edad5 (diff)
Merge #1652
1652: Improve type hints behavior r=matklad a=SomeoneToIgnore This PR fixed the following type hints issues: * Restructures the `InlayKind` enum contents based on the discussion here: https://github.com/rust-analyzer/rust-analyzer/pull/1606#issuecomment-515968055 * Races described in #1639 * Caches the latest decorations received for each file to show them the next time the file is opened (instead of a new server request) Co-authored-by: Kirill Bulatov <[email protected]>
Diffstat (limited to 'crates/ra_ide_api/src/inlay_hints.rs')
-rw-r--r--crates/ra_ide_api/src/inlay_hints.rs98
1 files changed, 41 insertions, 57 deletions
diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs
index a524e014f..7b9190314 100644
--- a/crates/ra_ide_api/src/inlay_hints.rs
+++ b/crates/ra_ide_api/src/inlay_hints.rs
@@ -9,14 +9,9 @@ use ra_syntax::{
9 SmolStr, SyntaxKind, SyntaxNode, TextRange, 9 SmolStr, SyntaxKind, SyntaxNode, TextRange,
10}; 10};
11 11
12#[derive(Debug, PartialEq, Eq, Clone)] 12#[derive(Debug, PartialEq, Eq)]
13pub enum InlayKind { 13pub enum InlayKind {
14 LetBindingType, 14 TypeHint,
15 ClosureParameterType,
16 ForExpressionBindingType,
17 IfExpressionType,
18 WhileLetExpressionType,
19 MatchArmType,
20} 15}
21 16
22#[derive(Debug)] 17#[derive(Debug)]
@@ -46,7 +41,7 @@ fn get_inlay_hints(
46 } 41 }
47 let pat = let_statement.pat()?; 42 let pat = let_statement.pat()?;
48 let analyzer = SourceAnalyzer::new(db, file_id, let_statement.syntax(), None); 43 let analyzer = SourceAnalyzer::new(db, file_id, let_statement.syntax(), None);
49 Some(get_pat_hints(db, &analyzer, pat, InlayKind::LetBindingType, false)) 44 Some(get_pat_type_hints(db, &analyzer, pat, false))
50 }) 45 })
51 .visit(|closure_parameter: LambdaExpr| { 46 .visit(|closure_parameter: LambdaExpr| {
52 let analyzer = SourceAnalyzer::new(db, file_id, closure_parameter.syntax(), None); 47 let analyzer = SourceAnalyzer::new(db, file_id, closure_parameter.syntax(), None);
@@ -55,15 +50,7 @@ fn get_inlay_hints(
55 .params() 50 .params()
56 .filter(|closure_param| closure_param.ascribed_type().is_none()) 51 .filter(|closure_param| closure_param.ascribed_type().is_none())
57 .filter_map(|closure_param| closure_param.pat()) 52 .filter_map(|closure_param| closure_param.pat())
58 .map(|root_pat| { 53 .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, false))
59 get_pat_hints(
60 db,
61 &analyzer,
62 root_pat,
63 InlayKind::ClosureParameterType,
64 false,
65 )
66 })
67 .flatten() 54 .flatten()
68 .collect() 55 .collect()
69 }) 56 })
@@ -71,17 +58,17 @@ fn get_inlay_hints(
71 .visit(|for_expression: ForExpr| { 58 .visit(|for_expression: ForExpr| {
72 let pat = for_expression.pat()?; 59 let pat = for_expression.pat()?;
73 let analyzer = SourceAnalyzer::new(db, file_id, for_expression.syntax(), None); 60 let analyzer = SourceAnalyzer::new(db, file_id, for_expression.syntax(), None);
74 Some(get_pat_hints(db, &analyzer, pat, InlayKind::ForExpressionBindingType, false)) 61 Some(get_pat_type_hints(db, &analyzer, pat, false))
75 }) 62 })
76 .visit(|if_expr: IfExpr| { 63 .visit(|if_expr: IfExpr| {
77 let pat = if_expr.condition()?.pat()?; 64 let pat = if_expr.condition()?.pat()?;
78 let analyzer = SourceAnalyzer::new(db, file_id, if_expr.syntax(), None); 65 let analyzer = SourceAnalyzer::new(db, file_id, if_expr.syntax(), None);
79 Some(get_pat_hints(db, &analyzer, pat, InlayKind::IfExpressionType, true)) 66 Some(get_pat_type_hints(db, &analyzer, pat, true))
80 }) 67 })
81 .visit(|while_expr: WhileExpr| { 68 .visit(|while_expr: WhileExpr| {
82 let pat = while_expr.condition()?.pat()?; 69 let pat = while_expr.condition()?.pat()?;
83 let analyzer = SourceAnalyzer::new(db, file_id, while_expr.syntax(), None); 70 let analyzer = SourceAnalyzer::new(db, file_id, while_expr.syntax(), None);
84 Some(get_pat_hints(db, &analyzer, pat, InlayKind::WhileLetExpressionType, true)) 71 Some(get_pat_type_hints(db, &analyzer, pat, true))
85 }) 72 })
86 .visit(|match_arm_list: MatchArmList| { 73 .visit(|match_arm_list: MatchArmList| {
87 let analyzer = SourceAnalyzer::new(db, file_id, match_arm_list.syntax(), None); 74 let analyzer = SourceAnalyzer::new(db, file_id, match_arm_list.syntax(), None);
@@ -90,9 +77,7 @@ fn get_inlay_hints(
90 .arms() 77 .arms()
91 .map(|match_arm| match_arm.pats()) 78 .map(|match_arm| match_arm.pats())
92 .flatten() 79 .flatten()
93 .map(|root_pat| { 80 .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, true))
94 get_pat_hints(db, &analyzer, root_pat, InlayKind::MatchArmType, true)
95 })
96 .flatten() 81 .flatten()
97 .collect(), 82 .collect(),
98 ) 83 )
@@ -100,11 +85,10 @@ fn get_inlay_hints(
100 .accept(&node)? 85 .accept(&node)?
101} 86}
102 87
103fn get_pat_hints( 88fn get_pat_type_hints(
104 db: &RootDatabase, 89 db: &RootDatabase,
105 analyzer: &SourceAnalyzer, 90 analyzer: &SourceAnalyzer,
106 root_pat: Pat, 91 root_pat: Pat,
107 kind: InlayKind,
108 skip_root_pat_hint: bool, 92 skip_root_pat_hint: bool,
109) -> Vec<InlayHint> { 93) -> Vec<InlayHint> {
110 let original_pat = &root_pat.clone(); 94 let original_pat = &root_pat.clone();
@@ -118,7 +102,7 @@ fn get_pat_hints(
118 }) 102 })
119 .map(|(range, pat_type)| InlayHint { 103 .map(|(range, pat_type)| InlayHint {
120 range, 104 range,
121 kind: kind.clone(), 105 kind: InlayKind::TypeHint,
122 label: pat_type.display(db).to_string().into(), 106 label: pat_type.display(db).to_string().into(),
123 }) 107 })
124 .collect() 108 .collect()
@@ -232,52 +216,52 @@ fn main() {
232 assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[ 216 assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[
233 InlayHint { 217 InlayHint {
234 range: [193; 197), 218 range: [193; 197),
235 kind: LetBindingType, 219 kind: TypeHint,
236 label: "i32", 220 label: "i32",
237 }, 221 },
238 InlayHint { 222 InlayHint {
239 range: [236; 244), 223 range: [236; 244),
240 kind: LetBindingType, 224 kind: TypeHint,
241 label: "i32", 225 label: "i32",
242 }, 226 },
243 InlayHint { 227 InlayHint {
244 range: [275; 279), 228 range: [275; 279),
245 kind: LetBindingType, 229 kind: TypeHint,
246 label: "&str", 230 label: "&str",
247 }, 231 },
248 InlayHint { 232 InlayHint {
249 range: [539; 543), 233 range: [539; 543),
250 kind: LetBindingType, 234 kind: TypeHint,
251 label: "(i32, char)", 235 label: "(i32, char)",
252 }, 236 },
253 InlayHint { 237 InlayHint {
254 range: [566; 567), 238 range: [566; 567),
255 kind: LetBindingType, 239 kind: TypeHint,
256 label: "i32", 240 label: "i32",
257 }, 241 },
258 InlayHint { 242 InlayHint {
259 range: [570; 571), 243 range: [570; 571),
260 kind: LetBindingType, 244 kind: TypeHint,
261 label: "i32", 245 label: "i32",
262 }, 246 },
263 InlayHint { 247 InlayHint {
264 range: [573; 574), 248 range: [573; 574),
265 kind: LetBindingType, 249 kind: TypeHint,
266 label: "i32", 250 label: "i32",
267 }, 251 },
268 InlayHint { 252 InlayHint {
269 range: [584; 585), 253 range: [584; 585),
270 kind: LetBindingType, 254 kind: TypeHint,
271 label: "i32", 255 label: "i32",
272 }, 256 },
273 InlayHint { 257 InlayHint {
274 range: [577; 578), 258 range: [577; 578),
275 kind: LetBindingType, 259 kind: TypeHint,
276 label: "f64", 260 label: "f64",
277 }, 261 },
278 InlayHint { 262 InlayHint {
279 range: [580; 581), 263 range: [580; 581),
280 kind: LetBindingType, 264 kind: TypeHint,
281 label: "f64", 265 label: "f64",
282 }, 266 },
283]"# 267]"#
@@ -299,12 +283,12 @@ fn main() {
299 assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[ 283 assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[
300 InlayHint { 284 InlayHint {
301 range: [21; 30), 285 range: [21; 30),
302 kind: LetBindingType, 286 kind: TypeHint,
303 label: "i32", 287 label: "i32",
304 }, 288 },
305 InlayHint { 289 InlayHint {
306 range: [57; 66), 290 range: [57; 66),
307 kind: ClosureParameterType, 291 kind: TypeHint,
308 label: "i32", 292 label: "i32",
309 }, 293 },
310]"# 294]"#
@@ -326,12 +310,12 @@ fn main() {
326 assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[ 310 assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[
327 InlayHint { 311 InlayHint {
328 range: [21; 30), 312 range: [21; 30),
329 kind: LetBindingType, 313 kind: TypeHint,
330 label: "i32", 314 label: "i32",
331 }, 315 },
332 InlayHint { 316 InlayHint {
333 range: [44; 53), 317 range: [44; 53),
334 kind: ForExpressionBindingType, 318 kind: TypeHint,
335 label: "i32", 319 label: "i32",
336 }, 320 },
337]"# 321]"#
@@ -364,7 +348,7 @@ fn main() {
364 if let CustomOption::Some(Test { a: CustomOption::Some(x), b: y }) = &test {}; 348 if let CustomOption::Some(Test { a: CustomOption::Some(x), b: y }) = &test {};
365 if let CustomOption::Some(Test { a: CustomOption::None, b: y }) = &test {}; 349 if let CustomOption::Some(Test { a: CustomOption::None, b: y }) = &test {};
366 if let CustomOption::Some(Test { b: y, .. }) = &test {}; 350 if let CustomOption::Some(Test { b: y, .. }) = &test {};
367 351
368 if test == CustomOption::None {} 352 if test == CustomOption::None {}
369}"#, 353}"#,
370 ); 354 );
@@ -372,27 +356,27 @@ fn main() {
372 assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[ 356 assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[
373 InlayHint { 357 InlayHint {
374 range: [166; 170), 358 range: [166; 170),
375 kind: LetBindingType, 359 kind: TypeHint,
376 label: "CustomOption<Test>", 360 label: "CustomOption<Test>",
377 }, 361 },
378 InlayHint { 362 InlayHint {
379 range: [334; 338), 363 range: [334; 338),
380 kind: IfExpressionType, 364 kind: TypeHint,
381 label: "&Test", 365 label: "&Test",
382 }, 366 },
383 InlayHint { 367 InlayHint {
384 range: [389; 390), 368 range: [389; 390),
385 kind: IfExpressionType, 369 kind: TypeHint,
386 label: "&CustomOption<u32>", 370 label: "&CustomOption<u32>",
387 }, 371 },
388 InlayHint { 372 InlayHint {
389 range: [392; 393), 373 range: [392; 393),
390 kind: IfExpressionType, 374 kind: TypeHint,
391 label: "&u8", 375 label: "&u8",
392 }, 376 },
393 InlayHint { 377 InlayHint {
394 range: [531; 532), 378 range: [531; 532),
395 kind: IfExpressionType, 379 kind: TypeHint,
396 label: "&u32", 380 label: "&u32",
397 }, 381 },
398]"# 382]"#
@@ -425,7 +409,7 @@ fn main() {
425 while let CustomOption::Some(Test { a: CustomOption::Some(x), b: y }) = &test {}; 409 while let CustomOption::Some(Test { a: CustomOption::Some(x), b: y }) = &test {};
426 while let CustomOption::Some(Test { a: CustomOption::None, b: y }) = &test {}; 410 while let CustomOption::Some(Test { a: CustomOption::None, b: y }) = &test {};
427 while let CustomOption::Some(Test { b: y, .. }) = &test {}; 411 while let CustomOption::Some(Test { b: y, .. }) = &test {};
428 412
429 while test == CustomOption::None {} 413 while test == CustomOption::None {}
430}"#, 414}"#,
431 ); 415 );
@@ -433,7 +417,7 @@ fn main() {
433 assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[ 417 assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[
434 InlayHint { 418 InlayHint {
435 range: [166; 170), 419 range: [166; 170),
436 kind: LetBindingType, 420 kind: TypeHint,
437 label: "CustomOption<Test>", 421 label: "CustomOption<Test>",
438 }, 422 },
439]"# 423]"#
@@ -445,7 +429,7 @@ fn main() {
445 let (analysis, file_id) = single_file( 429 let (analysis, file_id) = single_file(
446 r#" 430 r#"
447#[derive(PartialEq)] 431#[derive(PartialEq)]
448enum CustomOption<T> { 432enum CustomOption<T> {
449 None, 433 None,
450 Some(T), 434 Some(T),
451} 435}
@@ -473,23 +457,23 @@ fn main() {
473 457
474 assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[ 458 assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[
475 InlayHint { 459 InlayHint {
476 range: [312; 316), 460 range: [311; 315),
477 kind: MatchArmType, 461 kind: TypeHint,
478 label: "Test", 462 label: "Test",
479 }, 463 },
480 InlayHint { 464 InlayHint {
481 range: [359; 360), 465 range: [358; 359),
482 kind: MatchArmType, 466 kind: TypeHint,
483 label: "CustomOption<u32>", 467 label: "CustomOption<u32>",
484 }, 468 },
485 InlayHint { 469 InlayHint {
486 range: [362; 363), 470 range: [361; 362),
487 kind: MatchArmType, 471 kind: TypeHint,
488 label: "u8", 472 label: "u8",
489 }, 473 },
490 InlayHint { 474 InlayHint {
491 range: [485; 486), 475 range: [484; 485),
492 kind: MatchArmType, 476 kind: TypeHint,
493 label: "u32", 477 label: "u32",
494 }, 478 },
495]"# 479]"#