diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_ide/src/diagnostics.rs | 328 |
1 files changed, 147 insertions, 181 deletions
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index 46f8c31c7..c1cbfcc2c 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs | |||
@@ -324,10 +324,10 @@ mod tests { | |||
324 | /// * a diagnostic is produced | 324 | /// * a diagnostic is produced |
325 | /// * this diagnostic touches the input cursor position | 325 | /// * this diagnostic touches the input cursor position |
326 | /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied | 326 | /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied |
327 | fn check_apply_diagnostic_fix_from_position(ra_fixture: &str, after: &str) { | 327 | fn check_fix(ra_fixture_before: &str, ra_fixture_after: &str) { |
328 | let after = trim_indent(after); | 328 | let after = trim_indent(ra_fixture_after); |
329 | 329 | ||
330 | let (analysis, file_position) = analysis_and_position(ra_fixture); | 330 | let (analysis, file_position) = analysis_and_position(ra_fixture_before); |
331 | let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap(); | 331 | let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap(); |
332 | let mut fix = diagnostic.fix.unwrap(); | 332 | let mut fix = diagnostic.fix.unwrap(); |
333 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; | 333 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; |
@@ -348,21 +348,6 @@ mod tests { | |||
348 | ); | 348 | ); |
349 | } | 349 | } |
350 | 350 | ||
351 | fn check_apply_diagnostic_fix(ra_fixture_before: &str, ra_fixture_after: &str) { | ||
352 | let ra_fixture_after = &trim_indent(ra_fixture_after); | ||
353 | let (analysis, file_id) = single_file(ra_fixture_before); | ||
354 | let before = analysis.file_text(file_id).unwrap(); | ||
355 | let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap(); | ||
356 | let mut fix = diagnostic.fix.unwrap(); | ||
357 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; | ||
358 | let actual = { | ||
359 | let mut actual = before.to_string(); | ||
360 | edit.apply(&mut actual); | ||
361 | actual | ||
362 | }; | ||
363 | assert_eq_text!(ra_fixture_after, &actual); | ||
364 | } | ||
365 | |||
366 | /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics | 351 | /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics |
367 | /// apply to the file containing the cursor. | 352 | /// apply to the file containing the cursor. |
368 | fn check_no_diagnostic_for_target_file(ra_fixture: &str) { | 353 | fn check_no_diagnostic_for_target_file(ra_fixture: &str) { |
@@ -379,96 +364,99 @@ mod tests { | |||
379 | 364 | ||
380 | #[test] | 365 | #[test] |
381 | fn test_wrap_return_type() { | 366 | fn test_wrap_return_type() { |
382 | let before = r#" | 367 | check_fix( |
383 | //- /main.rs | 368 | r#" |
384 | use core::result::Result::{self, Ok, Err}; | 369 | //- /main.rs |
370 | use core::result::Result::{self, Ok, Err}; | ||
385 | 371 | ||
386 | fn div(x: i32, y: i32) -> Result<i32, ()> { | 372 | fn div(x: i32, y: i32) -> Result<i32, ()> { |
387 | if y == 0 { | 373 | if y == 0 { |
388 | return Err(()); | 374 | return Err(()); |
389 | } | 375 | } |
390 | x / y<|> | 376 | x / y<|> |
391 | } | 377 | } |
392 | //- /core/lib.rs | 378 | //- /core/lib.rs |
393 | pub mod result { | 379 | pub mod result { |
394 | pub enum Result<T, E> { Ok(T), Err(E) } | 380 | pub enum Result<T, E> { Ok(T), Err(E) } |
395 | } | 381 | } |
396 | "#; | 382 | "#, |
397 | let after = r#" | 383 | r#" |
398 | use core::result::Result::{self, Ok, Err}; | 384 | use core::result::Result::{self, Ok, Err}; |
399 | 385 | ||
400 | fn div(x: i32, y: i32) -> Result<i32, ()> { | 386 | fn div(x: i32, y: i32) -> Result<i32, ()> { |
401 | if y == 0 { | 387 | if y == 0 { |
402 | return Err(()); | 388 | return Err(()); |
403 | } | 389 | } |
404 | Ok(x / y) | 390 | Ok(x / y) |
405 | } | 391 | } |
406 | "#; | 392 | "#, |
407 | check_apply_diagnostic_fix_from_position(before, after); | 393 | ); |
408 | } | 394 | } |
409 | 395 | ||
410 | #[test] | 396 | #[test] |
411 | fn test_wrap_return_type_handles_generic_functions() { | 397 | fn test_wrap_return_type_handles_generic_functions() { |
412 | let before = r#" | 398 | check_fix( |
399 | r#" | ||
413 | //- /main.rs | 400 | //- /main.rs |
414 | use core::result::Result::{self, Ok, Err}; | 401 | use core::result::Result::{self, Ok, Err}; |
415 | 402 | ||
416 | fn div<T>(x: T) -> Result<T, i32> { | 403 | fn div<T>(x: T) -> Result<T, i32> { |
417 | if x == 0 { | 404 | if x == 0 { |
418 | return Err(7); | 405 | return Err(7); |
419 | } | 406 | } |
420 | <|>x | 407 | <|>x |
421 | } | 408 | } |
422 | //- /core/lib.rs | 409 | //- /core/lib.rs |
423 | pub mod result { | 410 | pub mod result { |
424 | pub enum Result<T, E> { Ok(T), Err(E) } | 411 | pub enum Result<T, E> { Ok(T), Err(E) } |
425 | } | 412 | } |
426 | "#; | 413 | "#, |
427 | let after = r#" | 414 | r#" |
428 | use core::result::Result::{self, Ok, Err}; | 415 | use core::result::Result::{self, Ok, Err}; |
429 | 416 | ||
430 | fn div<T>(x: T) -> Result<T, i32> { | 417 | fn div<T>(x: T) -> Result<T, i32> { |
431 | if x == 0 { | 418 | if x == 0 { |
432 | return Err(7); | 419 | return Err(7); |
433 | } | 420 | } |
434 | Ok(x) | 421 | Ok(x) |
435 | } | 422 | } |
436 | "#; | 423 | "#, |
437 | check_apply_diagnostic_fix_from_position(before, after); | 424 | ); |
438 | } | 425 | } |
439 | 426 | ||
440 | #[test] | 427 | #[test] |
441 | fn test_wrap_return_type_handles_type_aliases() { | 428 | fn test_wrap_return_type_handles_type_aliases() { |
442 | let before = r#" | 429 | check_fix( |
443 | //- /main.rs | 430 | r#" |
444 | use core::result::Result::{self, Ok, Err}; | 431 | //- /main.rs |
432 | use core::result::Result::{self, Ok, Err}; | ||
445 | 433 | ||
446 | type MyResult<T> = Result<T, ()>; | 434 | type MyResult<T> = Result<T, ()>; |
447 | 435 | ||
448 | fn div(x: i32, y: i32) -> MyResult<i32> { | 436 | fn div(x: i32, y: i32) -> MyResult<i32> { |
449 | if y == 0 { | 437 | if y == 0 { |
450 | return Err(()); | 438 | return Err(()); |
451 | } | 439 | } |
452 | x <|>/ y | 440 | x <|>/ y |
453 | } | 441 | } |
454 | //- /core/lib.rs | 442 | //- /core/lib.rs |
455 | pub mod result { | 443 | pub mod result { |
456 | pub enum Result<T, E> { Ok(T), Err(E) } | 444 | pub enum Result<T, E> { Ok(T), Err(E) } |
457 | } | 445 | } |
458 | "#; | 446 | "#, |
459 | let after = r#" | 447 | r#" |
460 | use core::result::Result::{self, Ok, Err}; | 448 | use core::result::Result::{self, Ok, Err}; |
461 | 449 | ||
462 | type MyResult<T> = Result<T, ()>; | 450 | type MyResult<T> = Result<T, ()>; |
463 | 451 | ||
464 | fn div(x: i32, y: i32) -> MyResult<i32> { | 452 | fn div(x: i32, y: i32) -> MyResult<i32> { |
465 | if y == 0 { | 453 | if y == 0 { |
466 | return Err(()); | 454 | return Err(()); |
467 | } | 455 | } |
468 | Ok(x / y) | 456 | Ok(x / y) |
469 | } | 457 | } |
470 | "#; | 458 | "#, |
471 | check_apply_diagnostic_fix_from_position(before, after); | 459 | ); |
472 | } | 460 | } |
473 | 461 | ||
474 | #[test] | 462 | #[test] |
@@ -516,116 +504,97 @@ mod tests { | |||
516 | 504 | ||
517 | #[test] | 505 | #[test] |
518 | fn test_fill_struct_fields_empty() { | 506 | fn test_fill_struct_fields_empty() { |
519 | let before = r" | 507 | check_fix( |
520 | struct TestStruct { | 508 | r#" |
521 | one: i32, | 509 | struct TestStruct { one: i32, two: i64 } |
522 | two: i64, | ||
523 | } | ||
524 | 510 | ||
525 | fn test_fn() { | 511 | fn test_fn() { |
526 | let s = TestStruct{}; | 512 | let s = TestStruct {<|>}; |
527 | } | 513 | } |
528 | "; | 514 | "#, |
529 | let after = r" | 515 | r#" |
530 | struct TestStruct { | 516 | struct TestStruct { one: i32, two: i64 } |
531 | one: i32, | ||
532 | two: i64, | ||
533 | } | ||
534 | 517 | ||
535 | fn test_fn() { | 518 | fn test_fn() { |
536 | let s = TestStruct{ one: (), two: ()}; | 519 | let s = TestStruct { one: (), two: ()}; |
537 | } | 520 | } |
538 | "; | 521 | "#, |
539 | check_apply_diagnostic_fix(before, after); | 522 | ); |
540 | } | 523 | } |
541 | 524 | ||
542 | #[test] | 525 | #[test] |
543 | fn test_fill_struct_fields_self() { | 526 | fn test_fill_struct_fields_self() { |
544 | let before = r" | 527 | check_fix( |
545 | struct TestStruct { | 528 | r#" |
546 | one: i32, | 529 | struct TestStruct { one: i32 } |
547 | } | ||
548 | 530 | ||
549 | impl TestStruct { | 531 | impl TestStruct { |
550 | fn test_fn() { | 532 | fn test_fn() { let s = Self {<|>}; } |
551 | let s = Self {}; | 533 | } |
552 | } | 534 | "#, |
553 | } | 535 | r#" |
554 | "; | 536 | struct TestStruct { one: i32 } |
555 | let after = r" | ||
556 | struct TestStruct { | ||
557 | one: i32, | ||
558 | } | ||
559 | 537 | ||
560 | impl TestStruct { | 538 | impl TestStruct { |
561 | fn test_fn() { | 539 | fn test_fn() { let s = Self { one: ()}; } |
562 | let s = Self { one: ()}; | 540 | } |
563 | } | 541 | "#, |
564 | } | 542 | ); |
565 | "; | ||
566 | check_apply_diagnostic_fix(before, after); | ||
567 | } | 543 | } |
568 | 544 | ||
569 | #[test] | 545 | #[test] |
570 | fn test_fill_struct_fields_enum() { | 546 | fn test_fill_struct_fields_enum() { |
571 | let before = r" | 547 | check_fix( |
572 | enum Expr { | 548 | r#" |
573 | Bin { lhs: Box<Expr>, rhs: Box<Expr> } | 549 | enum Expr { |
574 | } | 550 | Bin { lhs: Box<Expr>, rhs: Box<Expr> } |
551 | } | ||
575 | 552 | ||
576 | impl Expr { | 553 | impl Expr { |
577 | fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr { | 554 | fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr { |
578 | Expr::Bin { } | 555 | Expr::Bin {<|> } |
579 | } | 556 | } |
580 | } | 557 | } |
581 | "; | 558 | "#, |
582 | let after = r" | 559 | r#" |
583 | enum Expr { | 560 | enum Expr { |
584 | Bin { lhs: Box<Expr>, rhs: Box<Expr> } | 561 | Bin { lhs: Box<Expr>, rhs: Box<Expr> } |
585 | } | 562 | } |
586 | 563 | ||
587 | impl Expr { | 564 | impl Expr { |
588 | fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr { | 565 | fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr { |
589 | Expr::Bin { lhs: (), rhs: () } | 566 | Expr::Bin { lhs: (), rhs: () } |
590 | } | 567 | } |
591 | } | 568 | } |
592 | "; | 569 | "#, |
593 | check_apply_diagnostic_fix(before, after); | 570 | ); |
594 | } | 571 | } |
595 | 572 | ||
596 | #[test] | 573 | #[test] |
597 | fn test_fill_struct_fields_partial() { | 574 | fn test_fill_struct_fields_partial() { |
598 | let before = r" | 575 | check_fix( |
599 | struct TestStruct { | 576 | r#" |
600 | one: i32, | 577 | struct TestStruct { one: i32, two: i64 } |
601 | two: i64, | ||
602 | } | ||
603 | 578 | ||
604 | fn test_fn() { | 579 | fn test_fn() { |
605 | let s = TestStruct{ two: 2 }; | 580 | let s = TestStruct{ two: 2<|> }; |
606 | } | 581 | } |
607 | "; | 582 | "#, |
608 | let after = r" | 583 | r" |
609 | struct TestStruct { | 584 | struct TestStruct { one: i32, two: i64 } |
610 | one: i32, | ||
611 | two: i64, | ||
612 | } | ||
613 | 585 | ||
614 | fn test_fn() { | 586 | fn test_fn() { |
615 | let s = TestStruct{ two: 2, one: () }; | 587 | let s = TestStruct{ two: 2, one: () }; |
616 | } | 588 | } |
617 | "; | 589 | ", |
618 | check_apply_diagnostic_fix(before, after); | 590 | ); |
619 | } | 591 | } |
620 | 592 | ||
621 | #[test] | 593 | #[test] |
622 | fn test_fill_struct_fields_no_diagnostic() { | 594 | fn test_fill_struct_fields_no_diagnostic() { |
623 | check_no_diagnostic( | 595 | check_no_diagnostic( |
624 | r" | 596 | r" |
625 | struct TestStruct { | 597 | struct TestStruct { one: i32, two: i64 } |
626 | one: i32, | ||
627 | two: i64, | ||
628 | } | ||
629 | 598 | ||
630 | fn test_fn() { | 599 | fn test_fn() { |
631 | let one = 1; | 600 | let one = 1; |
@@ -639,10 +608,7 @@ mod tests { | |||
639 | fn test_fill_struct_fields_no_diagnostic_on_spread() { | 608 | fn test_fill_struct_fields_no_diagnostic_on_spread() { |
640 | check_no_diagnostic( | 609 | check_no_diagnostic( |
641 | r" | 610 | r" |
642 | struct TestStruct { | 611 | struct TestStruct { one: i32, two: i64 } |
643 | one: i32, | ||
644 | two: i64, | ||
645 | } | ||
646 | 612 | ||
647 | fn test_fn() { | 613 | fn test_fn() { |
648 | let one = 1; | 614 | let one = 1; |
@@ -855,10 +821,10 @@ fn main() { | |||
855 | 821 | ||
856 | #[test] | 822 | #[test] |
857 | fn test_add_field_from_usage() { | 823 | fn test_add_field_from_usage() { |
858 | check_apply_diagnostic_fix( | 824 | check_fix( |
859 | r" | 825 | r" |
860 | fn main() { | 826 | fn main() { |
861 | Foo { bar: 3, baz: false}; | 827 | Foo { bar: 3, baz<|>: false}; |
862 | } | 828 | } |
863 | struct Foo { | 829 | struct Foo { |
864 | bar: i32 | 830 | bar: i32 |