aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/diagnostics.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/diagnostics.rs')
-rw-r--r--crates/ide/src/diagnostics.rs533
1 files changed, 2 insertions, 531 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 273d8cfbb..4172f6cae 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -375,7 +375,7 @@ mod tests {
375 assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics); 375 assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics);
376 } 376 }
377 377
378 fn check_expect(ra_fixture: &str, expect: Expect) { 378 pub(crate) fn check_expect(ra_fixture: &str, expect: Expect) {
379 let (analysis, file_id) = fixture::file(ra_fixture); 379 let (analysis, file_id) = fixture::file(ra_fixture);
380 let diagnostics = analysis 380 let diagnostics = analysis
381 .diagnostics(&DiagnosticsConfig::default(), AssistResolveStrategy::All, file_id) 381 .diagnostics(&DiagnosticsConfig::default(), AssistResolveStrategy::All, file_id)
@@ -384,374 +384,6 @@ mod tests {
384 } 384 }
385 385
386 #[test] 386 #[test]
387 fn test_wrap_return_type_option() {
388 check_fix(
389 r#"
390//- /main.rs crate:main deps:core
391use core::option::Option::{self, Some, None};
392
393fn div(x: i32, y: i32) -> Option<i32> {
394 if y == 0 {
395 return None;
396 }
397 x / y$0
398}
399//- /core/lib.rs crate:core
400pub mod result {
401 pub enum Result<T, E> { Ok(T), Err(E) }
402}
403pub mod option {
404 pub enum Option<T> { Some(T), None }
405}
406"#,
407 r#"
408use core::option::Option::{self, Some, None};
409
410fn div(x: i32, y: i32) -> Option<i32> {
411 if y == 0 {
412 return None;
413 }
414 Some(x / y)
415}
416"#,
417 );
418 }
419
420 #[test]
421 fn test_wrap_return_type() {
422 check_fix(
423 r#"
424//- /main.rs crate:main deps:core
425use core::result::Result::{self, Ok, Err};
426
427fn div(x: i32, y: i32) -> Result<i32, ()> {
428 if y == 0 {
429 return Err(());
430 }
431 x / y$0
432}
433//- /core/lib.rs crate:core
434pub mod result {
435 pub enum Result<T, E> { Ok(T), Err(E) }
436}
437pub mod option {
438 pub enum Option<T> { Some(T), None }
439}
440"#,
441 r#"
442use core::result::Result::{self, Ok, Err};
443
444fn div(x: i32, y: i32) -> Result<i32, ()> {
445 if y == 0 {
446 return Err(());
447 }
448 Ok(x / y)
449}
450"#,
451 );
452 }
453
454 #[test]
455 fn test_wrap_return_type_handles_generic_functions() {
456 check_fix(
457 r#"
458//- /main.rs crate:main deps:core
459use core::result::Result::{self, Ok, Err};
460
461fn div<T>(x: T) -> Result<T, i32> {
462 if x == 0 {
463 return Err(7);
464 }
465 $0x
466}
467//- /core/lib.rs crate:core
468pub mod result {
469 pub enum Result<T, E> { Ok(T), Err(E) }
470}
471pub mod option {
472 pub enum Option<T> { Some(T), None }
473}
474"#,
475 r#"
476use core::result::Result::{self, Ok, Err};
477
478fn div<T>(x: T) -> Result<T, i32> {
479 if x == 0 {
480 return Err(7);
481 }
482 Ok(x)
483}
484"#,
485 );
486 }
487
488 #[test]
489 fn test_wrap_return_type_handles_type_aliases() {
490 check_fix(
491 r#"
492//- /main.rs crate:main deps:core
493use core::result::Result::{self, Ok, Err};
494
495type MyResult<T> = Result<T, ()>;
496
497fn div(x: i32, y: i32) -> MyResult<i32> {
498 if y == 0 {
499 return Err(());
500 }
501 x $0/ y
502}
503//- /core/lib.rs crate:core
504pub mod result {
505 pub enum Result<T, E> { Ok(T), Err(E) }
506}
507pub mod option {
508 pub enum Option<T> { Some(T), None }
509}
510"#,
511 r#"
512use core::result::Result::{self, Ok, Err};
513
514type MyResult<T> = Result<T, ()>;
515
516fn div(x: i32, y: i32) -> MyResult<i32> {
517 if y == 0 {
518 return Err(());
519 }
520 Ok(x / y)
521}
522"#,
523 );
524 }
525
526 #[test]
527 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
528 check_no_diagnostics(
529 r#"
530//- /main.rs crate:main deps:core
531use core::result::Result::{self, Ok, Err};
532
533fn foo() -> Result<(), i32> { 0 }
534
535//- /core/lib.rs crate:core
536pub mod result {
537 pub enum Result<T, E> { Ok(T), Err(E) }
538}
539pub mod option {
540 pub enum Option<T> { Some(T), None }
541}
542"#,
543 );
544 }
545
546 #[test]
547 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result_or_option() {
548 check_no_diagnostics(
549 r#"
550//- /main.rs crate:main deps:core
551use core::result::Result::{self, Ok, Err};
552
553enum SomeOtherEnum { Ok(i32), Err(String) }
554
555fn foo() -> SomeOtherEnum { 0 }
556
557//- /core/lib.rs crate:core
558pub mod result {
559 pub enum Result<T, E> { Ok(T), Err(E) }
560}
561pub mod option {
562 pub enum Option<T> { Some(T), None }
563}
564"#,
565 );
566 }
567
568 #[test]
569 fn test_fill_struct_fields_empty() {
570 check_fix(
571 r#"
572struct TestStruct { one: i32, two: i64 }
573
574fn test_fn() {
575 let s = TestStruct {$0};
576}
577"#,
578 r#"
579struct TestStruct { one: i32, two: i64 }
580
581fn test_fn() {
582 let s = TestStruct { one: (), two: ()};
583}
584"#,
585 );
586 }
587
588 #[test]
589 fn test_fill_struct_fields_self() {
590 check_fix(
591 r#"
592struct TestStruct { one: i32 }
593
594impl TestStruct {
595 fn test_fn() { let s = Self {$0}; }
596}
597"#,
598 r#"
599struct TestStruct { one: i32 }
600
601impl TestStruct {
602 fn test_fn() { let s = Self { one: ()}; }
603}
604"#,
605 );
606 }
607
608 #[test]
609 fn test_fill_struct_fields_enum() {
610 check_fix(
611 r#"
612enum Expr {
613 Bin { lhs: Box<Expr>, rhs: Box<Expr> }
614}
615
616impl Expr {
617 fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
618 Expr::Bin {$0 }
619 }
620}
621"#,
622 r#"
623enum Expr {
624 Bin { lhs: Box<Expr>, rhs: Box<Expr> }
625}
626
627impl Expr {
628 fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
629 Expr::Bin { lhs: (), rhs: () }
630 }
631}
632"#,
633 );
634 }
635
636 #[test]
637 fn test_fill_struct_fields_partial() {
638 check_fix(
639 r#"
640struct TestStruct { one: i32, two: i64 }
641
642fn test_fn() {
643 let s = TestStruct{ two: 2$0 };
644}
645"#,
646 r"
647struct TestStruct { one: i32, two: i64 }
648
649fn test_fn() {
650 let s = TestStruct{ two: 2, one: () };
651}
652",
653 );
654 }
655
656 #[test]
657 fn test_fill_struct_fields_raw_ident() {
658 check_fix(
659 r#"
660struct TestStruct { r#type: u8 }
661
662fn test_fn() {
663 TestStruct { $0 };
664}
665"#,
666 r"
667struct TestStruct { r#type: u8 }
668
669fn test_fn() {
670 TestStruct { r#type: () };
671}
672",
673 );
674 }
675
676 #[test]
677 fn test_fill_struct_fields_no_diagnostic() {
678 check_no_diagnostics(
679 r"
680 struct TestStruct { one: i32, two: i64 }
681
682 fn test_fn() {
683 let one = 1;
684 let s = TestStruct{ one, two: 2 };
685 }
686 ",
687 );
688 }
689
690 #[test]
691 fn test_fill_struct_fields_no_diagnostic_on_spread() {
692 check_no_diagnostics(
693 r"
694 struct TestStruct { one: i32, two: i64 }
695
696 fn test_fn() {
697 let one = 1;
698 let s = TestStruct{ ..a };
699 }
700 ",
701 );
702 }
703
704 #[test]
705 fn test_unresolved_module_diagnostic() {
706 check_expect(
707 r#"mod foo;"#,
708 expect![[r#"
709 [
710 Diagnostic {
711 message: "unresolved module",
712 range: 0..8,
713 severity: Error,
714 fix: Some(
715 Assist {
716 id: AssistId(
717 "create_module",
718 QuickFix,
719 ),
720 label: "Create module",
721 group: None,
722 target: 0..8,
723 source_change: Some(
724 SourceChange {
725 source_file_edits: {},
726 file_system_edits: [
727 CreateFile {
728 dst: AnchoredPathBuf {
729 anchor: FileId(
730 0,
731 ),
732 path: "foo.rs",
733 },
734 initial_contents: "",
735 },
736 ],
737 is_snippet: false,
738 },
739 ),
740 },
741 ),
742 unused: false,
743 code: Some(
744 DiagnosticCode(
745 "unresolved-module",
746 ),
747 ),
748 },
749 ]
750 "#]],
751 );
752 }
753
754 #[test]
755 fn test_unresolved_macro_range() { 387 fn test_unresolved_macro_range() {
756 check_expect( 388 check_expect(
757 r#"foo::bar!(92);"#, 389 r#"foo::bar!(92);"#,
@@ -792,7 +424,7 @@ fn main() {
792pub struct Foo { pub a: i32, pub b: i32 } 424pub struct Foo { pub a: i32, pub b: i32 }
793"#, 425"#,
794 r#" 426 r#"
795fn some(, b: ()) {} 427fn some(, b: () ) {}
796fn items() {} 428fn items() {}
797fn here() {} 429fn here() {}
798 430
@@ -891,53 +523,6 @@ mod a {
891 } 523 }
892 524
893 #[test] 525 #[test]
894 fn test_add_field_from_usage() {
895 check_fix(
896 r"
897fn main() {
898 Foo { bar: 3, baz$0: false};
899}
900struct Foo {
901 bar: i32
902}
903",
904 r"
905fn main() {
906 Foo { bar: 3, baz: false};
907}
908struct Foo {
909 bar: i32,
910 baz: bool
911}
912",
913 )
914 }
915
916 #[test]
917 fn test_add_field_in_other_file_from_usage() {
918 check_fix(
919 r#"
920//- /main.rs
921mod foo;
922
923fn main() {
924 foo::Foo { bar: 3, $0baz: false};
925}
926//- /foo.rs
927struct Foo {
928 bar: i32
929}
930"#,
931 r#"
932struct Foo {
933 bar: i32,
934 pub(crate) baz: bool
935}
936"#,
937 )
938 }
939
940 #[test]
941 fn test_disabled_diagnostics() { 526 fn test_disabled_diagnostics() {
942 let mut config = DiagnosticsConfig::default(); 527 let mut config = DiagnosticsConfig::default();
943 config.disabled.insert("unresolved-module".into()); 528 config.disabled.insert("unresolved-module".into());
@@ -955,120 +540,6 @@ struct Foo {
955 } 540 }
956 541
957 #[test] 542 #[test]
958 fn test_rename_incorrect_case() {
959 check_fix(
960 r#"
961pub struct test_struct$0 { one: i32 }
962
963pub fn some_fn(val: test_struct) -> test_struct {
964 test_struct { one: val.one + 1 }
965}
966"#,
967 r#"
968pub struct TestStruct { one: i32 }
969
970pub fn some_fn(val: TestStruct) -> TestStruct {
971 TestStruct { one: val.one + 1 }
972}
973"#,
974 );
975
976 check_fix(
977 r#"
978pub fn some_fn(NonSnakeCase$0: u8) -> u8 {
979 NonSnakeCase
980}
981"#,
982 r#"
983pub fn some_fn(non_snake_case: u8) -> u8 {
984 non_snake_case
985}
986"#,
987 );
988
989 check_fix(
990 r#"
991pub fn SomeFn$0(val: u8) -> u8 {
992 if val != 0 { SomeFn(val - 1) } else { val }
993}
994"#,
995 r#"
996pub fn some_fn(val: u8) -> u8 {
997 if val != 0 { some_fn(val - 1) } else { val }
998}
999"#,
1000 );
1001
1002 check_fix(
1003 r#"
1004fn some_fn() {
1005 let whatAWeird_Formatting$0 = 10;
1006 another_func(whatAWeird_Formatting);
1007}
1008"#,
1009 r#"
1010fn some_fn() {
1011 let what_a_weird_formatting = 10;
1012 another_func(what_a_weird_formatting);
1013}
1014"#,
1015 );
1016 }
1017
1018 #[test]
1019 fn test_uppercase_const_no_diagnostics() {
1020 check_no_diagnostics(
1021 r#"
1022fn foo() {
1023 const ANOTHER_ITEM$0: &str = "some_item";
1024}
1025"#,
1026 );
1027 }
1028
1029 #[test]
1030 fn test_rename_incorrect_case_struct_method() {
1031 check_fix(
1032 r#"
1033pub struct TestStruct;
1034
1035impl TestStruct {
1036 pub fn SomeFn$0() -> TestStruct {
1037 TestStruct
1038 }
1039}
1040"#,
1041 r#"
1042pub struct TestStruct;
1043
1044impl TestStruct {
1045 pub fn some_fn() -> TestStruct {
1046 TestStruct
1047 }
1048}
1049"#,
1050 );
1051 }
1052
1053 #[test]
1054 fn test_single_incorrect_case_diagnostic_in_function_name_issue_6970() {
1055 let input = r#"fn FOO$0() {}"#;
1056 let expected = r#"fn foo() {}"#;
1057
1058 let (analysis, file_position) = fixture::position(input);
1059 let diagnostics = analysis
1060 .diagnostics(
1061 &DiagnosticsConfig::default(),
1062 AssistResolveStrategy::All,
1063 file_position.file_id,
1064 )
1065 .unwrap();
1066 assert_eq!(diagnostics.len(), 1);
1067
1068 check_fix(input, expected);
1069 }
1070
1071 #[test]
1072 fn unlinked_file_prepend_first_item() { 543 fn unlinked_file_prepend_first_item() {
1073 cov_mark::check!(unlinked_file_prepend_before_first_item); 544 cov_mark::check!(unlinked_file_prepend_before_first_item);
1074 check_fix( 545 check_fix(