aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db/src/helpers/insert_use.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_db/src/helpers/insert_use.rs')
-rw-r--r--crates/ide_db/src/helpers/insert_use.rs639
1 files changed, 1 insertions, 638 deletions
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs
index 08d246c16..040843990 100644
--- a/crates/ide_db/src/helpers/insert_use.rs
+++ b/crates/ide_db/src/helpers/insert_use.rs
@@ -573,641 +573,4 @@ fn find_insert_position(
573} 573}
574 574
575#[cfg(test)] 575#[cfg(test)]
576mod tests { 576mod tests;
577 use super::*;
578
579 use test_utils::assert_eq_text;
580
581 #[test]
582 fn insert_existing() {
583 check_full("std::fs", "use std::fs;", "use std::fs;")
584 }
585
586 #[test]
587 fn insert_start() {
588 check_none(
589 "std::bar::AA",
590 r"
591use std::bar::B;
592use std::bar::D;
593use std::bar::F;
594use std::bar::G;",
595 r"
596use std::bar::AA;
597use std::bar::B;
598use std::bar::D;
599use std::bar::F;
600use std::bar::G;",
601 )
602 }
603
604 #[test]
605 fn insert_start_indent() {
606 mark::check!(insert_use_indent_after);
607 check_none(
608 "std::bar::AA",
609 r"
610 use std::bar::B;
611 use std::bar::D;",
612 r"
613 use std::bar::AA;
614 use std::bar::B;
615 use std::bar::D;",
616 )
617 }
618
619 #[test]
620 fn insert_middle() {
621 check_none(
622 "std::bar::EE",
623 r"
624use std::bar::A;
625use std::bar::D;
626use std::bar::F;
627use std::bar::G;",
628 r"
629use std::bar::A;
630use std::bar::D;
631use std::bar::EE;
632use std::bar::F;
633use std::bar::G;",
634 )
635 }
636
637 #[test]
638 fn insert_middle_indent() {
639 check_none(
640 "std::bar::EE",
641 r"
642 use std::bar::A;
643 use std::bar::D;
644 use std::bar::F;
645 use std::bar::G;",
646 r"
647 use std::bar::A;
648 use std::bar::D;
649 use std::bar::EE;
650 use std::bar::F;
651 use std::bar::G;",
652 )
653 }
654
655 #[test]
656 fn insert_end() {
657 check_none(
658 "std::bar::ZZ",
659 r"
660use std::bar::A;
661use std::bar::D;
662use std::bar::F;
663use std::bar::G;",
664 r"
665use std::bar::A;
666use std::bar::D;
667use std::bar::F;
668use std::bar::G;
669use std::bar::ZZ;",
670 )
671 }
672
673 #[test]
674 fn insert_end_indent() {
675 mark::check!(insert_use_indent_before);
676 check_none(
677 "std::bar::ZZ",
678 r"
679 use std::bar::A;
680 use std::bar::D;
681 use std::bar::F;
682 use std::bar::G;",
683 r"
684 use std::bar::A;
685 use std::bar::D;
686 use std::bar::F;
687 use std::bar::G;
688 use std::bar::ZZ;",
689 )
690 }
691
692 #[test]
693 fn insert_middle_nested() {
694 check_none(
695 "std::bar::EE",
696 r"
697use std::bar::A;
698use std::bar::{D, Z}; // example of weird imports due to user
699use std::bar::F;
700use std::bar::G;",
701 r"
702use std::bar::A;
703use std::bar::EE;
704use std::bar::{D, Z}; // example of weird imports due to user
705use std::bar::F;
706use std::bar::G;",
707 )
708 }
709
710 #[test]
711 fn insert_middle_groups() {
712 check_none(
713 "foo::bar::GG",
714 r"
715 use std::bar::A;
716 use std::bar::D;
717
718 use foo::bar::F;
719 use foo::bar::H;",
720 r"
721 use std::bar::A;
722 use std::bar::D;
723
724 use foo::bar::F;
725 use foo::bar::GG;
726 use foo::bar::H;",
727 )
728 }
729
730 #[test]
731 fn insert_first_matching_group() {
732 check_none(
733 "foo::bar::GG",
734 r"
735 use foo::bar::A;
736 use foo::bar::D;
737
738 use std;
739
740 use foo::bar::F;
741 use foo::bar::H;",
742 r"
743 use foo::bar::A;
744 use foo::bar::D;
745 use foo::bar::GG;
746
747 use std;
748
749 use foo::bar::F;
750 use foo::bar::H;",
751 )
752 }
753
754 #[test]
755 fn insert_missing_group_std() {
756 check_none(
757 "std::fmt",
758 r"
759 use foo::bar::A;
760 use foo::bar::D;",
761 r"
762 use std::fmt;
763
764 use foo::bar::A;
765 use foo::bar::D;",
766 )
767 }
768
769 #[test]
770 fn insert_missing_group_self() {
771 check_none(
772 "self::fmt",
773 r"
774use foo::bar::A;
775use foo::bar::D;",
776 r"
777use foo::bar::A;
778use foo::bar::D;
779
780use self::fmt;",
781 )
782 }
783
784 #[test]
785 fn insert_no_imports() {
786 check_full(
787 "foo::bar",
788 "fn main() {}",
789 r"use foo::bar;
790
791fn main() {}",
792 )
793 }
794
795 #[test]
796 fn insert_empty_file() {
797 // empty files will get two trailing newlines
798 // this is due to the test case insert_no_imports above
799 check_full(
800 "foo::bar",
801 "",
802 r"use foo::bar;
803
804",
805 )
806 }
807
808 #[test]
809 fn insert_empty_module() {
810 mark::check!(insert_use_no_indent_after);
811 check(
812 "foo::bar",
813 "mod x {}",
814 r"{
815 use foo::bar;
816}",
817 None,
818 true,
819 )
820 }
821
822 #[test]
823 fn insert_after_inner_attr() {
824 check_full(
825 "foo::bar",
826 r"#![allow(unused_imports)]",
827 r"#![allow(unused_imports)]
828
829use foo::bar;",
830 )
831 }
832
833 #[test]
834 fn insert_after_inner_attr2() {
835 check_full(
836 "foo::bar",
837 r"#![allow(unused_imports)]
838
839#![no_std]
840fn main() {}",
841 r"#![allow(unused_imports)]
842
843#![no_std]
844
845use foo::bar;
846fn main() {}",
847 );
848 }
849
850 #[test]
851 fn inserts_after_single_line_inner_comments() {
852 check_none(
853 "foo::bar::Baz",
854 "//! Single line inner comments do not allow any code before them.",
855 r#"//! Single line inner comments do not allow any code before them.
856
857use foo::bar::Baz;"#,
858 );
859 }
860
861 #[test]
862 fn inserts_after_multiline_inner_comments() {
863 check_none(
864 "foo::bar::Baz",
865 r#"/*! Multiline inner comments do not allow any code before them. */
866
867/*! Still an inner comment, cannot place any code before. */
868fn main() {}"#,
869 r#"/*! Multiline inner comments do not allow any code before them. */
870
871/*! Still an inner comment, cannot place any code before. */
872
873use foo::bar::Baz;
874fn main() {}"#,
875 )
876 }
877
878 #[test]
879 fn inserts_after_all_inner_items() {
880 check_none(
881 "foo::bar::Baz",
882 r#"#![allow(unused_imports)]
883/*! Multiline line comment 2 */
884
885
886//! Single line comment 1
887#![no_std]
888//! Single line comment 2
889fn main() {}"#,
890 r#"#![allow(unused_imports)]
891/*! Multiline line comment 2 */
892
893
894//! Single line comment 1
895#![no_std]
896//! Single line comment 2
897
898use foo::bar::Baz;
899fn main() {}"#,
900 )
901 }
902
903 #[test]
904 fn merge_groups() {
905 check_last("std::io", r"use std::fmt;", r"use std::{fmt, io};")
906 }
907
908 #[test]
909 fn merge_groups_last() {
910 check_last(
911 "std::io",
912 r"use std::fmt::{Result, Display};",
913 r"use std::fmt::{Result, Display};
914use std::io;",
915 )
916 }
917
918 #[test]
919 fn merge_last_into_self() {
920 check_last("foo::bar::baz", r"use foo::bar;", r"use foo::bar::{self, baz};");
921 }
922
923 #[test]
924 fn merge_groups_full() {
925 check_full(
926 "std::io",
927 r"use std::fmt::{Result, Display};",
928 r"use std::{fmt::{Result, Display}, io};",
929 )
930 }
931
932 #[test]
933 fn merge_groups_long_full() {
934 check_full(
935 "std::foo::bar::Baz",
936 r"use std::foo::bar::Qux;",
937 r"use std::foo::bar::{Baz, Qux};",
938 )
939 }
940
941 #[test]
942 fn merge_groups_long_last() {
943 check_last(
944 "std::foo::bar::Baz",
945 r"use std::foo::bar::Qux;",
946 r"use std::foo::bar::{Baz, Qux};",
947 )
948 }
949
950 #[test]
951 fn merge_groups_long_full_list() {
952 check_full(
953 "std::foo::bar::Baz",
954 r"use std::foo::bar::{Qux, Quux};",
955 r"use std::foo::bar::{Baz, Quux, Qux};",
956 )
957 }
958
959 #[test]
960 fn merge_groups_long_last_list() {
961 check_last(
962 "std::foo::bar::Baz",
963 r"use std::foo::bar::{Qux, Quux};",
964 r"use std::foo::bar::{Baz, Quux, Qux};",
965 )
966 }
967
968 #[test]
969 fn merge_groups_long_full_nested() {
970 check_full(
971 "std::foo::bar::Baz",
972 r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
973 r"use std::foo::bar::{Baz, Qux, quux::{Fez, Fizz}};",
974 )
975 }
976
977 #[test]
978 fn merge_groups_long_last_nested() {
979 check_last(
980 "std::foo::bar::Baz",
981 r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
982 r"use std::foo::bar::Baz;
983use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
984 )
985 }
986
987 #[test]
988 fn merge_groups_full_nested_deep() {
989 check_full(
990 "std::foo::bar::quux::Baz",
991 r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
992 r"use std::foo::bar::{Qux, quux::{Baz, Fez, Fizz}};",
993 )
994 }
995
996 #[test]
997 fn merge_groups_full_nested_long() {
998 check_full(
999 "std::foo::bar::Baz",
1000 r"use std::{foo::bar::Qux};",
1001 r"use std::{foo::bar::{Baz, Qux}};",
1002 );
1003 }
1004
1005 #[test]
1006 fn merge_groups_last_nested_long() {
1007 check_full(
1008 "std::foo::bar::Baz",
1009 r"use std::{foo::bar::Qux};",
1010 r"use std::{foo::bar::{Baz, Qux}};",
1011 );
1012 }
1013
1014 #[test]
1015 fn merge_groups_skip_pub() {
1016 check_full(
1017 "std::io",
1018 r"pub use std::fmt::{Result, Display};",
1019 r"pub use std::fmt::{Result, Display};
1020use std::io;",
1021 )
1022 }
1023
1024 #[test]
1025 fn merge_groups_skip_pub_crate() {
1026 check_full(
1027 "std::io",
1028 r"pub(crate) use std::fmt::{Result, Display};",
1029 r"pub(crate) use std::fmt::{Result, Display};
1030use std::io;",
1031 )
1032 }
1033
1034 #[test]
1035 #[ignore] // FIXME: Support this
1036 fn split_out_merge() {
1037 check_last(
1038 "std::fmt::Result",
1039 r"use std::{fmt, io};",
1040 r"use std::fmt::{self, Result};
1041use std::io;",
1042 )
1043 }
1044
1045 #[test]
1046 fn merge_into_module_import() {
1047 check_full(
1048 "std::fmt::Result",
1049 r"use std::{fmt, io};",
1050 r"use std::{fmt::{self, Result}, io};",
1051 )
1052 }
1053
1054 #[test]
1055 fn merge_groups_self() {
1056 check_full("std::fmt::Debug", r"use std::fmt;", r"use std::fmt::{self, Debug};")
1057 }
1058
1059 #[test]
1060 fn merge_mod_into_glob() {
1061 check_full(
1062 "token::TokenKind",
1063 r"use token::TokenKind::*;",
1064 r"use token::TokenKind::{*, self};",
1065 )
1066 // FIXME: have it emit `use token::TokenKind::{self, *}`?
1067 }
1068
1069 #[test]
1070 fn merge_self_glob() {
1071 check_full("self", r"use self::*;", r"use self::{*, self};")
1072 // FIXME: have it emit `use {self, *}`?
1073 }
1074
1075 #[test]
1076 fn merge_glob_nested() {
1077 check_full(
1078 "foo::bar::quux::Fez",
1079 r"use foo::bar::{Baz, quux::*};",
1080 r"use foo::bar::{Baz, quux::{self::*, Fez}};",
1081 )
1082 }
1083
1084 #[test]
1085 fn merge_nested_considers_first_segments() {
1086 check_full(
1087 "hir_ty::display::write_bounds_like_dyn_trait",
1088 r"use hir_ty::{autoderef, display::{HirDisplayError, HirFormatter}, method_resolution};",
1089 r"use hir_ty::{autoderef, display::{HirDisplayError, HirFormatter, write_bounds_like_dyn_trait}, method_resolution};",
1090 );
1091 }
1092
1093 #[test]
1094 fn skip_merge_last_too_long() {
1095 check_last(
1096 "foo::bar",
1097 r"use foo::bar::baz::Qux;",
1098 r"use foo::bar;
1099use foo::bar::baz::Qux;",
1100 );
1101 }
1102
1103 #[test]
1104 fn skip_merge_last_too_long2() {
1105 check_last(
1106 "foo::bar::baz::Qux",
1107 r"use foo::bar;",
1108 r"use foo::bar;
1109use foo::bar::baz::Qux;",
1110 );
1111 }
1112
1113 #[test]
1114 fn insert_short_before_long() {
1115 check_none(
1116 "foo::bar",
1117 r"use foo::bar::baz::Qux;",
1118 r"use foo::bar;
1119use foo::bar::baz::Qux;",
1120 );
1121 }
1122
1123 #[test]
1124 fn merge_last_fail() {
1125 check_merge_only_fail(
1126 r"use foo::bar::{baz::{Qux, Fez}};",
1127 r"use foo::bar::{baaz::{Quux, Feez}};",
1128 MergeBehaviour::Last,
1129 );
1130 }
1131
1132 #[test]
1133 fn merge_last_fail1() {
1134 check_merge_only_fail(
1135 r"use foo::bar::{baz::{Qux, Fez}};",
1136 r"use foo::bar::baaz::{Quux, Feez};",
1137 MergeBehaviour::Last,
1138 );
1139 }
1140
1141 #[test]
1142 fn merge_last_fail2() {
1143 check_merge_only_fail(
1144 r"use foo::bar::baz::{Qux, Fez};",
1145 r"use foo::bar::{baaz::{Quux, Feez}};",
1146 MergeBehaviour::Last,
1147 );
1148 }
1149
1150 #[test]
1151 fn merge_last_fail3() {
1152 check_merge_only_fail(
1153 r"use foo::bar::baz::{Qux, Fez};",
1154 r"use foo::bar::baaz::{Quux, Feez};",
1155 MergeBehaviour::Last,
1156 );
1157 }
1158
1159 fn check(
1160 path: &str,
1161 ra_fixture_before: &str,
1162 ra_fixture_after: &str,
1163 mb: Option<MergeBehaviour>,
1164 module: bool,
1165 ) {
1166 let mut syntax = ast::SourceFile::parse(ra_fixture_before).tree().syntax().clone();
1167 if module {
1168 syntax = syntax.descendants().find_map(ast::Module::cast).unwrap().syntax().clone();
1169 }
1170 let file = super::ImportScope::from(syntax).unwrap();
1171 let path = ast::SourceFile::parse(&format!("use {};", path))
1172 .tree()
1173 .syntax()
1174 .descendants()
1175 .find_map(ast::Path::cast)
1176 .unwrap();
1177
1178 let rewriter = insert_use(&file, path, mb);
1179 let result = rewriter.rewrite(file.as_syntax_node()).to_string();
1180 assert_eq_text!(&result, ra_fixture_after);
1181 }
1182
1183 fn check_full(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
1184 check(path, ra_fixture_before, ra_fixture_after, Some(MergeBehaviour::Full), false)
1185 }
1186
1187 fn check_last(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
1188 check(path, ra_fixture_before, ra_fixture_after, Some(MergeBehaviour::Last), false)
1189 }
1190
1191 fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
1192 check(path, ra_fixture_before, ra_fixture_after, None, false)
1193 }
1194
1195 fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehaviour) {
1196 let use0 = ast::SourceFile::parse(ra_fixture0)
1197 .tree()
1198 .syntax()
1199 .descendants()
1200 .find_map(ast::Use::cast)
1201 .unwrap();
1202
1203 let use1 = ast::SourceFile::parse(ra_fixture1)
1204 .tree()
1205 .syntax()
1206 .descendants()
1207 .find_map(ast::Use::cast)
1208 .unwrap();
1209
1210 let result = try_merge_imports(&use0, &use1, mb);
1211 assert_eq!(result.map(|u| u.to_string()), None);
1212 }
1213}