aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--crates/ra_lsp_server/Cargo.toml1
-rw-r--r--crates/ra_lsp_server/src/cargo_check.rs709
-rw-r--r--crates/ra_lsp_server/src/snapshots/test__snap_clippy_pass_by_ref.snap85
-rw-r--r--crates/ra_lsp_server/src/snapshots/test__snap_handles_macro_location.snap46
-rw-r--r--crates/ra_lsp_server/src/snapshots/test__snap_rustc_incompatible_type_for_trait.snap46
-rw-r--r--crates/ra_lsp_server/src/snapshots/test__snap_rustc_mismatched_type.snap46
-rw-r--r--crates/ra_lsp_server/src/snapshots/test__snap_rustc_unused_variable.snap70
-rw-r--r--crates/ra_lsp_server/src/snapshots/test__snap_rustc_wrong_number_of_parameters.snap65
9 files changed, 1069 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 77c10a10e..08e4b7106 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1054,6 +1054,7 @@ dependencies = [
1054 "cargo_metadata 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", 1054 "cargo_metadata 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
1055 "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1055 "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1056 "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 1056 "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
1057 "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
1057 "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1058 "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1058 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1059 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1059 "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 1060 "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index aa1acdc33..54a01d7a2 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -30,6 +30,7 @@ env_logger = { version = "0.7.1", default-features = false, features = ["humanti
30cargo_metadata = "0.9.1" 30cargo_metadata = "0.9.1"
31 31
32[dev-dependencies] 32[dev-dependencies]
33insta = "0.12.0"
33tempfile = "3" 34tempfile = "3"
34test_utils = { path = "../test_utils" } 35test_utils = { path = "../test_utils" }
35 36
diff --git a/crates/ra_lsp_server/src/cargo_check.rs b/crates/ra_lsp_server/src/cargo_check.rs
index 30716fc43..5a6a209eb 100644
--- a/crates/ra_lsp_server/src/cargo_check.rs
+++ b/crates/ra_lsp_server/src/cargo_check.rs
@@ -461,6 +461,7 @@ fn map_rust_child_diagnostic(
461 } 461 }
462} 462}
463 463
464#[derive(Debug)]
464struct MappedRustDiagnostic { 465struct MappedRustDiagnostic {
465 location: Location, 466 location: Location,
466 diagnostic: Diagnostic, 467 diagnostic: Diagnostic,
@@ -563,3 +564,711 @@ fn are_diagnostics_equal(left: &Diagnostic, right: &Diagnostic) -> bool {
563 && left.range == right.range 564 && left.range == right.range
564 && left.message == right.message 565 && left.message == right.message
565} 566}
567
568#[cfg(test)]
569mod test {
570 use super::*;
571
572 fn parse_diagnostic(val: &str) -> cargo_metadata::diagnostic::Diagnostic {
573 serde_json::from_str::<cargo_metadata::diagnostic::Diagnostic>(val).unwrap()
574 }
575
576 #[test]
577 fn snap_rustc_incompatible_type_for_trait() {
578 let diag = parse_diagnostic(
579 r##"{
580 "message": "method `next` has an incompatible type for trait",
581 "code": {
582 "code": "E0053",
583 "explanation": "\nThe parameters of any trait method must match between a trait implementation\nand the trait definition.\n\nHere are a couple examples of this error:\n\n```compile_fail,E0053\ntrait Foo {\n fn foo(x: u16);\n fn bar(&self);\n}\n\nstruct Bar;\n\nimpl Foo for Bar {\n // error, expected u16, found i16\n fn foo(x: i16) { }\n\n // error, types differ in mutability\n fn bar(&mut self) { }\n}\n```\n"
584 },
585 "level": "error",
586 "spans": [
587 {
588 "file_name": "compiler/ty/list_iter.rs",
589 "byte_start": 1307,
590 "byte_end": 1350,
591 "line_start": 52,
592 "line_end": 52,
593 "column_start": 5,
594 "column_end": 48,
595 "is_primary": true,
596 "text": [
597 {
598 "text": " fn next(&self) -> Option<&'list ty::Ref<M>> {",
599 "highlight_start": 5,
600 "highlight_end": 48
601 }
602 ],
603 "label": "types differ in mutability",
604 "suggested_replacement": null,
605 "suggestion_applicability": null,
606 "expansion": null
607 }
608 ],
609 "children": [
610 {
611 "message": "expected type `fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref<M>>`\n found type `fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref<M>>`",
612 "code": null,
613 "level": "note",
614 "spans": [],
615 "children": [],
616 "rendered": null
617 }
618 ],
619 "rendered": "error[E0053]: method `next` has an incompatible type for trait\n --> compiler/ty/list_iter.rs:52:5\n |\n52 | fn next(&self) -> Option<&'list ty::Ref<M>> {\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability\n |\n = note: expected type `fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref<M>>`\n found type `fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref<M>>`\n\n"
620 }
621 "##,
622 );
623
624 let workspace_root = PathBuf::from("/test/");
625 let diag =
626 map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
627 insta::assert_debug_snapshot!(diag);
628 }
629
630 #[test]
631 fn snap_rustc_unused_variable() {
632 let diag = parse_diagnostic(
633 r##"{
634 "message": "unused variable: `foo`",
635 "code": {
636 "code": "unused_variables",
637 "explanation": null
638 },
639 "level": "warning",
640 "spans": [
641 {
642 "file_name": "driver/subcommand/repl.rs",
643 "byte_start": 9228,
644 "byte_end": 9231,
645 "line_start": 291,
646 "line_end": 291,
647 "column_start": 9,
648 "column_end": 12,
649 "is_primary": true,
650 "text": [
651 {
652 "text": " let foo = 42;",
653 "highlight_start": 9,
654 "highlight_end": 12
655 }
656 ],
657 "label": null,
658 "suggested_replacement": null,
659 "suggestion_applicability": null,
660 "expansion": null
661 }
662 ],
663 "children": [
664 {
665 "message": "#[warn(unused_variables)] on by default",
666 "code": null,
667 "level": "note",
668 "spans": [],
669 "children": [],
670 "rendered": null
671 },
672 {
673 "message": "consider prefixing with an underscore",
674 "code": null,
675 "level": "help",
676 "spans": [
677 {
678 "file_name": "driver/subcommand/repl.rs",
679 "byte_start": 9228,
680 "byte_end": 9231,
681 "line_start": 291,
682 "line_end": 291,
683 "column_start": 9,
684 "column_end": 12,
685 "is_primary": true,
686 "text": [
687 {
688 "text": " let foo = 42;",
689 "highlight_start": 9,
690 "highlight_end": 12
691 }
692 ],
693 "label": null,
694 "suggested_replacement": "_foo",
695 "suggestion_applicability": "MachineApplicable",
696 "expansion": null
697 }
698 ],
699 "children": [],
700 "rendered": null
701 }
702 ],
703 "rendered": "warning: unused variable: `foo`\n --> driver/subcommand/repl.rs:291:9\n |\n291 | let foo = 42;\n | ^^^ help: consider prefixing with an underscore: `_foo`\n |\n = note: #[warn(unused_variables)] on by default\n\n"
704}"##,
705 );
706
707 let workspace_root = PathBuf::from("/test/");
708 let diag =
709 map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
710 insta::assert_debug_snapshot!(diag);
711 }
712
713 #[test]
714 fn snap_rustc_wrong_number_of_parameters() {
715 let diag = parse_diagnostic(
716 r##"{
717 "message": "this function takes 2 parameters but 3 parameters were supplied",
718 "code": {
719 "code": "E0061",
720 "explanation": "\nThe number of arguments passed to a function must match the number of arguments\nspecified in the function signature.\n\nFor example, a function like:\n\n```\nfn f(a: u16, b: &str) {}\n```\n\nMust always be called with exactly two arguments, e.g., `f(2, \"test\")`.\n\nNote that Rust does not have a notion of optional function arguments or\nvariadic functions (except for its C-FFI).\n"
721 },
722 "level": "error",
723 "spans": [
724 {
725 "file_name": "compiler/ty/select.rs",
726 "byte_start": 8787,
727 "byte_end": 9241,
728 "line_start": 219,
729 "line_end": 231,
730 "column_start": 5,
731 "column_end": 6,
732 "is_primary": false,
733 "text": [
734 {
735 "text": " pub fn add_evidence(",
736 "highlight_start": 5,
737 "highlight_end": 25
738 },
739 {
740 "text": " &mut self,",
741 "highlight_start": 1,
742 "highlight_end": 19
743 },
744 {
745 "text": " target_poly: &ty::Ref<ty::Poly>,",
746 "highlight_start": 1,
747 "highlight_end": 41
748 },
749 {
750 "text": " evidence_poly: &ty::Ref<ty::Poly>,",
751 "highlight_start": 1,
752 "highlight_end": 43
753 },
754 {
755 "text": " ) {",
756 "highlight_start": 1,
757 "highlight_end": 8
758 },
759 {
760 "text": " match target_poly {",
761 "highlight_start": 1,
762 "highlight_end": 28
763 },
764 {
765 "text": " ty::Ref::Var(tvar, _) => self.add_var_evidence(tvar, evidence_poly),",
766 "highlight_start": 1,
767 "highlight_end": 81
768 },
769 {
770 "text": " ty::Ref::Fixed(target_ty) => {",
771 "highlight_start": 1,
772 "highlight_end": 43
773 },
774 {
775 "text": " let evidence_ty = evidence_poly.resolve_to_ty();",
776 "highlight_start": 1,
777 "highlight_end": 65
778 },
779 {
780 "text": " self.add_evidence_ty(target_ty, evidence_poly, evidence_ty)",
781 "highlight_start": 1,
782 "highlight_end": 76
783 },
784 {
785 "text": " }",
786 "highlight_start": 1,
787 "highlight_end": 14
788 },
789 {
790 "text": " }",
791 "highlight_start": 1,
792 "highlight_end": 10
793 },
794 {
795 "text": " }",
796 "highlight_start": 1,
797 "highlight_end": 6
798 }
799 ],
800 "label": "defined here",
801 "suggested_replacement": null,
802 "suggestion_applicability": null,
803 "expansion": null
804 },
805 {
806 "file_name": "compiler/ty/select.rs",
807 "byte_start": 4045,
808 "byte_end": 4057,
809 "line_start": 104,
810 "line_end": 104,
811 "column_start": 18,
812 "column_end": 30,
813 "is_primary": true,
814 "text": [
815 {
816 "text": " self.add_evidence(target_fixed, evidence_fixed, false);",
817 "highlight_start": 18,
818 "highlight_end": 30
819 }
820 ],
821 "label": "expected 2 parameters",
822 "suggested_replacement": null,
823 "suggestion_applicability": null,
824 "expansion": null
825 }
826 ],
827 "children": [],
828 "rendered": "error[E0061]: this function takes 2 parameters but 3 parameters were supplied\n --> compiler/ty/select.rs:104:18\n |\n104 | self.add_evidence(target_fixed, evidence_fixed, false);\n | ^^^^^^^^^^^^ expected 2 parameters\n...\n219 | / pub fn add_evidence(\n220 | | &mut self,\n221 | | target_poly: &ty::Ref<ty::Poly>,\n222 | | evidence_poly: &ty::Ref<ty::Poly>,\n... |\n230 | | }\n231 | | }\n | |_____- defined here\n\n"
829}"##,
830 );
831
832 let workspace_root = PathBuf::from("/test/");
833 let diag =
834 map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
835 insta::assert_debug_snapshot!(diag);
836 }
837
838 #[test]
839 fn snap_clippy_pass_by_ref() {
840 let diag = parse_diagnostic(
841 r##"{
842 "message": "this argument is passed by reference, but would be more efficient if passed by value",
843 "code": {
844 "code": "clippy::trivially_copy_pass_by_ref",
845 "explanation": null
846 },
847 "level": "warning",
848 "spans": [
849 {
850 "file_name": "compiler/mir/tagset.rs",
851 "byte_start": 941,
852 "byte_end": 946,
853 "line_start": 42,
854 "line_end": 42,
855 "column_start": 24,
856 "column_end": 29,
857 "is_primary": true,
858 "text": [
859 {
860 "text": " pub fn is_disjoint(&self, other: Self) -> bool {",
861 "highlight_start": 24,
862 "highlight_end": 29
863 }
864 ],
865 "label": null,
866 "suggested_replacement": null,
867 "suggestion_applicability": null,
868 "expansion": null
869 }
870 ],
871 "children": [
872 {
873 "message": "lint level defined here",
874 "code": null,
875 "level": "note",
876 "spans": [
877 {
878 "file_name": "compiler/lib.rs",
879 "byte_start": 8,
880 "byte_end": 19,
881 "line_start": 1,
882 "line_end": 1,
883 "column_start": 9,
884 "column_end": 20,
885 "is_primary": true,
886 "text": [
887 {
888 "text": "#![warn(clippy::all)]",
889 "highlight_start": 9,
890 "highlight_end": 20
891 }
892 ],
893 "label": null,
894 "suggested_replacement": null,
895 "suggestion_applicability": null,
896 "expansion": null
897 }
898 ],
899 "children": [],
900 "rendered": null
901 },
902 {
903 "message": "#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]",
904 "code": null,
905 "level": "note",
906 "spans": [],
907 "children": [],
908 "rendered": null
909 },
910 {
911 "message": "for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref",
912 "code": null,
913 "level": "help",
914 "spans": [],
915 "children": [],
916 "rendered": null
917 },
918 {
919 "message": "consider passing by value instead",
920 "code": null,
921 "level": "help",
922 "spans": [
923 {
924 "file_name": "compiler/mir/tagset.rs",
925 "byte_start": 941,
926 "byte_end": 946,
927 "line_start": 42,
928 "line_end": 42,
929 "column_start": 24,
930 "column_end": 29,
931 "is_primary": true,
932 "text": [
933 {
934 "text": " pub fn is_disjoint(&self, other: Self) -> bool {",
935 "highlight_start": 24,
936 "highlight_end": 29
937 }
938 ],
939 "label": null,
940 "suggested_replacement": "self",
941 "suggestion_applicability": "Unspecified",
942 "expansion": null
943 }
944 ],
945 "children": [],
946 "rendered": null
947 }
948 ],
949 "rendered": "warning: this argument is passed by reference, but would be more efficient if passed by value\n --> compiler/mir/tagset.rs:42:24\n |\n42 | pub fn is_disjoint(&self, other: Self) -> bool {\n | ^^^^^ help: consider passing by value instead: `self`\n |\nnote: lint level defined here\n --> compiler/lib.rs:1:9\n |\n1 | #![warn(clippy::all)]\n | ^^^^^^^^^^^\n = note: #[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]\n = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref\n\n"
950}"##,
951 );
952
953 let workspace_root = PathBuf::from("/test/");
954 let diag =
955 map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
956 insta::assert_debug_snapshot!(diag);
957 }
958
959 #[test]
960 fn snap_rustc_mismatched_type() {
961 let diag = parse_diagnostic(
962 r##"{
963 "message": "mismatched types",
964 "code": {
965 "code": "E0308",
966 "explanation": "\nThis error occurs when the compiler was unable to infer the concrete type of a\nvariable. It can occur for several cases, the most common of which is a\nmismatch in the expected type that the compiler inferred for a variable's\ninitializing expression, and the actual type explicitly assigned to the\nvariable.\n\nFor example:\n\n```compile_fail,E0308\nlet x: i32 = \"I am not a number!\";\n// ~~~ ~~~~~~~~~~~~~~~~~~~~\n// | |\n// | initializing expression;\n// | compiler infers type `&str`\n// |\n// type `i32` assigned to variable `x`\n```\n"
967 },
968 "level": "error",
969 "spans": [
970 {
971 "file_name": "runtime/compiler_support.rs",
972 "byte_start": 1589,
973 "byte_end": 1594,
974 "line_start": 48,
975 "line_end": 48,
976 "column_start": 65,
977 "column_end": 70,
978 "is_primary": true,
979 "text": [
980 {
981 "text": " let layout = alloc::Layout::from_size_align_unchecked(size, align);",
982 "highlight_start": 65,
983 "highlight_end": 70
984 }
985 ],
986 "label": "expected usize, found u32",
987 "suggested_replacement": null,
988 "suggestion_applicability": null,
989 "expansion": null
990 }
991 ],
992 "children": [],
993 "rendered": "error[E0308]: mismatched types\n --> runtime/compiler_support.rs:48:65\n |\n48 | let layout = alloc::Layout::from_size_align_unchecked(size, align);\n | ^^^^^ expected usize, found u32\n\n"
994}"##,
995 );
996
997 let workspace_root = PathBuf::from("/test/");
998 let diag =
999 map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
1000 insta::assert_debug_snapshot!(diag);
1001 }
1002
1003 #[test]
1004 fn snap_handles_macro_location() {
1005 let diag = parse_diagnostic(
1006 r##"{
1007 "rendered": "error[E0277]: can't compare `{integer}` with `&str`\n --> src/main.rs:2:5\n |\n2 | assert_eq!(1, \"love\");\n | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `{integer} == &str`\n |\n = help: the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`\n = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)\n\n",
1008 "children": [
1009 {
1010 "children": [],
1011 "code": null,
1012 "level": "help",
1013 "message": "the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`",
1014 "rendered": null,
1015 "spans": []
1016 }
1017 ],
1018 "code": {
1019 "code": "E0277",
1020 "explanation": "\nYou tried to use a type which doesn't implement some trait in a place which\nexpected that trait. Erroneous code example:\n\n```compile_fail,E0277\n// here we declare the Foo trait with a bar method\ntrait Foo {\n fn bar(&self);\n}\n\n// we now declare a function which takes an object implementing the Foo trait\nfn some_func<T: Foo>(foo: T) {\n foo.bar();\n}\n\nfn main() {\n // we now call the method with the i32 type, which doesn't implement\n // the Foo trait\n some_func(5i32); // error: the trait bound `i32 : Foo` is not satisfied\n}\n```\n\nIn order to fix this error, verify that the type you're using does implement\nthe trait. Example:\n\n```\ntrait Foo {\n fn bar(&self);\n}\n\nfn some_func<T: Foo>(foo: T) {\n foo.bar(); // we can now use this method since i32 implements the\n // Foo trait\n}\n\n// we implement the trait on the i32 type\nimpl Foo for i32 {\n fn bar(&self) {}\n}\n\nfn main() {\n some_func(5i32); // ok!\n}\n```\n\nOr in a generic context, an erroneous code example would look like:\n\n```compile_fail,E0277\nfn some_func<T>(foo: T) {\n println!(\"{:?}\", foo); // error: the trait `core::fmt::Debug` is not\n // implemented for the type `T`\n}\n\nfn main() {\n // We now call the method with the i32 type,\n // which *does* implement the Debug trait.\n some_func(5i32);\n}\n```\n\nNote that the error here is in the definition of the generic function: Although\nwe only call it with a parameter that does implement `Debug`, the compiler\nstill rejects the function: It must work with all possible input types. In\norder to make this example compile, we need to restrict the generic type we're\naccepting:\n\n```\nuse std::fmt;\n\n// Restrict the input type to types that implement Debug.\nfn some_func<T: fmt::Debug>(foo: T) {\n println!(\"{:?}\", foo);\n}\n\nfn main() {\n // Calling the method is still fine, as i32 implements Debug.\n some_func(5i32);\n\n // This would fail to compile now:\n // struct WithoutDebug;\n // some_func(WithoutDebug);\n}\n```\n\nRust only looks at the signature of the called function, as such it must\nalready specify all requirements that will be used for every type parameter.\n"
1021 },
1022 "level": "error",
1023 "message": "can't compare `{integer}` with `&str`",
1024 "spans": [
1025 {
1026 "byte_end": 155,
1027 "byte_start": 153,
1028 "column_end": 33,
1029 "column_start": 31,
1030 "expansion": {
1031 "def_site_span": {
1032 "byte_end": 940,
1033 "byte_start": 0,
1034 "column_end": 6,
1035 "column_start": 1,
1036 "expansion": null,
1037 "file_name": "<::core::macros::assert_eq macros>",
1038 "is_primary": false,
1039 "label": null,
1040 "line_end": 36,
1041 "line_start": 1,
1042 "suggested_replacement": null,
1043 "suggestion_applicability": null,
1044 "text": [
1045 {
1046 "highlight_end": 35,
1047 "highlight_start": 1,
1048 "text": "($ left : expr, $ right : expr) =>"
1049 },
1050 {
1051 "highlight_end": 3,
1052 "highlight_start": 1,
1053 "text": "({"
1054 },
1055 {
1056 "highlight_end": 33,
1057 "highlight_start": 1,
1058 "text": " match (& $ left, & $ right)"
1059 },
1060 {
1061 "highlight_end": 7,
1062 "highlight_start": 1,
1063 "text": " {"
1064 },
1065 {
1066 "highlight_end": 34,
1067 "highlight_start": 1,
1068 "text": " (left_val, right_val) =>"
1069 },
1070 {
1071 "highlight_end": 11,
1072 "highlight_start": 1,
1073 "text": " {"
1074 },
1075 {
1076 "highlight_end": 46,
1077 "highlight_start": 1,
1078 "text": " if ! (* left_val == * right_val)"
1079 },
1080 {
1081 "highlight_end": 15,
1082 "highlight_start": 1,
1083 "text": " {"
1084 },
1085 {
1086 "highlight_end": 25,
1087 "highlight_start": 1,
1088 "text": " panic !"
1089 },
1090 {
1091 "highlight_end": 57,
1092 "highlight_start": 1,
1093 "text": " (r#\"assertion failed: `(left == right)`"
1094 },
1095 {
1096 "highlight_end": 16,
1097 "highlight_start": 1,
1098 "text": " left: `{:?}`,"
1099 },
1100 {
1101 "highlight_end": 18,
1102 "highlight_start": 1,
1103 "text": " right: `{:?}`\"#,"
1104 },
1105 {
1106 "highlight_end": 47,
1107 "highlight_start": 1,
1108 "text": " & * left_val, & * right_val)"
1109 },
1110 {
1111 "highlight_end": 15,
1112 "highlight_start": 1,
1113 "text": " }"
1114 },
1115 {
1116 "highlight_end": 11,
1117 "highlight_start": 1,
1118 "text": " }"
1119 },
1120 {
1121 "highlight_end": 7,
1122 "highlight_start": 1,
1123 "text": " }"
1124 },
1125 {
1126 "highlight_end": 42,
1127 "highlight_start": 1,
1128 "text": " }) ; ($ left : expr, $ right : expr,) =>"
1129 },
1130 {
1131 "highlight_end": 49,
1132 "highlight_start": 1,
1133 "text": "({ $ crate :: assert_eq ! ($ left, $ right) }) ;"
1134 },
1135 {
1136 "highlight_end": 53,
1137 "highlight_start": 1,
1138 "text": "($ left : expr, $ right : expr, $ ($ arg : tt) +) =>"
1139 },
1140 {
1141 "highlight_end": 3,
1142 "highlight_start": 1,
1143 "text": "({"
1144 },
1145 {
1146 "highlight_end": 37,
1147 "highlight_start": 1,
1148 "text": " match (& ($ left), & ($ right))"
1149 },
1150 {
1151 "highlight_end": 7,
1152 "highlight_start": 1,
1153 "text": " {"
1154 },
1155 {
1156 "highlight_end": 34,
1157 "highlight_start": 1,
1158 "text": " (left_val, right_val) =>"
1159 },
1160 {
1161 "highlight_end": 11,
1162 "highlight_start": 1,
1163 "text": " {"
1164 },
1165 {
1166 "highlight_end": 46,
1167 "highlight_start": 1,
1168 "text": " if ! (* left_val == * right_val)"
1169 },
1170 {
1171 "highlight_end": 15,
1172 "highlight_start": 1,
1173 "text": " {"
1174 },
1175 {
1176 "highlight_end": 25,
1177 "highlight_start": 1,
1178 "text": " panic !"
1179 },
1180 {
1181 "highlight_end": 57,
1182 "highlight_start": 1,
1183 "text": " (r#\"assertion failed: `(left == right)`"
1184 },
1185 {
1186 "highlight_end": 16,
1187 "highlight_start": 1,
1188 "text": " left: `{:?}`,"
1189 },
1190 {
1191 "highlight_end": 22,
1192 "highlight_start": 1,
1193 "text": " right: `{:?}`: {}\"#,"
1194 },
1195 {
1196 "highlight_end": 72,
1197 "highlight_start": 1,
1198 "text": " & * left_val, & * right_val, $ crate :: format_args !"
1199 },
1200 {
1201 "highlight_end": 33,
1202 "highlight_start": 1,
1203 "text": " ($ ($ arg) +))"
1204 },
1205 {
1206 "highlight_end": 15,
1207 "highlight_start": 1,
1208 "text": " }"
1209 },
1210 {
1211 "highlight_end": 11,
1212 "highlight_start": 1,
1213 "text": " }"
1214 },
1215 {
1216 "highlight_end": 7,
1217 "highlight_start": 1,
1218 "text": " }"
1219 },
1220 {
1221 "highlight_end": 6,
1222 "highlight_start": 1,
1223 "text": " }) ;"
1224 }
1225 ]
1226 },
1227 "macro_decl_name": "assert_eq!",
1228 "span": {
1229 "byte_end": 38,
1230 "byte_start": 16,
1231 "column_end": 27,
1232 "column_start": 5,
1233 "expansion": null,
1234 "file_name": "src/main.rs",
1235 "is_primary": false,
1236 "label": null,
1237 "line_end": 2,
1238 "line_start": 2,
1239 "suggested_replacement": null,
1240 "suggestion_applicability": null,
1241 "text": [
1242 {
1243 "highlight_end": 27,
1244 "highlight_start": 5,
1245 "text": " assert_eq!(1, \"love\");"
1246 }
1247 ]
1248 }
1249 },
1250 "file_name": "<::core::macros::assert_eq macros>",
1251 "is_primary": true,
1252 "label": "no implementation for `{integer} == &str`",
1253 "line_end": 7,
1254 "line_start": 7,
1255 "suggested_replacement": null,
1256 "suggestion_applicability": null,
1257 "text": [
1258 {
1259 "highlight_end": 33,
1260 "highlight_start": 31,
1261 "text": " if ! (* left_val == * right_val)"
1262 }
1263 ]
1264 }
1265 ]
1266}"##,
1267 );
1268
1269 let workspace_root = PathBuf::from("/test/");
1270 let diag =
1271 map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
1272 insta::assert_debug_snapshot!(diag);
1273 }
1274}
diff --git a/crates/ra_lsp_server/src/snapshots/test__snap_clippy_pass_by_ref.snap b/crates/ra_lsp_server/src/snapshots/test__snap_clippy_pass_by_ref.snap
new file mode 100644
index 000000000..a5ce29157
--- /dev/null
+++ b/crates/ra_lsp_server/src/snapshots/test__snap_clippy_pass_by_ref.snap
@@ -0,0 +1,85 @@
1---
2source: crates/ra_lsp_server/src/cargo_check.rs
3expression: diag
4---
5MappedRustDiagnostic {
6 location: Location {
7 uri: "file:///test/compiler/mir/tagset.rs",
8 range: Range {
9 start: Position {
10 line: 41,
11 character: 23,
12 },
13 end: Position {
14 line: 41,
15 character: 28,
16 },
17 },
18 },
19 diagnostic: Diagnostic {
20 range: Range {
21 start: Position {
22 line: 41,
23 character: 23,
24 },
25 end: Position {
26 line: 41,
27 character: 28,
28 },
29 },
30 severity: Some(
31 Warning,
32 ),
33 code: Some(
34 String(
35 "trivially_copy_pass_by_ref",
36 ),
37 ),
38 source: Some(
39 "clippy",
40 ),
41 message: "this argument is passed by reference, but would be more efficient if passed by value\n#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref",
42 related_information: Some(
43 [
44 DiagnosticRelatedInformation {
45 location: Location {
46 uri: "file:///test/compiler/lib.rs",
47 range: Range {
48 start: Position {
49 line: 0,
50 character: 8,
51 },
52 end: Position {
53 line: 0,
54 character: 19,
55 },
56 },
57 },
58 message: "lint level defined here",
59 },
60 ],
61 ),
62 tags: None,
63 },
64 suggested_fixes: [
65 SuggestedFix {
66 title: "consider passing by value instead: \'self\'",
67 location: Location {
68 uri: "file:///test/compiler/mir/tagset.rs",
69 range: Range {
70 start: Position {
71 line: 41,
72 character: 23,
73 },
74 end: Position {
75 line: 41,
76 character: 28,
77 },
78 },
79 },
80 replacement: "self",
81 applicability: Unspecified,
82 diagnostics: [],
83 },
84 ],
85}
diff --git a/crates/ra_lsp_server/src/snapshots/test__snap_handles_macro_location.snap b/crates/ra_lsp_server/src/snapshots/test__snap_handles_macro_location.snap
new file mode 100644
index 000000000..07e363ebf
--- /dev/null
+++ b/crates/ra_lsp_server/src/snapshots/test__snap_handles_macro_location.snap
@@ -0,0 +1,46 @@
1---
2source: crates/ra_lsp_server/src/cargo_check.rs
3expression: diag
4---
5MappedRustDiagnostic {
6 location: Location {
7 uri: "file:///test/src/main.rs",
8 range: Range {
9 start: Position {
10 line: 1,
11 character: 4,
12 },
13 end: Position {
14 line: 1,
15 character: 26,
16 },
17 },
18 },
19 diagnostic: Diagnostic {
20 range: Range {
21 start: Position {
22 line: 1,
23 character: 4,
24 },
25 end: Position {
26 line: 1,
27 character: 26,
28 },
29 },
30 severity: Some(
31 Error,
32 ),
33 code: Some(
34 String(
35 "E0277",
36 ),
37 ),
38 source: Some(
39 "rustc",
40 ),
41 message: "can\'t compare `{integer}` with `&str`\nthe trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`",
42 related_information: None,
43 tags: None,
44 },
45 suggested_fixes: [],
46}
diff --git a/crates/ra_lsp_server/src/snapshots/test__snap_rustc_incompatible_type_for_trait.snap b/crates/ra_lsp_server/src/snapshots/test__snap_rustc_incompatible_type_for_trait.snap
new file mode 100644
index 000000000..85a87db0b
--- /dev/null
+++ b/crates/ra_lsp_server/src/snapshots/test__snap_rustc_incompatible_type_for_trait.snap
@@ -0,0 +1,46 @@
1---
2source: crates/ra_lsp_server/src/cargo_check.rs
3expression: diag
4---
5MappedRustDiagnostic {
6 location: Location {
7 uri: "file:///test/compiler/ty/list_iter.rs",
8 range: Range {
9 start: Position {
10 line: 51,
11 character: 4,
12 },
13 end: Position {
14 line: 51,
15 character: 47,
16 },
17 },
18 },
19 diagnostic: Diagnostic {
20 range: Range {
21 start: Position {
22 line: 51,
23 character: 4,
24 },
25 end: Position {
26 line: 51,
27 character: 47,
28 },
29 },
30 severity: Some(
31 Error,
32 ),
33 code: Some(
34 String(
35 "E0053",
36 ),
37 ),
38 source: Some(
39 "rustc",
40 ),
41 message: "method `next` has an incompatible type for trait\nexpected type `fn(&mut ty::list_iter::ListIterator<\'list, M>) -> std::option::Option<&ty::Ref<M>>`\n found type `fn(&ty::list_iter::ListIterator<\'list, M>) -> std::option::Option<&\'list ty::Ref<M>>`",
42 related_information: None,
43 tags: None,
44 },
45 suggested_fixes: [],
46}
diff --git a/crates/ra_lsp_server/src/snapshots/test__snap_rustc_mismatched_type.snap b/crates/ra_lsp_server/src/snapshots/test__snap_rustc_mismatched_type.snap
new file mode 100644
index 000000000..69cb8badf
--- /dev/null
+++ b/crates/ra_lsp_server/src/snapshots/test__snap_rustc_mismatched_type.snap
@@ -0,0 +1,46 @@
1---
2source: crates/ra_lsp_server/src/cargo_check.rs
3expression: diag
4---
5MappedRustDiagnostic {
6 location: Location {
7 uri: "file:///test/runtime/compiler_support.rs",
8 range: Range {
9 start: Position {
10 line: 47,
11 character: 64,
12 },
13 end: Position {
14 line: 47,
15 character: 69,
16 },
17 },
18 },
19 diagnostic: Diagnostic {
20 range: Range {
21 start: Position {
22 line: 47,
23 character: 64,
24 },
25 end: Position {
26 line: 47,
27 character: 69,
28 },
29 },
30 severity: Some(
31 Error,
32 ),
33 code: Some(
34 String(
35 "E0308",
36 ),
37 ),
38 source: Some(
39 "rustc",
40 ),
41 message: "mismatched types\nexpected usize, found u32",
42 related_information: None,
43 tags: None,
44 },
45 suggested_fixes: [],
46}
diff --git a/crates/ra_lsp_server/src/snapshots/test__snap_rustc_unused_variable.snap b/crates/ra_lsp_server/src/snapshots/test__snap_rustc_unused_variable.snap
new file mode 100644
index 000000000..33a3e3034
--- /dev/null
+++ b/crates/ra_lsp_server/src/snapshots/test__snap_rustc_unused_variable.snap
@@ -0,0 +1,70 @@
1---
2source: crates/ra_lsp_server/src/cargo_check.rs
3expression: diag
4---
5MappedRustDiagnostic {
6 location: Location {
7 uri: "file:///test/driver/subcommand/repl.rs",
8 range: Range {
9 start: Position {
10 line: 290,
11 character: 8,
12 },
13 end: Position {
14 line: 290,
15 character: 11,
16 },
17 },
18 },
19 diagnostic: Diagnostic {
20 range: Range {
21 start: Position {
22 line: 290,
23 character: 8,
24 },
25 end: Position {
26 line: 290,
27 character: 11,
28 },
29 },
30 severity: Some(
31 Warning,
32 ),
33 code: Some(
34 String(
35 "unused_variables",
36 ),
37 ),
38 source: Some(
39 "rustc",
40 ),
41 message: "unused variable: `foo`\n#[warn(unused_variables)] on by default",
42 related_information: None,
43 tags: Some(
44 [
45 Unnecessary,
46 ],
47 ),
48 },
49 suggested_fixes: [
50 SuggestedFix {
51 title: "consider prefixing with an underscore: \'_foo\'",
52 location: Location {
53 uri: "file:///test/driver/subcommand/repl.rs",
54 range: Range {
55 start: Position {
56 line: 290,
57 character: 8,
58 },
59 end: Position {
60 line: 290,
61 character: 11,
62 },
63 },
64 },
65 replacement: "_foo",
66 applicability: MachineApplicable,
67 diagnostics: [],
68 },
69 ],
70}
diff --git a/crates/ra_lsp_server/src/snapshots/test__snap_rustc_wrong_number_of_parameters.snap b/crates/ra_lsp_server/src/snapshots/test__snap_rustc_wrong_number_of_parameters.snap
new file mode 100644
index 000000000..ced6fa4df
--- /dev/null
+++ b/crates/ra_lsp_server/src/snapshots/test__snap_rustc_wrong_number_of_parameters.snap
@@ -0,0 +1,65 @@
1---
2source: crates/ra_lsp_server/src/cargo_check.rs
3expression: diag
4---
5MappedRustDiagnostic {
6 location: Location {
7 uri: "file:///test/compiler/ty/select.rs",
8 range: Range {
9 start: Position {
10 line: 103,
11 character: 17,
12 },
13 end: Position {
14 line: 103,
15 character: 29,
16 },
17 },
18 },
19 diagnostic: Diagnostic {
20 range: Range {
21 start: Position {
22 line: 103,
23 character: 17,
24 },
25 end: Position {
26 line: 103,
27 character: 29,
28 },
29 },
30 severity: Some(
31 Error,
32 ),
33 code: Some(
34 String(
35 "E0061",
36 ),
37 ),
38 source: Some(
39 "rustc",
40 ),
41 message: "this function takes 2 parameters but 3 parameters were supplied\nexpected 2 parameters",
42 related_information: Some(
43 [
44 DiagnosticRelatedInformation {
45 location: Location {
46 uri: "file:///test/compiler/ty/select.rs",
47 range: Range {
48 start: Position {
49 line: 218,
50 character: 4,
51 },
52 end: Position {
53 line: 230,
54 character: 5,
55 },
56 },
57 },
58 message: "defined here",
59 },
60 ],
61 ),
62 tags: None,
63 },
64 suggested_fixes: [],
65}