diff options
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r-- | crates/ra_ide/src/completion/complete_unqualified_path.rs | 17 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_item.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/test_utils.rs | 22 | ||||
-rw-r--r-- | crates/ra_ide/src/diagnostics.rs | 684 | ||||
-rw-r--r-- | crates/ra_ide/src/inlay_hints.rs | 94 | ||||
-rw-r--r-- | crates/ra_ide/src/mock_analysis.rs | 20 |
7 files changed, 360 insertions, 483 deletions
diff --git a/crates/ra_ide/src/completion/complete_unqualified_path.rs b/crates/ra_ide/src/completion/complete_unqualified_path.rs index 72ff82e66..18f4488b7 100644 --- a/crates/ra_ide/src/completion/complete_unqualified_path.rs +++ b/crates/ra_ide/src/completion/complete_unqualified_path.rs | |||
@@ -638,4 +638,21 @@ fn f() {} | |||
638 | expect![[""]], | 638 | expect![[""]], |
639 | ) | 639 | ) |
640 | } | 640 | } |
641 | |||
642 | #[test] | ||
643 | fn completes_type_or_trait_in_impl_block() { | ||
644 | check( | ||
645 | r#" | ||
646 | trait MyTrait {} | ||
647 | struct MyStruct {} | ||
648 | |||
649 | impl My<|> | ||
650 | "#, | ||
651 | expect![[r#" | ||
652 | st MyStruct | ||
653 | tt MyTrait | ||
654 | tp Self | ||
655 | "#]], | ||
656 | ) | ||
657 | } | ||
641 | } | 658 | } |
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index d7011c9cf..7bdda316c 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs | |||
@@ -58,7 +58,7 @@ pub struct CompletionItem { | |||
58 | score: Option<CompletionScore>, | 58 | score: Option<CompletionScore>, |
59 | } | 59 | } |
60 | 60 | ||
61 | // We use custom debug for CompletionItem to make `insta`'s diffs more readable. | 61 | // We use custom debug for CompletionItem to make snapshot tests more readable. |
62 | impl fmt::Debug for CompletionItem { | 62 | impl fmt::Debug for CompletionItem { |
63 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 63 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
64 | let mut s = f.debug_struct("CompletionItem"); | 64 | let mut s = f.debug_struct("CompletionItem"); |
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index e4c57e41a..48afee5fb 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -491,7 +491,7 @@ mod tests { | |||
491 | } | 491 | } |
492 | } | 492 | } |
493 | 493 | ||
494 | let mut completions = get_all_completion_items(ra_fixture, &CompletionConfig::default()); | 494 | let mut completions = get_all_completion_items(CompletionConfig::default(), ra_fixture); |
495 | completions.sort_by_key(|it| (Reverse(it.score()), it.label().to_string())); | 495 | completions.sort_by_key(|it| (Reverse(it.score()), it.label().to_string())); |
496 | let actual = completions | 496 | let actual = completions |
497 | .into_iter() | 497 | .into_iter() |
@@ -835,6 +835,7 @@ fn bar(s: &S) { | |||
835 | fn suppress_arg_snippets() { | 835 | fn suppress_arg_snippets() { |
836 | mark::check!(suppress_arg_snippets); | 836 | mark::check!(suppress_arg_snippets); |
837 | check_edit_with_config( | 837 | check_edit_with_config( |
838 | CompletionConfig { add_call_argument_snippets: false, ..CompletionConfig::default() }, | ||
838 | "with_args", | 839 | "with_args", |
839 | r#" | 840 | r#" |
840 | fn with_args(x: i32, y: String) {} | 841 | fn with_args(x: i32, y: String) {} |
@@ -844,7 +845,6 @@ fn main() { with_<|> } | |||
844 | fn with_args(x: i32, y: String) {} | 845 | fn with_args(x: i32, y: String) {} |
845 | fn main() { with_args($0) } | 846 | fn main() { with_args($0) } |
846 | "#, | 847 | "#, |
847 | &CompletionConfig { add_call_argument_snippets: false, ..CompletionConfig::default() }, | ||
848 | ); | 848 | ); |
849 | } | 849 | } |
850 | 850 | ||
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs index c2be23697..919177745 100644 --- a/crates/ra_ide/src/completion/test_utils.rs +++ b/crates/ra_ide/src/completion/test_utils.rs | |||
@@ -13,15 +13,15 @@ use crate::{ | |||
13 | }; | 13 | }; |
14 | 14 | ||
15 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { | 15 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { |
16 | do_completion_with_config(code, kind, &CompletionConfig::default()) | 16 | do_completion_with_config(CompletionConfig::default(), code, kind) |
17 | } | 17 | } |
18 | 18 | ||
19 | pub(crate) fn do_completion_with_config( | 19 | pub(crate) fn do_completion_with_config( |
20 | config: CompletionConfig, | ||
20 | code: &str, | 21 | code: &str, |
21 | kind: CompletionKind, | 22 | kind: CompletionKind, |
22 | config: &CompletionConfig, | ||
23 | ) -> Vec<CompletionItem> { | 23 | ) -> Vec<CompletionItem> { |
24 | let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(code, config) | 24 | let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(config, code) |
25 | .into_iter() | 25 | .into_iter() |
26 | .filter(|c| c.completion_kind == kind) | 26 | .filter(|c| c.completion_kind == kind) |
27 | .collect(); | 27 | .collect(); |
@@ -30,15 +30,15 @@ pub(crate) fn do_completion_with_config( | |||
30 | } | 30 | } |
31 | 31 | ||
32 | pub(crate) fn completion_list(code: &str, kind: CompletionKind) -> String { | 32 | pub(crate) fn completion_list(code: &str, kind: CompletionKind) -> String { |
33 | completion_list_with_config(code, kind, &CompletionConfig::default()) | 33 | completion_list_with_config(CompletionConfig::default(), code, kind) |
34 | } | 34 | } |
35 | 35 | ||
36 | pub(crate) fn completion_list_with_config( | 36 | pub(crate) fn completion_list_with_config( |
37 | config: CompletionConfig, | ||
37 | code: &str, | 38 | code: &str, |
38 | kind: CompletionKind, | 39 | kind: CompletionKind, |
39 | config: &CompletionConfig, | ||
40 | ) -> String { | 40 | ) -> String { |
41 | let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(code, config) | 41 | let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(config, code) |
42 | .into_iter() | 42 | .into_iter() |
43 | .filter(|c| c.completion_kind == kind) | 43 | .filter(|c| c.completion_kind == kind) |
44 | .collect(); | 44 | .collect(); |
@@ -70,19 +70,19 @@ fn monospace_width(s: &str) -> usize { | |||
70 | } | 70 | } |
71 | 71 | ||
72 | pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) { | 72 | pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) { |
73 | check_edit_with_config(what, ra_fixture_before, ra_fixture_after, &CompletionConfig::default()) | 73 | check_edit_with_config(CompletionConfig::default(), what, ra_fixture_before, ra_fixture_after) |
74 | } | 74 | } |
75 | 75 | ||
76 | pub(crate) fn check_edit_with_config( | 76 | pub(crate) fn check_edit_with_config( |
77 | config: CompletionConfig, | ||
77 | what: &str, | 78 | what: &str, |
78 | ra_fixture_before: &str, | 79 | ra_fixture_before: &str, |
79 | ra_fixture_after: &str, | 80 | ra_fixture_after: &str, |
80 | config: &CompletionConfig, | ||
81 | ) { | 81 | ) { |
82 | let ra_fixture_after = trim_indent(ra_fixture_after); | 82 | let ra_fixture_after = trim_indent(ra_fixture_after); |
83 | let (analysis, position) = analysis_and_position(ra_fixture_before); | 83 | let (analysis, position) = analysis_and_position(ra_fixture_before); |
84 | let completions: Vec<CompletionItem> = | 84 | let completions: Vec<CompletionItem> = |
85 | analysis.completions(config, position).unwrap().unwrap().into(); | 85 | analysis.completions(&config, position).unwrap().unwrap().into(); |
86 | let (completion,) = completions | 86 | let (completion,) = completions |
87 | .iter() | 87 | .iter() |
88 | .filter(|it| it.lookup() == what) | 88 | .filter(|it| it.lookup() == what) |
@@ -106,9 +106,9 @@ pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) - | |||
106 | } | 106 | } |
107 | 107 | ||
108 | pub(crate) fn get_all_completion_items( | 108 | pub(crate) fn get_all_completion_items( |
109 | config: CompletionConfig, | ||
109 | code: &str, | 110 | code: &str, |
110 | options: &CompletionConfig, | ||
111 | ) -> Vec<CompletionItem> { | 111 | ) -> Vec<CompletionItem> { |
112 | let (analysis, position) = analysis_and_position(code); | 112 | let (analysis, position) = analysis_and_position(code); |
113 | analysis.completions(options, position).unwrap().unwrap().into() | 113 | analysis.completions(&config, position).unwrap().unwrap().into() |
114 | } | 114 | } |
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index f4bc0d619..e69e9b4ec 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs | |||
@@ -273,53 +273,21 @@ fn check_struct_shorthand_initialization( | |||
273 | 273 | ||
274 | #[cfg(test)] | 274 | #[cfg(test)] |
275 | mod tests { | 275 | mod tests { |
276 | use insta::assert_debug_snapshot; | ||
277 | use ra_syntax::SourceFile; | ||
278 | use stdx::trim_indent; | 276 | use stdx::trim_indent; |
279 | use test_utils::assert_eq_text; | 277 | use test_utils::assert_eq_text; |
280 | 278 | ||
281 | use crate::mock_analysis::{analysis_and_position, single_file}; | 279 | use crate::mock_analysis::{analysis_and_position, single_file, MockAnalysis}; |
282 | 280 | use expect::{expect, Expect}; | |
283 | use super::*; | ||
284 | |||
285 | type DiagnosticChecker = fn(&mut Vec<Diagnostic>, FileId, &SyntaxNode) -> Option<()>; | ||
286 | |||
287 | fn check_not_applicable(code: &str, func: DiagnosticChecker) { | ||
288 | let parse = SourceFile::parse(code); | ||
289 | let mut diagnostics = Vec::new(); | ||
290 | for node in parse.tree().syntax().descendants() { | ||
291 | func(&mut diagnostics, FileId(0), &node); | ||
292 | } | ||
293 | assert!(diagnostics.is_empty()); | ||
294 | } | ||
295 | |||
296 | fn check_apply(before: &str, after: &str, func: DiagnosticChecker) { | ||
297 | let parse = SourceFile::parse(before); | ||
298 | let mut diagnostics = Vec::new(); | ||
299 | for node in parse.tree().syntax().descendants() { | ||
300 | func(&mut diagnostics, FileId(0), &node); | ||
301 | } | ||
302 | let diagnostic = | ||
303 | diagnostics.pop().unwrap_or_else(|| panic!("no diagnostics for:\n{}\n", before)); | ||
304 | let mut fix = diagnostic.fix.unwrap(); | ||
305 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; | ||
306 | let actual = { | ||
307 | let mut actual = before.to_string(); | ||
308 | edit.apply(&mut actual); | ||
309 | actual | ||
310 | }; | ||
311 | assert_eq_text!(after, &actual); | ||
312 | } | ||
313 | 281 | ||
314 | /// Takes a multi-file input fixture with annotated cursor positions, | 282 | /// Takes a multi-file input fixture with annotated cursor positions, |
315 | /// and checks that: | 283 | /// and checks that: |
316 | /// * a diagnostic is produced | 284 | /// * a diagnostic is produced |
317 | /// * this diagnostic touches the input cursor position | 285 | /// * this diagnostic touches the input cursor position |
318 | /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied | 286 | /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied |
319 | fn check_apply_diagnostic_fix_from_position(ra_fixture: &str, after: &str) { | 287 | fn check_fix(ra_fixture_before: &str, ra_fixture_after: &str) { |
320 | let after = trim_indent(after); | 288 | let after = trim_indent(ra_fixture_after); |
321 | 289 | ||
322 | let (analysis, file_position) = analysis_and_position(ra_fixture); | 290 | let (analysis, file_position) = analysis_and_position(ra_fixture_before); |
323 | let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap(); | 291 | let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap(); |
324 | let mut fix = diagnostic.fix.unwrap(); | 292 | let mut fix = diagnostic.fix.unwrap(); |
325 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; | 293 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; |
@@ -340,284 +308,251 @@ mod tests { | |||
340 | ); | 308 | ); |
341 | } | 309 | } |
342 | 310 | ||
343 | fn check_apply_diagnostic_fix(ra_fixture_before: &str, ra_fixture_after: &str) { | ||
344 | let ra_fixture_after = &trim_indent(ra_fixture_after); | ||
345 | let (analysis, file_id) = single_file(ra_fixture_before); | ||
346 | let before = analysis.file_text(file_id).unwrap(); | ||
347 | let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap(); | ||
348 | let mut fix = diagnostic.fix.unwrap(); | ||
349 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; | ||
350 | let actual = { | ||
351 | let mut actual = before.to_string(); | ||
352 | edit.apply(&mut actual); | ||
353 | actual | ||
354 | }; | ||
355 | assert_eq_text!(ra_fixture_after, &actual); | ||
356 | } | ||
357 | |||
358 | /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics | 311 | /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics |
359 | /// apply to the file containing the cursor. | 312 | /// apply to the file containing the cursor. |
360 | fn check_no_diagnostic_for_target_file(ra_fixture: &str) { | 313 | fn check_no_diagnostics(ra_fixture: &str) { |
361 | let (analysis, file_position) = analysis_and_position(ra_fixture); | 314 | let mock = MockAnalysis::with_files(ra_fixture); |
362 | let diagnostics = analysis.diagnostics(file_position.file_id).unwrap(); | 315 | let files = mock.files().map(|(it, _)| it).collect::<Vec<_>>(); |
363 | assert_eq!(diagnostics.len(), 0); | 316 | let analysis = mock.analysis(); |
364 | } | 317 | let diagnostics = files |
365 | 318 | .into_iter() | |
366 | fn check_no_diagnostic(ra_fixture: &str) { | 319 | .flat_map(|file_id| analysis.diagnostics(file_id).unwrap()) |
320 | .collect::<Vec<_>>(); | ||
321 | assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics); | ||
322 | } | ||
323 | |||
324 | fn check_expect(ra_fixture: &str, expect: Expect) { | ||
367 | let (analysis, file_id) = single_file(ra_fixture); | 325 | let (analysis, file_id) = single_file(ra_fixture); |
368 | let diagnostics = analysis.diagnostics(file_id).unwrap(); | 326 | let diagnostics = analysis.diagnostics(file_id).unwrap(); |
369 | assert_eq!(diagnostics.len(), 0, "expected no diagnostic, found one"); | 327 | expect.assert_debug_eq(&diagnostics) |
370 | } | 328 | } |
371 | 329 | ||
372 | #[test] | 330 | #[test] |
373 | fn test_wrap_return_type() { | 331 | fn test_wrap_return_type() { |
374 | let before = r#" | 332 | check_fix( |
375 | //- /main.rs | 333 | r#" |
376 | use core::result::Result::{self, Ok, Err}; | 334 | //- /main.rs |
377 | 335 | use core::result::Result::{self, Ok, Err}; | |
378 | fn div(x: i32, y: i32) -> Result<i32, ()> { | 336 | |
379 | if y == 0 { | 337 | fn div(x: i32, y: i32) -> Result<i32, ()> { |
380 | return Err(()); | 338 | if y == 0 { |
381 | } | 339 | return Err(()); |
382 | x / y<|> | 340 | } |
383 | } | 341 | x / y<|> |
384 | //- /core/lib.rs | 342 | } |
385 | pub mod result { | 343 | //- /core/lib.rs |
386 | pub enum Result<T, E> { Ok(T), Err(E) } | 344 | pub mod result { |
387 | } | 345 | pub enum Result<T, E> { Ok(T), Err(E) } |
388 | "#; | 346 | } |
389 | let after = r#" | 347 | "#, |
390 | use core::result::Result::{self, Ok, Err}; | 348 | r#" |
391 | 349 | use core::result::Result::{self, Ok, Err}; | |
392 | fn div(x: i32, y: i32) -> Result<i32, ()> { | 350 | |
393 | if y == 0 { | 351 | fn div(x: i32, y: i32) -> Result<i32, ()> { |
394 | return Err(()); | 352 | if y == 0 { |
395 | } | 353 | return Err(()); |
396 | Ok(x / y) | 354 | } |
397 | } | 355 | Ok(x / y) |
398 | "#; | 356 | } |
399 | check_apply_diagnostic_fix_from_position(before, after); | 357 | "#, |
358 | ); | ||
400 | } | 359 | } |
401 | 360 | ||
402 | #[test] | 361 | #[test] |
403 | fn test_wrap_return_type_handles_generic_functions() { | 362 | fn test_wrap_return_type_handles_generic_functions() { |
404 | let before = r#" | 363 | check_fix( |
405 | //- /main.rs | 364 | r#" |
406 | use core::result::Result::{self, Ok, Err}; | 365 | //- /main.rs |
407 | 366 | use core::result::Result::{self, Ok, Err}; | |
408 | fn div<T>(x: T) -> Result<T, i32> { | 367 | |
409 | if x == 0 { | 368 | fn div<T>(x: T) -> Result<T, i32> { |
410 | return Err(7); | 369 | if x == 0 { |
411 | } | 370 | return Err(7); |
412 | <|>x | 371 | } |
413 | } | 372 | <|>x |
414 | //- /core/lib.rs | 373 | } |
415 | pub mod result { | 374 | //- /core/lib.rs |
416 | pub enum Result<T, E> { Ok(T), Err(E) } | 375 | pub mod result { |
417 | } | 376 | pub enum Result<T, E> { Ok(T), Err(E) } |
418 | "#; | 377 | } |
419 | let after = r#" | 378 | "#, |
420 | use core::result::Result::{self, Ok, Err}; | 379 | r#" |
421 | 380 | use core::result::Result::{self, Ok, Err}; | |
422 | fn div<T>(x: T) -> Result<T, i32> { | 381 | |
423 | if x == 0 { | 382 | fn div<T>(x: T) -> Result<T, i32> { |
424 | return Err(7); | 383 | if x == 0 { |
425 | } | 384 | return Err(7); |
426 | Ok(x) | 385 | } |
427 | } | 386 | Ok(x) |
428 | "#; | 387 | } |
429 | check_apply_diagnostic_fix_from_position(before, after); | 388 | "#, |
389 | ); | ||
430 | } | 390 | } |
431 | 391 | ||
432 | #[test] | 392 | #[test] |
433 | fn test_wrap_return_type_handles_type_aliases() { | 393 | fn test_wrap_return_type_handles_type_aliases() { |
434 | let before = r#" | 394 | check_fix( |
435 | //- /main.rs | 395 | r#" |
436 | use core::result::Result::{self, Ok, Err}; | 396 | //- /main.rs |
397 | use core::result::Result::{self, Ok, Err}; | ||
437 | 398 | ||
438 | type MyResult<T> = Result<T, ()>; | 399 | type MyResult<T> = Result<T, ()>; |
439 | 400 | ||
440 | fn div(x: i32, y: i32) -> MyResult<i32> { | 401 | fn div(x: i32, y: i32) -> MyResult<i32> { |
441 | if y == 0 { | 402 | if y == 0 { |
442 | return Err(()); | 403 | return Err(()); |
443 | } | 404 | } |
444 | x <|>/ y | 405 | x <|>/ y |
445 | } | 406 | } |
446 | //- /core/lib.rs | 407 | //- /core/lib.rs |
447 | pub mod result { | 408 | pub mod result { |
448 | pub enum Result<T, E> { Ok(T), Err(E) } | 409 | pub enum Result<T, E> { Ok(T), Err(E) } |
449 | } | 410 | } |
450 | "#; | 411 | "#, |
451 | let after = r#" | 412 | r#" |
452 | use core::result::Result::{self, Ok, Err}; | 413 | use core::result::Result::{self, Ok, Err}; |
453 | 414 | ||
454 | type MyResult<T> = Result<T, ()>; | 415 | type MyResult<T> = Result<T, ()>; |
455 | 416 | ||
456 | fn div(x: i32, y: i32) -> MyResult<i32> { | 417 | fn div(x: i32, y: i32) -> MyResult<i32> { |
457 | if y == 0 { | 418 | if y == 0 { |
458 | return Err(()); | 419 | return Err(()); |
459 | } | 420 | } |
460 | Ok(x / y) | 421 | Ok(x / y) |
461 | } | 422 | } |
462 | "#; | 423 | "#, |
463 | check_apply_diagnostic_fix_from_position(before, after); | 424 | ); |
464 | } | 425 | } |
465 | 426 | ||
466 | #[test] | 427 | #[test] |
467 | fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() { | 428 | fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() { |
468 | check_no_diagnostic_for_target_file( | 429 | check_no_diagnostics( |
469 | r" | 430 | r#" |
470 | //- /main.rs | 431 | //- /main.rs |
471 | use core::result::Result::{self, Ok, Err}; | 432 | use core::result::Result::{self, Ok, Err}; |
472 | 433 | ||
473 | fn foo() -> Result<(), i32> { | 434 | fn foo() -> Result<(), i32> { 0 } |
474 | 0<|> | ||
475 | } | ||
476 | 435 | ||
477 | //- /core/lib.rs | 436 | //- /core/lib.rs |
478 | pub mod result { | 437 | pub mod result { |
479 | pub enum Result<T, E> { Ok(T), Err(E) } | 438 | pub enum Result<T, E> { Ok(T), Err(E) } |
480 | } | 439 | } |
481 | ", | 440 | "#, |
482 | ); | 441 | ); |
483 | } | 442 | } |
484 | 443 | ||
485 | #[test] | 444 | #[test] |
486 | fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() { | 445 | fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() { |
487 | check_no_diagnostic_for_target_file( | 446 | check_no_diagnostics( |
488 | r" | 447 | r#" |
489 | //- /main.rs | 448 | //- /main.rs |
490 | use core::result::Result::{self, Ok, Err}; | 449 | use core::result::Result::{self, Ok, Err}; |
491 | 450 | ||
492 | enum SomeOtherEnum { | 451 | enum SomeOtherEnum { Ok(i32), Err(String) } |
493 | Ok(i32), | ||
494 | Err(String), | ||
495 | } | ||
496 | 452 | ||
497 | fn foo() -> SomeOtherEnum { | 453 | fn foo() -> SomeOtherEnum { 0 } |
498 | 0<|> | ||
499 | } | ||
500 | 454 | ||
501 | //- /core/lib.rs | 455 | //- /core/lib.rs |
502 | pub mod result { | 456 | pub mod result { |
503 | pub enum Result<T, E> { Ok(T), Err(E) } | 457 | pub enum Result<T, E> { Ok(T), Err(E) } |
504 | } | 458 | } |
505 | ", | 459 | "#, |
506 | ); | 460 | ); |
507 | } | 461 | } |
508 | 462 | ||
509 | #[test] | 463 | #[test] |
510 | fn test_fill_struct_fields_empty() { | 464 | fn test_fill_struct_fields_empty() { |
511 | let before = r" | 465 | check_fix( |
512 | struct TestStruct { | 466 | r#" |
513 | one: i32, | 467 | struct TestStruct { one: i32, two: i64 } |
514 | two: i64, | ||
515 | } | ||
516 | 468 | ||
517 | fn test_fn() { | 469 | fn test_fn() { |
518 | let s = TestStruct{}; | 470 | let s = TestStruct {<|>}; |
519 | } | 471 | } |
520 | "; | 472 | "#, |
521 | let after = r" | 473 | r#" |
522 | struct TestStruct { | 474 | struct TestStruct { one: i32, two: i64 } |
523 | one: i32, | ||
524 | two: i64, | ||
525 | } | ||
526 | 475 | ||
527 | fn test_fn() { | 476 | fn test_fn() { |
528 | let s = TestStruct{ one: (), two: ()}; | 477 | let s = TestStruct { one: (), two: ()}; |
529 | } | 478 | } |
530 | "; | 479 | "#, |
531 | check_apply_diagnostic_fix(before, after); | 480 | ); |
532 | } | 481 | } |
533 | 482 | ||
534 | #[test] | 483 | #[test] |
535 | fn test_fill_struct_fields_self() { | 484 | fn test_fill_struct_fields_self() { |
536 | let before = r" | 485 | check_fix( |
537 | struct TestStruct { | 486 | r#" |
538 | one: i32, | 487 | struct TestStruct { one: i32 } |
539 | } | ||
540 | 488 | ||
541 | impl TestStruct { | 489 | impl TestStruct { |
542 | fn test_fn() { | 490 | fn test_fn() { let s = Self {<|>}; } |
543 | let s = Self {}; | 491 | } |
544 | } | 492 | "#, |
545 | } | 493 | r#" |
546 | "; | 494 | struct TestStruct { one: i32 } |
547 | let after = r" | ||
548 | struct TestStruct { | ||
549 | one: i32, | ||
550 | } | ||
551 | 495 | ||
552 | impl TestStruct { | 496 | impl TestStruct { |
553 | fn test_fn() { | 497 | fn test_fn() { let s = Self { one: ()}; } |
554 | let s = Self { one: ()}; | 498 | } |
555 | } | 499 | "#, |
556 | } | 500 | ); |
557 | "; | ||
558 | check_apply_diagnostic_fix(before, after); | ||
559 | } | 501 | } |
560 | 502 | ||
561 | #[test] | 503 | #[test] |
562 | fn test_fill_struct_fields_enum() { | 504 | fn test_fill_struct_fields_enum() { |
563 | let before = r" | 505 | check_fix( |
564 | enum Expr { | 506 | r#" |
565 | Bin { lhs: Box<Expr>, rhs: Box<Expr> } | 507 | enum Expr { |
566 | } | 508 | Bin { lhs: Box<Expr>, rhs: Box<Expr> } |
509 | } | ||
567 | 510 | ||
568 | impl Expr { | 511 | impl Expr { |
569 | fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr { | 512 | fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr { |
570 | Expr::Bin { } | 513 | Expr::Bin {<|> } |
571 | } | 514 | } |
572 | } | 515 | } |
573 | "; | 516 | "#, |
574 | let after = r" | 517 | r#" |
575 | enum Expr { | 518 | enum Expr { |
576 | Bin { lhs: Box<Expr>, rhs: Box<Expr> } | 519 | Bin { lhs: Box<Expr>, rhs: Box<Expr> } |
577 | } | 520 | } |
578 | 521 | ||
579 | impl Expr { | 522 | impl Expr { |
580 | fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr { | 523 | fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr { |
581 | Expr::Bin { lhs: (), rhs: () } | 524 | Expr::Bin { lhs: (), rhs: () } |
582 | } | 525 | } |
583 | } | 526 | } |
584 | "; | 527 | "#, |
585 | check_apply_diagnostic_fix(before, after); | 528 | ); |
586 | } | 529 | } |
587 | 530 | ||
588 | #[test] | 531 | #[test] |
589 | fn test_fill_struct_fields_partial() { | 532 | fn test_fill_struct_fields_partial() { |
590 | let before = r" | 533 | check_fix( |
591 | struct TestStruct { | 534 | r#" |
592 | one: i32, | 535 | struct TestStruct { one: i32, two: i64 } |
593 | two: i64, | ||
594 | } | ||
595 | 536 | ||
596 | fn test_fn() { | 537 | fn test_fn() { |
597 | let s = TestStruct{ two: 2 }; | 538 | let s = TestStruct{ two: 2<|> }; |
598 | } | 539 | } |
599 | "; | 540 | "#, |
600 | let after = r" | 541 | r" |
601 | struct TestStruct { | 542 | struct TestStruct { one: i32, two: i64 } |
602 | one: i32, | ||
603 | two: i64, | ||
604 | } | ||
605 | 543 | ||
606 | fn test_fn() { | 544 | fn test_fn() { |
607 | let s = TestStruct{ two: 2, one: () }; | 545 | let s = TestStruct{ two: 2, one: () }; |
608 | } | 546 | } |
609 | "; | 547 | ", |
610 | check_apply_diagnostic_fix(before, after); | 548 | ); |
611 | } | 549 | } |
612 | 550 | ||
613 | #[test] | 551 | #[test] |
614 | fn test_fill_struct_fields_no_diagnostic() { | 552 | fn test_fill_struct_fields_no_diagnostic() { |
615 | check_no_diagnostic( | 553 | check_no_diagnostics( |
616 | r" | 554 | r" |
617 | struct TestStruct { | 555 | struct TestStruct { one: i32, two: i64 } |
618 | one: i32, | ||
619 | two: i64, | ||
620 | } | ||
621 | 556 | ||
622 | fn test_fn() { | 557 | fn test_fn() { |
623 | let one = 1; | 558 | let one = 1; |
@@ -629,12 +564,9 @@ mod tests { | |||
629 | 564 | ||
630 | #[test] | 565 | #[test] |
631 | fn test_fill_struct_fields_no_diagnostic_on_spread() { | 566 | fn test_fill_struct_fields_no_diagnostic_on_spread() { |
632 | check_no_diagnostic( | 567 | check_no_diagnostics( |
633 | r" | 568 | r" |
634 | struct TestStruct { | 569 | struct TestStruct { one: i32, two: i64 } |
635 | one: i32, | ||
636 | two: i64, | ||
637 | } | ||
638 | 570 | ||
639 | fn test_fn() { | 571 | fn test_fn() { |
640 | let one = 1; | 572 | let one = 1; |
@@ -646,211 +578,143 @@ mod tests { | |||
646 | 578 | ||
647 | #[test] | 579 | #[test] |
648 | fn test_unresolved_module_diagnostic() { | 580 | fn test_unresolved_module_diagnostic() { |
649 | let (analysis, file_id) = single_file("mod foo;"); | 581 | check_expect( |
650 | let diagnostics = analysis.diagnostics(file_id).unwrap(); | 582 | r#"mod foo;"#, |
651 | assert_debug_snapshot!(diagnostics, @r###" | 583 | expect![[r#" |
652 | [ | 584 | [ |
653 | Diagnostic { | 585 | Diagnostic { |
654 | message: "unresolved module", | 586 | message: "unresolved module", |
655 | range: 0..8, | 587 | range: 0..8, |
656 | severity: Error, | 588 | severity: Error, |
657 | fix: Some( | 589 | fix: Some( |
658 | Fix { | 590 | Fix { |
659 | label: "Create module", | 591 | label: "Create module", |
660 | source_change: SourceChange { | 592 | source_change: SourceChange { |
661 | source_file_edits: [], | 593 | source_file_edits: [], |
662 | file_system_edits: [ | 594 | file_system_edits: [ |
663 | CreateFile { | 595 | CreateFile { |
664 | anchor: FileId( | 596 | anchor: FileId( |
665 | 1, | 597 | 1, |
666 | ), | 598 | ), |
667 | dst: "foo.rs", | 599 | dst: "foo.rs", |
600 | }, | ||
601 | ], | ||
602 | is_snippet: false, | ||
668 | }, | 603 | }, |
669 | ], | 604 | }, |
670 | is_snippet: false, | 605 | ), |
671 | }, | ||
672 | }, | 606 | }, |
673 | ), | 607 | ] |
674 | }, | 608 | "#]], |
675 | ] | 609 | ); |
676 | "###); | ||
677 | } | 610 | } |
678 | 611 | ||
679 | #[test] | 612 | #[test] |
680 | fn range_mapping_out_of_macros() { | 613 | fn range_mapping_out_of_macros() { |
681 | let (analysis, file_id) = single_file( | 614 | // FIXME: this is very wrong, but somewhat tricky to fix. |
682 | r" | 615 | check_fix( |
683 | fn some() {} | 616 | r#" |
684 | fn items() {} | 617 | fn some() {} |
685 | fn here() {} | 618 | fn items() {} |
619 | fn here() {} | ||
686 | 620 | ||
687 | macro_rules! id { | 621 | macro_rules! id { ($($tt:tt)*) => { $($tt)*}; } |
688 | ($($tt:tt)*) => { $($tt)*}; | ||
689 | } | ||
690 | 622 | ||
691 | fn main() { | 623 | fn main() { |
692 | let _x = id![Foo { a: 42 }]; | 624 | let _x = id![Foo { a: <|>42 }]; |
693 | } | 625 | } |
694 | 626 | ||
695 | pub struct Foo { | 627 | pub struct Foo { pub a: i32, pub b: i32 } |
696 | pub a: i32, | 628 | "#, |
697 | pub b: i32, | 629 | r#" |
698 | } | 630 | fn {a:42, b: ()} {} |
699 | ", | 631 | fn items() {} |
632 | fn here() {} | ||
633 | |||
634 | macro_rules! id { ($($tt:tt)*) => { $($tt)*}; } | ||
635 | |||
636 | fn main() { | ||
637 | let _x = id![Foo { a: 42 }]; | ||
638 | } | ||
639 | |||
640 | pub struct Foo { pub a: i32, pub b: i32 } | ||
641 | "#, | ||
700 | ); | 642 | ); |
701 | let diagnostics = analysis.diagnostics(file_id).unwrap(); | ||
702 | assert_debug_snapshot!(diagnostics, @r###" | ||
703 | [ | ||
704 | Diagnostic { | ||
705 | message: "Missing structure fields:\n- b\n", | ||
706 | range: 127..136, | ||
707 | severity: Error, | ||
708 | fix: Some( | ||
709 | Fix { | ||
710 | label: "Fill struct fields", | ||
711 | source_change: SourceChange { | ||
712 | source_file_edits: [ | ||
713 | SourceFileEdit { | ||
714 | file_id: FileId( | ||
715 | 1, | ||
716 | ), | ||
717 | edit: TextEdit { | ||
718 | indels: [ | ||
719 | Indel { | ||
720 | insert: "{a:42, b: ()}", | ||
721 | delete: 3..9, | ||
722 | }, | ||
723 | ], | ||
724 | }, | ||
725 | }, | ||
726 | ], | ||
727 | file_system_edits: [], | ||
728 | is_snippet: false, | ||
729 | }, | ||
730 | }, | ||
731 | ), | ||
732 | }, | ||
733 | ] | ||
734 | "###); | ||
735 | } | 643 | } |
736 | 644 | ||
737 | #[test] | 645 | #[test] |
738 | fn test_check_unnecessary_braces_in_use_statement() { | 646 | fn test_check_unnecessary_braces_in_use_statement() { |
739 | check_not_applicable( | 647 | check_no_diagnostics( |
740 | " | 648 | r#" |
741 | use a; | 649 | use a; |
742 | use a::{c, d::e}; | 650 | use a::{c, d::e}; |
743 | ", | 651 | "#, |
744 | check_unnecessary_braces_in_use_statement, | ||
745 | ); | ||
746 | check_apply("use {b};", "use b;", check_unnecessary_braces_in_use_statement); | ||
747 | check_apply("use a::{c};", "use a::c;", check_unnecessary_braces_in_use_statement); | ||
748 | check_apply("use a::{self};", "use a;", check_unnecessary_braces_in_use_statement); | ||
749 | check_apply( | ||
750 | "use a::{c, d::{e}};", | ||
751 | "use a::{c, d::e};", | ||
752 | check_unnecessary_braces_in_use_statement, | ||
753 | ); | 652 | ); |
653 | check_fix(r#"use {<|>b};"#, r#"use b;"#); | ||
654 | check_fix(r#"use {b<|>};"#, r#"use b;"#); | ||
655 | check_fix(r#"use a::{c<|>};"#, r#"use a::c;"#); | ||
656 | check_fix(r#"use a::{self<|>};"#, r#"use a;"#); | ||
657 | check_fix(r#"use a::{c, d::{e<|>}};"#, r#"use a::{c, d::e};"#); | ||
754 | } | 658 | } |
755 | 659 | ||
756 | #[test] | 660 | #[test] |
757 | fn test_check_struct_shorthand_initialization() { | 661 | fn test_check_struct_shorthand_initialization() { |
758 | check_not_applicable( | 662 | check_no_diagnostics( |
759 | r#" | 663 | r#" |
760 | struct A { | 664 | struct A { a: &'static str } |
761 | a: &'static str | 665 | fn main() { A { a: "hello" } } |
762 | } | 666 | "#, |
763 | |||
764 | fn main() { | ||
765 | A { | ||
766 | a: "hello" | ||
767 | } | ||
768 | } | ||
769 | "#, | ||
770 | check_struct_shorthand_initialization, | ||
771 | ); | 667 | ); |
772 | check_not_applicable( | 668 | check_no_diagnostics( |
773 | r#" | 669 | r#" |
774 | struct A(usize); | 670 | struct A(usize); |
775 | 671 | fn main() { A { 0: 0 } } | |
776 | fn main() { | 672 | "#, |
777 | A { | ||
778 | 0: 0 | ||
779 | } | ||
780 | } | ||
781 | "#, | ||
782 | check_struct_shorthand_initialization, | ||
783 | ); | 673 | ); |
784 | 674 | ||
785 | check_apply( | 675 | check_fix( |
786 | r#" | 676 | r#" |
787 | struct A { | 677 | struct A { a: &'static str } |
788 | a: &'static str | ||
789 | } | ||
790 | |||
791 | fn main() { | 678 | fn main() { |
792 | let a = "haha"; | 679 | let a = "haha"; |
793 | A { | 680 | A { a<|>: a } |
794 | a: a | ||
795 | } | ||
796 | } | 681 | } |
797 | "#, | 682 | "#, |
798 | r#" | 683 | r#" |
799 | struct A { | 684 | struct A { a: &'static str } |
800 | a: &'static str | ||
801 | } | ||
802 | |||
803 | fn main() { | 685 | fn main() { |
804 | let a = "haha"; | 686 | let a = "haha"; |
805 | A { | 687 | A { a } |
806 | a | ||
807 | } | ||
808 | } | 688 | } |
809 | "#, | 689 | "#, |
810 | check_struct_shorthand_initialization, | ||
811 | ); | 690 | ); |
812 | 691 | ||
813 | check_apply( | 692 | check_fix( |
814 | r#" | 693 | r#" |
815 | struct A { | 694 | struct A { a: &'static str, b: &'static str } |
816 | a: &'static str, | ||
817 | b: &'static str | ||
818 | } | ||
819 | |||
820 | fn main() { | 695 | fn main() { |
821 | let a = "haha"; | 696 | let a = "haha"; |
822 | let b = "bb"; | 697 | let b = "bb"; |
823 | A { | 698 | A { a<|>: a, b } |
824 | a: a, | ||
825 | b | ||
826 | } | ||
827 | } | 699 | } |
828 | "#, | 700 | "#, |
829 | r#" | 701 | r#" |
830 | struct A { | 702 | struct A { a: &'static str, b: &'static str } |
831 | a: &'static str, | ||
832 | b: &'static str | ||
833 | } | ||
834 | |||
835 | fn main() { | 703 | fn main() { |
836 | let a = "haha"; | 704 | let a = "haha"; |
837 | let b = "bb"; | 705 | let b = "bb"; |
838 | A { | 706 | A { a, b } |
839 | a, | ||
840 | b | ||
841 | } | ||
842 | } | 707 | } |
843 | "#, | 708 | "#, |
844 | check_struct_shorthand_initialization, | ||
845 | ); | 709 | ); |
846 | } | 710 | } |
847 | 711 | ||
848 | #[test] | 712 | #[test] |
849 | fn test_add_field_from_usage() { | 713 | fn test_add_field_from_usage() { |
850 | check_apply_diagnostic_fix( | 714 | check_fix( |
851 | r" | 715 | r" |
852 | fn main() { | 716 | fn main() { |
853 | Foo { bar: 3, baz: false}; | 717 | Foo { bar: 3, baz<|>: false}; |
854 | } | 718 | } |
855 | struct Foo { | 719 | struct Foo { |
856 | bar: i32 | 720 | bar: i32 |
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 62d364bfa..35ab741d8 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs | |||
@@ -351,10 +351,10 @@ mod tests { | |||
351 | use crate::{inlay_hints::InlayHintsConfig, mock_analysis::single_file}; | 351 | use crate::{inlay_hints::InlayHintsConfig, mock_analysis::single_file}; |
352 | 352 | ||
353 | fn check(ra_fixture: &str) { | 353 | fn check(ra_fixture: &str) { |
354 | check_with_config(ra_fixture, InlayHintsConfig::default()); | 354 | check_with_config(InlayHintsConfig::default(), ra_fixture); |
355 | } | 355 | } |
356 | 356 | ||
357 | fn check_with_config(ra_fixture: &str, config: InlayHintsConfig) { | 357 | fn check_with_config(config: InlayHintsConfig, ra_fixture: &str) { |
358 | let (analysis, file_id) = single_file(ra_fixture); | 358 | let (analysis, file_id) = single_file(ra_fixture); |
359 | let expected = extract_annotations(&*analysis.file_text(file_id).unwrap()); | 359 | let expected = extract_annotations(&*analysis.file_text(file_id).unwrap()); |
360 | let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap(); | 360 | let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap(); |
@@ -363,7 +363,7 @@ mod tests { | |||
363 | assert_eq!(expected, actual); | 363 | assert_eq!(expected, actual); |
364 | } | 364 | } |
365 | 365 | ||
366 | fn check_expect(ra_fixture: &str, config: InlayHintsConfig, expect: Expect) { | 366 | fn check_expect(config: InlayHintsConfig, ra_fixture: &str, expect: Expect) { |
367 | let (analysis, file_id) = single_file(ra_fixture); | 367 | let (analysis, file_id) = single_file(ra_fixture); |
368 | let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap(); | 368 | let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap(); |
369 | expect.assert_debug_eq(&inlay_hints) | 369 | expect.assert_debug_eq(&inlay_hints) |
@@ -372,6 +372,12 @@ mod tests { | |||
372 | #[test] | 372 | #[test] |
373 | fn param_hints_only() { | 373 | fn param_hints_only() { |
374 | check_with_config( | 374 | check_with_config( |
375 | InlayHintsConfig { | ||
376 | parameter_hints: true, | ||
377 | type_hints: false, | ||
378 | chaining_hints: false, | ||
379 | max_length: None, | ||
380 | }, | ||
375 | r#" | 381 | r#" |
376 | fn foo(a: i32, b: i32) -> i32 { a + b } | 382 | fn foo(a: i32, b: i32) -> i32 { a + b } |
377 | fn main() { | 383 | fn main() { |
@@ -382,47 +388,41 @@ fn main() { | |||
382 | //^ b | 388 | //^ b |
383 | ); | 389 | ); |
384 | }"#, | 390 | }"#, |
385 | InlayHintsConfig { | ||
386 | parameter_hints: true, | ||
387 | type_hints: false, | ||
388 | chaining_hints: false, | ||
389 | max_length: None, | ||
390 | }, | ||
391 | ); | 391 | ); |
392 | } | 392 | } |
393 | 393 | ||
394 | #[test] | 394 | #[test] |
395 | fn hints_disabled() { | 395 | fn hints_disabled() { |
396 | check_with_config( | 396 | check_with_config( |
397 | r#" | ||
398 | fn foo(a: i32, b: i32) -> i32 { a + b } | ||
399 | fn main() { | ||
400 | let _x = foo(4, 4); | ||
401 | }"#, | ||
402 | InlayHintsConfig { | 397 | InlayHintsConfig { |
403 | type_hints: false, | 398 | type_hints: false, |
404 | parameter_hints: false, | 399 | parameter_hints: false, |
405 | chaining_hints: false, | 400 | chaining_hints: false, |
406 | max_length: None, | 401 | max_length: None, |
407 | }, | 402 | }, |
403 | r#" | ||
404 | fn foo(a: i32, b: i32) -> i32 { a + b } | ||
405 | fn main() { | ||
406 | let _x = foo(4, 4); | ||
407 | }"#, | ||
408 | ); | 408 | ); |
409 | } | 409 | } |
410 | 410 | ||
411 | #[test] | 411 | #[test] |
412 | fn type_hints_only() { | 412 | fn type_hints_only() { |
413 | check_with_config( | 413 | check_with_config( |
414 | r#" | ||
415 | fn foo(a: i32, b: i32) -> i32 { a + b } | ||
416 | fn main() { | ||
417 | let _x = foo(4, 4); | ||
418 | //^^ i32 | ||
419 | }"#, | ||
420 | InlayHintsConfig { | 414 | InlayHintsConfig { |
421 | type_hints: true, | 415 | type_hints: true, |
422 | parameter_hints: false, | 416 | parameter_hints: false, |
423 | chaining_hints: false, | 417 | chaining_hints: false, |
424 | max_length: None, | 418 | max_length: None, |
425 | }, | 419 | }, |
420 | r#" | ||
421 | fn foo(a: i32, b: i32) -> i32 { a + b } | ||
422 | fn main() { | ||
423 | let _x = foo(4, 4); | ||
424 | //^^ i32 | ||
425 | }"#, | ||
426 | ); | 426 | ); |
427 | } | 427 | } |
428 | 428 | ||
@@ -590,6 +590,7 @@ fn main() { | |||
590 | #[test] | 590 | #[test] |
591 | fn hint_truncation() { | 591 | fn hint_truncation() { |
592 | check_with_config( | 592 | check_with_config( |
593 | InlayHintsConfig { max_length: Some(8), ..Default::default() }, | ||
593 | r#" | 594 | r#" |
594 | struct Smol<T>(T); | 595 | struct Smol<T>(T); |
595 | 596 | ||
@@ -603,7 +604,6 @@ fn main() { | |||
603 | let c = Smol(Smol(0u32)) | 604 | let c = Smol(Smol(0u32)) |
604 | //^ Smol<Smol<…>> | 605 | //^ Smol<Smol<…>> |
605 | }"#, | 606 | }"#, |
606 | InlayHintsConfig { max_length: Some(8), ..Default::default() }, | ||
607 | ); | 607 | ); |
608 | } | 608 | } |
609 | 609 | ||
@@ -673,6 +673,7 @@ fn main() { | |||
673 | #[test] | 673 | #[test] |
674 | fn omitted_parameters_hints_heuristics() { | 674 | fn omitted_parameters_hints_heuristics() { |
675 | check_with_config( | 675 | check_with_config( |
676 | InlayHintsConfig { max_length: Some(8), ..Default::default() }, | ||
676 | r#" | 677 | r#" |
677 | fn map(f: i32) {} | 678 | fn map(f: i32) {} |
678 | fn filter(predicate: i32) {} | 679 | fn filter(predicate: i32) {} |
@@ -753,13 +754,13 @@ fn main() { | |||
753 | let _: f64 = a.div_euclid(b); | 754 | let _: f64 = a.div_euclid(b); |
754 | let _: f64 = a.abs_sub(b); | 755 | let _: f64 = a.abs_sub(b); |
755 | }"#, | 756 | }"#, |
756 | InlayHintsConfig { max_length: Some(8), ..Default::default() }, | ||
757 | ); | 757 | ); |
758 | } | 758 | } |
759 | 759 | ||
760 | #[test] | 760 | #[test] |
761 | fn unit_structs_have_no_type_hints() { | 761 | fn unit_structs_have_no_type_hints() { |
762 | check_with_config( | 762 | check_with_config( |
763 | InlayHintsConfig { max_length: Some(8), ..Default::default() }, | ||
763 | r#" | 764 | r#" |
764 | enum Result<T, E> { Ok(T), Err(E) } | 765 | enum Result<T, E> { Ok(T), Err(E) } |
765 | use Result::*; | 766 | use Result::*; |
@@ -772,13 +773,18 @@ fn main() { | |||
772 | Err(SyntheticSyntax) => (), | 773 | Err(SyntheticSyntax) => (), |
773 | } | 774 | } |
774 | }"#, | 775 | }"#, |
775 | InlayHintsConfig { max_length: Some(8), ..Default::default() }, | ||
776 | ); | 776 | ); |
777 | } | 777 | } |
778 | 778 | ||
779 | #[test] | 779 | #[test] |
780 | fn chaining_hints_ignore_comments() { | 780 | fn chaining_hints_ignore_comments() { |
781 | check_expect( | 781 | check_expect( |
782 | InlayHintsConfig { | ||
783 | parameter_hints: false, | ||
784 | type_hints: false, | ||
785 | chaining_hints: true, | ||
786 | max_length: None, | ||
787 | }, | ||
782 | r#" | 788 | r#" |
783 | struct A(B); | 789 | struct A(B); |
784 | impl A { fn into_b(self) -> B { self.0 } } | 790 | impl A { fn into_b(self) -> B { self.0 } } |
@@ -792,12 +798,6 @@ fn main() { | |||
792 | .into_c(); | 798 | .into_c(); |
793 | } | 799 | } |
794 | "#, | 800 | "#, |
795 | InlayHintsConfig { | ||
796 | parameter_hints: false, | ||
797 | type_hints: false, | ||
798 | chaining_hints: true, | ||
799 | max_length: None, | ||
800 | }, | ||
801 | expect![[r#" | 801 | expect![[r#" |
802 | [ | 802 | [ |
803 | InlayHint { | 803 | InlayHint { |
@@ -818,6 +818,12 @@ fn main() { | |||
818 | #[test] | 818 | #[test] |
819 | fn chaining_hints_without_newlines() { | 819 | fn chaining_hints_without_newlines() { |
820 | check_with_config( | 820 | check_with_config( |
821 | InlayHintsConfig { | ||
822 | parameter_hints: false, | ||
823 | type_hints: false, | ||
824 | chaining_hints: true, | ||
825 | max_length: None, | ||
826 | }, | ||
821 | r#" | 827 | r#" |
822 | struct A(B); | 828 | struct A(B); |
823 | impl A { fn into_b(self) -> B { self.0 } } | 829 | impl A { fn into_b(self) -> B { self.0 } } |
@@ -828,18 +834,18 @@ struct C; | |||
828 | fn main() { | 834 | fn main() { |
829 | let c = A(B(C)).into_b().into_c(); | 835 | let c = A(B(C)).into_b().into_c(); |
830 | }"#, | 836 | }"#, |
831 | InlayHintsConfig { | ||
832 | parameter_hints: false, | ||
833 | type_hints: false, | ||
834 | chaining_hints: true, | ||
835 | max_length: None, | ||
836 | }, | ||
837 | ); | 837 | ); |
838 | } | 838 | } |
839 | 839 | ||
840 | #[test] | 840 | #[test] |
841 | fn struct_access_chaining_hints() { | 841 | fn struct_access_chaining_hints() { |
842 | check_expect( | 842 | check_expect( |
843 | InlayHintsConfig { | ||
844 | parameter_hints: false, | ||
845 | type_hints: false, | ||
846 | chaining_hints: true, | ||
847 | max_length: None, | ||
848 | }, | ||
843 | r#" | 849 | r#" |
844 | struct A { pub b: B } | 850 | struct A { pub b: B } |
845 | struct B { pub c: C } | 851 | struct B { pub c: C } |
@@ -858,12 +864,6 @@ fn main() { | |||
858 | let x = D | 864 | let x = D |
859 | .foo(); | 865 | .foo(); |
860 | }"#, | 866 | }"#, |
861 | InlayHintsConfig { | ||
862 | parameter_hints: false, | ||
863 | type_hints: false, | ||
864 | chaining_hints: true, | ||
865 | max_length: None, | ||
866 | }, | ||
867 | expect![[r#" | 867 | expect![[r#" |
868 | [ | 868 | [ |
869 | InlayHint { | 869 | InlayHint { |
@@ -884,6 +884,12 @@ fn main() { | |||
884 | #[test] | 884 | #[test] |
885 | fn generic_chaining_hints() { | 885 | fn generic_chaining_hints() { |
886 | check_expect( | 886 | check_expect( |
887 | InlayHintsConfig { | ||
888 | parameter_hints: false, | ||
889 | type_hints: false, | ||
890 | chaining_hints: true, | ||
891 | max_length: None, | ||
892 | }, | ||
887 | r#" | 893 | r#" |
888 | struct A<T>(T); | 894 | struct A<T>(T); |
889 | struct B<T>(T); | 895 | struct B<T>(T); |
@@ -903,12 +909,6 @@ fn main() { | |||
903 | .into_c(); | 909 | .into_c(); |
904 | } | 910 | } |
905 | "#, | 911 | "#, |
906 | InlayHintsConfig { | ||
907 | parameter_hints: false, | ||
908 | type_hints: false, | ||
909 | chaining_hints: true, | ||
910 | max_length: None, | ||
911 | }, | ||
912 | expect![[r#" | 912 | expect![[r#" |
913 | [ | 913 | [ |
914 | InlayHint { | 914 | InlayHint { |
diff --git a/crates/ra_ide/src/mock_analysis.rs b/crates/ra_ide/src/mock_analysis.rs index a393d3dba..b28054688 100644 --- a/crates/ra_ide/src/mock_analysis.rs +++ b/crates/ra_ide/src/mock_analysis.rs | |||
@@ -71,20 +71,13 @@ impl MockAnalysis { | |||
71 | } | 71 | } |
72 | 72 | ||
73 | pub fn id_of(&self, path: &str) -> FileId { | 73 | pub fn id_of(&self, path: &str) -> FileId { |
74 | let (idx, _) = self | 74 | let (file_id, _) = |
75 | .files | 75 | self.files().find(|(_, data)| path == data.path).expect("no file in this mock"); |
76 | .iter() | 76 | file_id |
77 | .enumerate() | ||
78 | .find(|(_, data)| path == data.path) | ||
79 | .expect("no file in this mock"); | ||
80 | FileId(idx as u32 + 1) | ||
81 | } | 77 | } |
82 | pub fn annotations(&self) -> Vec<(FileRange, String)> { | 78 | pub fn annotations(&self) -> Vec<(FileRange, String)> { |
83 | self.files | 79 | self.files() |
84 | .iter() | 80 | .flat_map(|(file_id, fixture)| { |
85 | .enumerate() | ||
86 | .flat_map(|(idx, fixture)| { | ||
87 | let file_id = FileId(idx as u32 + 1); | ||
88 | let annotations = extract_annotations(&fixture.text); | 81 | let annotations = extract_annotations(&fixture.text); |
89 | annotations | 82 | annotations |
90 | .into_iter() | 83 | .into_iter() |
@@ -92,6 +85,9 @@ impl MockAnalysis { | |||
92 | }) | 85 | }) |
93 | .collect() | 86 | .collect() |
94 | } | 87 | } |
88 | pub fn files(&self) -> impl Iterator<Item = (FileId, &Fixture)> + '_ { | ||
89 | self.files.iter().enumerate().map(|(idx, fixture)| (FileId(idx as u32 + 1), fixture)) | ||
90 | } | ||
95 | pub fn annotation(&self) -> (FileRange, String) { | 91 | pub fn annotation(&self) -> (FileRange, String) { |
96 | let mut all = self.annotations(); | 92 | let mut all = self.annotations(); |
97 | assert_eq!(all.len(), 1); | 93 | assert_eq!(all.len(), 1); |