diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-08-06 17:50:49 +0100 |
---|---|---|
committer | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-08-06 17:50:49 +0100 |
commit | 7e12422fa2c8ba7b3df63b4e4297464a0071a359 (patch) | |
tree | f88de34c48e08ea8cf481a29f5764f13492a9ac9 | |
parent | 811492aa546d83daf56f61d334d6ee295651f111 (diff) | |
parent | c5598d9ade92e9ec4474a14229bb34a44a4edad5 (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]>
-rw-r--r-- | crates/ra_ide_api/src/inlay_hints.rs | 98 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 9 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/req.rs | 7 | ||||
-rw-r--r-- | editors/code/src/commands/inlay_hints.ts | 76 | ||||
-rw-r--r-- | editors/code/src/extension.ts | 20 |
5 files changed, 98 insertions, 112 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)] |
13 | pub enum InlayKind { | 13 | pub 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 | ||
103 | fn get_pat_hints( | 88 | fn 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)] |
448 | enum CustomOption<T> { | 432 | enum 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 | ]"# |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 005ce08b3..686ee5d12 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -885,14 +885,7 @@ pub fn handle_inlay_hints( | |||
885 | label: api_type.label.to_string(), | 885 | label: api_type.label.to_string(), |
886 | range: api_type.range.conv_with(&line_index), | 886 | range: api_type.range.conv_with(&line_index), |
887 | kind: match api_type.kind { | 887 | kind: match api_type.kind { |
888 | ra_ide_api::InlayKind::LetBindingType => InlayKind::LetBindingType, | 888 | ra_ide_api::InlayKind::TypeHint => InlayKind::TypeHint, |
889 | ra_ide_api::InlayKind::ClosureParameterType => InlayKind::ClosureParameterType, | ||
890 | ra_ide_api::InlayKind::ForExpressionBindingType => { | ||
891 | InlayKind::ForExpressionBindingType | ||
892 | } | ||
893 | ra_ide_api::InlayKind::IfExpressionType => InlayKind::IfExpressionType, | ||
894 | ra_ide_api::InlayKind::WhileLetExpressionType => InlayKind::WhileLetExpressionType, | ||
895 | ra_ide_api::InlayKind::MatchArmType => InlayKind::MatchArmType, | ||
896 | }, | 889 | }, |
897 | }) | 890 | }) |
898 | .collect()) | 891 | .collect()) |
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs index 570438643..6b986bcc9 100644 --- a/crates/ra_lsp_server/src/req.rs +++ b/crates/ra_lsp_server/src/req.rs | |||
@@ -213,12 +213,7 @@ pub struct InlayHintsParams { | |||
213 | 213 | ||
214 | #[derive(Debug, PartialEq, Eq, Deserialize, Serialize)] | 214 | #[derive(Debug, PartialEq, Eq, Deserialize, Serialize)] |
215 | pub enum InlayKind { | 215 | pub enum InlayKind { |
216 | LetBindingType, | 216 | TypeHint, |
217 | ClosureParameterType, | ||
218 | ForExpressionBindingType, | ||
219 | IfExpressionType, | ||
220 | WhileLetExpressionType, | ||
221 | MatchArmType, | ||
222 | } | 217 | } |
223 | 218 | ||
224 | #[derive(Debug, Deserialize, Serialize)] | 219 | #[derive(Debug, Deserialize, Serialize)] |
diff --git a/editors/code/src/commands/inlay_hints.ts b/editors/code/src/commands/inlay_hints.ts index 3ba9da48b..5393a2bc9 100644 --- a/editors/code/src/commands/inlay_hints.ts +++ b/editors/code/src/commands/inlay_hints.ts | |||
@@ -22,53 +22,56 @@ const typeHintDecorationType = vscode.window.createTextEditorDecorationType({ | |||
22 | export class HintsUpdater { | 22 | export class HintsUpdater { |
23 | private displayHints = true; | 23 | private displayHints = true; |
24 | 24 | ||
25 | public async loadHints( | ||
26 | editor: vscode.TextEditor | undefined | ||
27 | ): Promise<void> { | ||
28 | if ( | ||
29 | this.displayHints && | ||
30 | editor !== undefined && | ||
31 | this.isRustDocument(editor.document) | ||
32 | ) { | ||
33 | await this.updateDecorationsFromServer( | ||
34 | editor.document.uri.toString(), | ||
35 | editor | ||
36 | ); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | public async toggleHintsDisplay(displayHints: boolean): Promise<void> { | 25 | public async toggleHintsDisplay(displayHints: boolean): Promise<void> { |
41 | if (this.displayHints !== displayHints) { | 26 | if (this.displayHints !== displayHints) { |
42 | this.displayHints = displayHints; | 27 | this.displayHints = displayHints; |
43 | 28 | return this.refreshVisibleEditorsHints( | |
44 | if (displayHints) { | 29 | displayHints ? undefined : [] |
45 | return this.updateHints(); | 30 | ); |
46 | } else { | ||
47 | const editor = vscode.window.activeTextEditor; | ||
48 | if (editor != null) { | ||
49 | return editor.setDecorations(typeHintDecorationType, []); | ||
50 | } | ||
51 | } | ||
52 | } | 31 | } |
53 | } | 32 | } |
54 | 33 | ||
55 | public async updateHints(cause?: TextDocumentChangeEvent): Promise<void> { | 34 | public async refreshHintsForVisibleEditors( |
35 | cause?: TextDocumentChangeEvent | ||
36 | ): Promise<void> { | ||
56 | if (!this.displayHints) { | 37 | if (!this.displayHints) { |
57 | return; | 38 | return; |
58 | } | 39 | } |
59 | const editor = vscode.window.activeTextEditor; | 40 | if ( |
60 | if (editor == null) { | 41 | cause !== undefined && |
42 | (cause.contentChanges.length === 0 || | ||
43 | !this.isRustDocument(cause.document)) | ||
44 | ) { | ||
61 | return; | 45 | return; |
62 | } | 46 | } |
63 | const document = cause == null ? editor.document : cause.document; | 47 | return this.refreshVisibleEditorsHints(); |
64 | if (!this.isRustDocument(document)) { | 48 | } |
65 | return; | 49 | |
50 | private async refreshVisibleEditorsHints( | ||
51 | newDecorations?: vscode.DecorationOptions[] | ||
52 | ) { | ||
53 | const promises: Array<Promise<void>> = []; | ||
54 | |||
55 | for (const rustEditor of vscode.window.visibleTextEditors.filter( | ||
56 | editor => this.isRustDocument(editor.document) | ||
57 | )) { | ||
58 | if (newDecorations !== undefined) { | ||
59 | promises.push( | ||
60 | Promise.resolve( | ||
61 | rustEditor.setDecorations( | ||
62 | typeHintDecorationType, | ||
63 | newDecorations | ||
64 | ) | ||
65 | ) | ||
66 | ); | ||
67 | } else { | ||
68 | promises.push(this.updateDecorationsFromServer(rustEditor)); | ||
69 | } | ||
66 | } | 70 | } |
67 | 71 | ||
68 | return await this.updateDecorationsFromServer( | 72 | for (const promise of promises) { |
69 | document.uri.toString(), | 73 | await promise; |
70 | editor | 74 | } |
71 | ); | ||
72 | } | 75 | } |
73 | 76 | ||
74 | private isRustDocument(document: vscode.TextDocument): boolean { | 77 | private isRustDocument(document: vscode.TextDocument): boolean { |
@@ -76,11 +79,10 @@ export class HintsUpdater { | |||
76 | } | 79 | } |
77 | 80 | ||
78 | private async updateDecorationsFromServer( | 81 | private async updateDecorationsFromServer( |
79 | documentUri: string, | ||
80 | editor: TextEditor | 82 | editor: TextEditor |
81 | ): Promise<void> { | 83 | ): Promise<void> { |
82 | const newHints = await this.queryHints(documentUri); | 84 | const newHints = await this.queryHints(editor.document.uri.toString()); |
83 | if (newHints != null) { | 85 | if (newHints !== null) { |
84 | const newDecorations = newHints.map(hint => ({ | 86 | const newDecorations = newHints.map(hint => ({ |
85 | range: hint.range, | 87 | range: hint.range, |
86 | renderOptions: { after: { contentText: `: ${hint.label}` } } | 88 | renderOptions: { after: { contentText: `: ${hint.label}` } } |
diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index c6efc2e7e..39fe6efd8 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts | |||
@@ -151,15 +151,27 @@ export function activate(context: vscode.ExtensionContext) { | |||
151 | 151 | ||
152 | if (Server.config.displayInlayHints) { | 152 | if (Server.config.displayInlayHints) { |
153 | const hintsUpdater = new HintsUpdater(); | 153 | const hintsUpdater = new HintsUpdater(); |
154 | hintsUpdater.loadHints(vscode.window.activeTextEditor).then(() => { | 154 | hintsUpdater.refreshHintsForVisibleEditors().then(() => { |
155 | // vscode may ignore top level hintsUpdater.refreshHintsForVisibleEditors() | ||
156 | // so update the hints once when the focus changes to guarantee their presence | ||
157 | let editorChangeDisposable: vscode.Disposable | null = null; | ||
158 | editorChangeDisposable = vscode.window.onDidChangeActiveTextEditor( | ||
159 | _ => { | ||
160 | if (editorChangeDisposable !== null) { | ||
161 | editorChangeDisposable.dispose(); | ||
162 | } | ||
163 | return hintsUpdater.refreshHintsForVisibleEditors(); | ||
164 | } | ||
165 | ); | ||
166 | |||
155 | disposeOnDeactivation( | 167 | disposeOnDeactivation( |
156 | vscode.window.onDidChangeActiveTextEditor(editor => | 168 | vscode.window.onDidChangeVisibleTextEditors(_ => |
157 | hintsUpdater.loadHints(editor) | 169 | hintsUpdater.refreshHintsForVisibleEditors() |
158 | ) | 170 | ) |
159 | ); | 171 | ); |
160 | disposeOnDeactivation( | 172 | disposeOnDeactivation( |
161 | vscode.workspace.onDidChangeTextDocument(e => | 173 | vscode.workspace.onDidChangeTextDocument(e => |
162 | hintsUpdater.updateHints(e) | 174 | hintsUpdater.refreshHintsForVisibleEditors(e) |
163 | ) | 175 | ) |
164 | ); | 176 | ); |
165 | disposeOnDeactivation( | 177 | disposeOnDeactivation( |