1 use base_db::fixture::WithFixture;
2 use hir::PrefixKind;
3 use stdx::trim_indent;
4 use test_utils::{assert_eq_text, CURSOR_MARKER};
5
6 use super::*;
7
8 #[test]
trailing_comment_in_empty_file()9 fn trailing_comment_in_empty_file() {
10 check(
11 "foo::bar",
12 r#"
13 struct Struct;
14 // 0 = 1
15 "#,
16 r#"
17 use foo::bar;
18
19 struct Struct;
20 // 0 = 1
21 "#,
22 ImportGranularity::Crate,
23 );
24 }
25
26 #[test]
respects_cfg_attr_fn()27 fn respects_cfg_attr_fn() {
28 check(
29 r"bar::Bar",
30 r#"
31 #[cfg(test)]
32 fn foo() {$0}
33 "#,
34 r#"
35 #[cfg(test)]
36 fn foo() {
37 use bar::Bar;
38 }
39 "#,
40 ImportGranularity::Crate,
41 );
42 }
43
44 #[test]
respects_cfg_attr_const()45 fn respects_cfg_attr_const() {
46 check(
47 r"bar::Bar",
48 r#"
49 #[cfg(test)]
50 const FOO: Bar = {$0};
51 "#,
52 r#"
53 #[cfg(test)]
54 const FOO: Bar = {
55 use bar::Bar;
56 };
57 "#,
58 ImportGranularity::Crate,
59 );
60 }
61
62 #[test]
insert_skips_lone_glob_imports()63 fn insert_skips_lone_glob_imports() {
64 check(
65 "use foo::baz::A",
66 r"
67 use foo::bar::*;
68 ",
69 r"
70 use foo::bar::*;
71 use foo::baz::A;
72 ",
73 ImportGranularity::Crate,
74 );
75 }
76
77 #[test]
insert_not_group()78 fn insert_not_group() {
79 cov_mark::check!(insert_no_grouping_last);
80 check_with_config(
81 "use external_crate2::bar::A",
82 r"
83 use std::bar::B;
84 use external_crate::bar::A;
85 use crate::bar::A;
86 use self::bar::A;
87 use super::bar::A;",
88 r"
89 use std::bar::B;
90 use external_crate::bar::A;
91 use crate::bar::A;
92 use self::bar::A;
93 use super::bar::A;
94 use external_crate2::bar::A;",
95 &InsertUseConfig {
96 granularity: ImportGranularity::Item,
97 enforce_granularity: true,
98 prefix_kind: PrefixKind::Plain,
99 group: false,
100 skip_glob_imports: true,
101 },
102 );
103 }
104
105 #[test]
insert_existing()106 fn insert_existing() {
107 check_crate("std::fs", "use std::fs;", "use std::fs;")
108 }
109
110 #[test]
insert_start()111 fn insert_start() {
112 check_none(
113 "std::bar::AA",
114 r"
115 use std::bar::B;
116 use std::bar::D;
117 use std::bar::F;
118 use std::bar::G;",
119 r"
120 use std::bar::AA;
121 use std::bar::B;
122 use std::bar::D;
123 use std::bar::F;
124 use std::bar::G;",
125 )
126 }
127
128 #[test]
insert_start_indent()129 fn insert_start_indent() {
130 check_none(
131 "std::bar::AA",
132 r"
133 use std::bar::B;
134 use std::bar::C;",
135 r"
136 use std::bar::AA;
137 use std::bar::B;
138 use std::bar::C;",
139 );
140 }
141
142 #[test]
insert_middle()143 fn insert_middle() {
144 cov_mark::check!(insert_group);
145 check_none(
146 "std::bar::EE",
147 r"
148 use std::bar::A;
149 use std::bar::D;
150 use std::bar::F;
151 use std::bar::G;",
152 r"
153 use std::bar::A;
154 use std::bar::D;
155 use std::bar::EE;
156 use std::bar::F;
157 use std::bar::G;",
158 )
159 }
160
161 #[test]
insert_middle_indent()162 fn insert_middle_indent() {
163 check_none(
164 "std::bar::EE",
165 r"
166 use std::bar::A;
167 use std::bar::D;
168 use std::bar::F;
169 use std::bar::G;",
170 r"
171 use std::bar::A;
172 use std::bar::D;
173 use std::bar::EE;
174 use std::bar::F;
175 use std::bar::G;",
176 )
177 }
178
179 #[test]
insert_end()180 fn insert_end() {
181 cov_mark::check!(insert_group_last);
182 check_none(
183 "std::bar::ZZ",
184 r"
185 use std::bar::A;
186 use std::bar::D;
187 use std::bar::F;
188 use std::bar::G;",
189 r"
190 use std::bar::A;
191 use std::bar::D;
192 use std::bar::F;
193 use std::bar::G;
194 use std::bar::ZZ;",
195 )
196 }
197
198 #[test]
insert_end_indent()199 fn insert_end_indent() {
200 check_none(
201 "std::bar::ZZ",
202 r"
203 use std::bar::A;
204 use std::bar::D;
205 use std::bar::F;
206 use std::bar::G;",
207 r"
208 use std::bar::A;
209 use std::bar::D;
210 use std::bar::F;
211 use std::bar::G;
212 use std::bar::ZZ;",
213 )
214 }
215
216 #[test]
insert_middle_nested()217 fn insert_middle_nested() {
218 check_none(
219 "std::bar::EE",
220 r"
221 use std::bar::A;
222 use std::bar::{D, Z}; // example of weird imports due to user
223 use std::bar::F;
224 use std::bar::G;",
225 r"
226 use std::bar::A;
227 use std::bar::EE;
228 use std::bar::{D, Z}; // example of weird imports due to user
229 use std::bar::F;
230 use std::bar::G;",
231 )
232 }
233
234 #[test]
insert_middle_groups()235 fn insert_middle_groups() {
236 check_none(
237 "foo::bar::GG",
238 r"
239 use std::bar::A;
240 use std::bar::D;
241
242 use foo::bar::F;
243 use foo::bar::H;",
244 r"
245 use std::bar::A;
246 use std::bar::D;
247
248 use foo::bar::F;
249 use foo::bar::GG;
250 use foo::bar::H;",
251 )
252 }
253
254 #[test]
insert_first_matching_group()255 fn insert_first_matching_group() {
256 check_none(
257 "foo::bar::GG",
258 r"
259 use foo::bar::A;
260 use foo::bar::D;
261
262 use std;
263
264 use foo::bar::F;
265 use foo::bar::H;",
266 r"
267 use foo::bar::A;
268 use foo::bar::D;
269 use foo::bar::GG;
270
271 use std;
272
273 use foo::bar::F;
274 use foo::bar::H;",
275 )
276 }
277
278 #[test]
insert_missing_group_std()279 fn insert_missing_group_std() {
280 cov_mark::check!(insert_group_new_group);
281 check_none(
282 "std::fmt",
283 r"
284 use foo::bar::A;
285 use foo::bar::D;",
286 r"
287 use std::fmt;
288
289 use foo::bar::A;
290 use foo::bar::D;",
291 )
292 }
293
294 #[test]
insert_missing_group_self()295 fn insert_missing_group_self() {
296 cov_mark::check!(insert_group_no_group);
297 check_none(
298 "self::fmt",
299 r"
300 use foo::bar::A;
301 use foo::bar::D;",
302 r"
303 use foo::bar::A;
304 use foo::bar::D;
305
306 use self::fmt;",
307 )
308 }
309
310 #[test]
insert_no_imports()311 fn insert_no_imports() {
312 check_crate(
313 "foo::bar",
314 "fn main() {}",
315 r"use foo::bar;
316
317 fn main() {}",
318 )
319 }
320
321 #[test]
insert_empty_file()322 fn insert_empty_file() {
323 cov_mark::check_count!(insert_empty_file, 2);
324
325 // Default configuration
326 // empty files will get two trailing newlines
327 // this is due to the test case insert_no_imports above
328 check_crate(
329 "foo::bar",
330 "",
331 r"use foo::bar;
332
333 ",
334 );
335
336 // "not group" configuration
337 check_with_config(
338 "use external_crate2::bar::A",
339 r"",
340 r"use external_crate2::bar::A;
341
342 ",
343 &InsertUseConfig {
344 granularity: ImportGranularity::Item,
345 enforce_granularity: true,
346 prefix_kind: PrefixKind::Plain,
347 group: false,
348 skip_glob_imports: true,
349 },
350 );
351 }
352
353 #[test]
insert_empty_module()354 fn insert_empty_module() {
355 cov_mark::check_count!(insert_empty_module, 2);
356
357 // Default configuration
358 check(
359 "foo::bar",
360 r"
361 mod x {$0}
362 ",
363 r"
364 mod x {
365 use foo::bar;
366 }
367 ",
368 ImportGranularity::Item,
369 );
370
371 // "not group" configuration
372 check_with_config(
373 "foo::bar",
374 r"mod x {$0}",
375 r"mod x {
376 use foo::bar;
377 }",
378 &InsertUseConfig {
379 granularity: ImportGranularity::Item,
380 enforce_granularity: true,
381 prefix_kind: PrefixKind::Plain,
382 group: false,
383 skip_glob_imports: true,
384 },
385 );
386 }
387
388 #[test]
insert_after_inner_attr()389 fn insert_after_inner_attr() {
390 cov_mark::check_count!(insert_empty_inner_attr, 2);
391
392 // Default configuration
393 check_crate(
394 "foo::bar",
395 r"#![allow(unused_imports)]",
396 r"#![allow(unused_imports)]
397
398 use foo::bar;",
399 );
400
401 // "not group" configuration
402 check_with_config(
403 "foo::bar",
404 r"#![allow(unused_imports)]",
405 r"#![allow(unused_imports)]
406
407 use foo::bar;",
408 &InsertUseConfig {
409 granularity: ImportGranularity::Item,
410 enforce_granularity: true,
411 prefix_kind: PrefixKind::Plain,
412 group: false,
413 skip_glob_imports: true,
414 },
415 );
416 }
417
418 #[test]
insert_after_inner_attr2()419 fn insert_after_inner_attr2() {
420 check_crate(
421 "foo::bar",
422 r"#![allow(unused_imports)]
423
424 #![no_std]
425 fn main() {}",
426 r"#![allow(unused_imports)]
427
428 #![no_std]
429
430 use foo::bar;
431 fn main() {}",
432 );
433 }
434
435 #[test]
inserts_after_single_line_inner_comments()436 fn inserts_after_single_line_inner_comments() {
437 check_none(
438 "foo::bar::Baz",
439 "//! Single line inner comments do not allow any code before them.",
440 r#"//! Single line inner comments do not allow any code before them.
441
442 use foo::bar::Baz;"#,
443 );
444 check_none(
445 "foo::bar::Baz",
446 r"mod foo {
447 //! Single line inner comments do not allow any code before them.
448 $0
449 }",
450 r"mod foo {
451 //! Single line inner comments do not allow any code before them.
452
453 use foo::bar::Baz;
454
455 }",
456 );
457 }
458
459 #[test]
inserts_after_single_line_comments()460 fn inserts_after_single_line_comments() {
461 check_none(
462 "foo::bar::Baz",
463 "// Represents a possible license header and/or general module comments",
464 r#"// Represents a possible license header and/or general module comments
465
466 use foo::bar::Baz;"#,
467 );
468 }
469
470 #[test]
inserts_after_shebang()471 fn inserts_after_shebang() {
472 check_none(
473 "foo::bar::Baz",
474 "#!/usr/bin/env rust",
475 r#"#!/usr/bin/env rust
476
477 use foo::bar::Baz;"#,
478 );
479 }
480
481 #[test]
inserts_after_multiple_single_line_comments()482 fn inserts_after_multiple_single_line_comments() {
483 check_none(
484 "foo::bar::Baz",
485 "// Represents a possible license header and/or general module comments
486 // Second single-line comment
487 // Third single-line comment",
488 r#"// Represents a possible license header and/or general module comments
489 // Second single-line comment
490 // Third single-line comment
491
492 use foo::bar::Baz;"#,
493 );
494 }
495
496 #[test]
inserts_before_single_line_item_comments()497 fn inserts_before_single_line_item_comments() {
498 check_none(
499 "foo::bar::Baz",
500 r#"// Represents a comment about a function
501 fn foo() {}"#,
502 r#"use foo::bar::Baz;
503
504 // Represents a comment about a function
505 fn foo() {}"#,
506 );
507 }
508
509 #[test]
inserts_after_single_line_header_comments_and_before_item()510 fn inserts_after_single_line_header_comments_and_before_item() {
511 check_none(
512 "foo::bar::Baz",
513 r#"// Represents a possible license header
514 // Line two of possible license header
515
516 fn foo() {}"#,
517 r#"// Represents a possible license header
518 // Line two of possible license header
519
520 use foo::bar::Baz;
521
522 fn foo() {}"#,
523 );
524 }
525
526 #[test]
inserts_after_multiline_inner_comments()527 fn inserts_after_multiline_inner_comments() {
528 check_none(
529 "foo::bar::Baz",
530 r#"/*! Multiline inner comments do not allow any code before them. */
531
532 /*! Still an inner comment, cannot place any code before. */
533 fn main() {}"#,
534 r#"/*! Multiline inner comments do not allow any code before them. */
535
536 /*! Still an inner comment, cannot place any code before. */
537
538 use foo::bar::Baz;
539 fn main() {}"#,
540 )
541 }
542
543 #[test]
inserts_after_all_inner_items()544 fn inserts_after_all_inner_items() {
545 check_none(
546 "foo::bar::Baz",
547 r#"#![allow(unused_imports)]
548 /*! Multiline line comment 2 */
549
550
551 //! Single line comment 1
552 #![no_std]
553 //! Single line comment 2
554 fn main() {}"#,
555 r#"#![allow(unused_imports)]
556 /*! Multiline line comment 2 */
557
558
559 //! Single line comment 1
560 #![no_std]
561 //! Single line comment 2
562
563 use foo::bar::Baz;
564 fn main() {}"#,
565 )
566 }
567
568 #[test]
merge_groups()569 fn merge_groups() {
570 check_module("std::io", r"use std::fmt;", r"use std::{fmt, io};")
571 }
572
573 #[test]
merge_groups_last()574 fn merge_groups_last() {
575 check_module(
576 "std::io",
577 r"use std::fmt::{Result, Display};",
578 r"use std::fmt::{Result, Display};
579 use std::io;",
580 )
581 }
582
583 #[test]
merge_last_into_self()584 fn merge_last_into_self() {
585 check_module("foo::bar::baz", r"use foo::bar;", r"use foo::bar::{self, baz};");
586 }
587
588 #[test]
merge_groups_full()589 fn merge_groups_full() {
590 check_crate(
591 "std::io",
592 r"use std::fmt::{Result, Display};",
593 r"use std::{fmt::{Result, Display}, io};",
594 )
595 }
596
597 #[test]
merge_groups_long_full()598 fn merge_groups_long_full() {
599 check_crate("std::foo::bar::Baz", r"use std::foo::bar::Qux;", r"use std::foo::bar::{Qux, Baz};")
600 }
601
602 #[test]
merge_groups_long_last()603 fn merge_groups_long_last() {
604 check_module(
605 "std::foo::bar::Baz",
606 r"use std::foo::bar::Qux;",
607 r"use std::foo::bar::{Qux, Baz};",
608 )
609 }
610
611 #[test]
merge_groups_long_full_list()612 fn merge_groups_long_full_list() {
613 check_crate(
614 "std::foo::bar::Baz",
615 r"use std::foo::bar::{Qux, Quux};",
616 r"use std::foo::bar::{Qux, Quux, Baz};",
617 )
618 }
619
620 #[test]
merge_groups_long_last_list()621 fn merge_groups_long_last_list() {
622 check_module(
623 "std::foo::bar::Baz",
624 r"use std::foo::bar::{Qux, Quux};",
625 r"use std::foo::bar::{Qux, Quux, Baz};",
626 )
627 }
628
629 #[test]
merge_groups_long_full_nested()630 fn merge_groups_long_full_nested() {
631 check_crate(
632 "std::foo::bar::Baz",
633 r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
634 r"use std::foo::bar::{Qux, quux::{Fez, Fizz}, Baz};",
635 )
636 }
637
638 #[test]
merge_groups_long_last_nested()639 fn merge_groups_long_last_nested() {
640 check_module(
641 "std::foo::bar::Baz",
642 r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
643 r"use std::foo::bar::Baz;
644 use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
645 )
646 }
647
648 #[test]
merge_groups_full_nested_deep()649 fn merge_groups_full_nested_deep() {
650 check_crate(
651 "std::foo::bar::quux::Baz",
652 r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
653 r"use std::foo::bar::{Qux, quux::{Fez, Fizz, Baz}};",
654 )
655 }
656
657 #[test]
merge_groups_full_nested_long()658 fn merge_groups_full_nested_long() {
659 check_crate(
660 "std::foo::bar::Baz",
661 r"use std::{foo::bar::Qux};",
662 r"use std::{foo::bar::{Qux, Baz}};",
663 );
664 }
665
666 #[test]
merge_groups_last_nested_long()667 fn merge_groups_last_nested_long() {
668 check_crate(
669 "std::foo::bar::Baz",
670 r"use std::{foo::bar::Qux};",
671 r"use std::{foo::bar::{Qux, Baz}};",
672 );
673 }
674
675 #[test]
merge_groups_skip_pub()676 fn merge_groups_skip_pub() {
677 check_crate(
678 "std::io",
679 r"pub use std::fmt::{Result, Display};",
680 r"pub use std::fmt::{Result, Display};
681 use std::io;",
682 )
683 }
684
685 #[test]
merge_groups_skip_pub_crate()686 fn merge_groups_skip_pub_crate() {
687 check_crate(
688 "std::io",
689 r"pub(crate) use std::fmt::{Result, Display};",
690 r"pub(crate) use std::fmt::{Result, Display};
691 use std::io;",
692 )
693 }
694
695 #[test]
merge_groups_skip_attributed()696 fn merge_groups_skip_attributed() {
697 check_crate(
698 "std::io",
699 r#"
700 #[cfg(feature = "gated")] use std::fmt::{Result, Display};
701 "#,
702 r#"
703 #[cfg(feature = "gated")] use std::fmt::{Result, Display};
704 use std::io;
705 "#,
706 )
707 }
708
709 #[test]
split_out_merge()710 fn split_out_merge() {
711 // FIXME: This is suboptimal, we want to get `use std::fmt::{self, Result}`
712 // instead.
713 check_module(
714 "std::fmt::Result",
715 r"use std::{fmt, io};",
716 r"use std::fmt::Result;
717 use std::{fmt, io};",
718 )
719 }
720
721 #[test]
merge_into_module_import()722 fn merge_into_module_import() {
723 check_crate("std::fmt::Result", r"use std::{fmt, io};", r"use std::{fmt::{self, Result}, io};")
724 }
725
726 #[test]
merge_groups_self()727 fn merge_groups_self() {
728 check_crate("std::fmt::Debug", r"use std::fmt;", r"use std::fmt::{self, Debug};")
729 }
730
731 #[test]
merge_mod_into_glob()732 fn merge_mod_into_glob() {
733 check_with_config(
734 "token::TokenKind",
735 r"use token::TokenKind::*;",
736 r"use token::TokenKind::{*, self};",
737 &InsertUseConfig {
738 granularity: ImportGranularity::Crate,
739 enforce_granularity: true,
740 prefix_kind: PrefixKind::Plain,
741 group: false,
742 skip_glob_imports: false,
743 },
744 )
745 // FIXME: have it emit `use token::TokenKind::{self, *}`?
746 }
747
748 #[test]
merge_self_glob()749 fn merge_self_glob() {
750 check_with_config(
751 "self",
752 r"use self::*;",
753 r"use self::{*, self};",
754 &InsertUseConfig {
755 granularity: ImportGranularity::Crate,
756 enforce_granularity: true,
757 prefix_kind: PrefixKind::Plain,
758 group: false,
759 skip_glob_imports: false,
760 },
761 )
762 // FIXME: have it emit `use {self, *}`?
763 }
764
765 #[test]
merge_glob()766 fn merge_glob() {
767 check_crate(
768 "syntax::SyntaxKind",
769 r"
770 use syntax::{SyntaxKind::*};",
771 r"
772 use syntax::{SyntaxKind::{*, self}};",
773 )
774 }
775
776 #[test]
merge_glob_nested()777 fn merge_glob_nested() {
778 check_crate(
779 "foo::bar::quux::Fez",
780 r"use foo::bar::{Baz, quux::*};",
781 r"use foo::bar::{Baz, quux::{*, Fez}};",
782 )
783 }
784
785 #[test]
merge_nested_considers_first_segments()786 fn merge_nested_considers_first_segments() {
787 check_crate(
788 "hir_ty::display::write_bounds_like_dyn_trait",
789 r"use hir_ty::{autoderef, display::{HirDisplayError, HirFormatter}, method_resolution};",
790 r"use hir_ty::{autoderef, display::{HirDisplayError, HirFormatter, write_bounds_like_dyn_trait}, method_resolution};",
791 );
792 }
793
794 #[test]
skip_merge_last_too_long()795 fn skip_merge_last_too_long() {
796 check_module(
797 "foo::bar",
798 r"use foo::bar::baz::Qux;",
799 r"use foo::bar;
800 use foo::bar::baz::Qux;",
801 );
802 }
803
804 #[test]
skip_merge_last_too_long2()805 fn skip_merge_last_too_long2() {
806 check_module(
807 "foo::bar::baz::Qux",
808 r"use foo::bar;",
809 r"use foo::bar;
810 use foo::bar::baz::Qux;",
811 );
812 }
813
814 #[test]
insert_short_before_long()815 fn insert_short_before_long() {
816 check_none(
817 "foo::bar",
818 r"use foo::bar::baz::Qux;",
819 r"use foo::bar;
820 use foo::bar::baz::Qux;",
821 );
822 }
823
824 #[test]
merge_last_fail()825 fn merge_last_fail() {
826 check_merge_only_fail(
827 r"use foo::bar::{baz::{Qux, Fez}};",
828 r"use foo::bar::{baaz::{Quux, Feez}};",
829 MergeBehavior::Module,
830 );
831 }
832
833 #[test]
merge_last_fail1()834 fn merge_last_fail1() {
835 check_merge_only_fail(
836 r"use foo::bar::{baz::{Qux, Fez}};",
837 r"use foo::bar::baaz::{Quux, Feez};",
838 MergeBehavior::Module,
839 );
840 }
841
842 #[test]
merge_last_fail2()843 fn merge_last_fail2() {
844 check_merge_only_fail(
845 r"use foo::bar::baz::{Qux, Fez};",
846 r"use foo::bar::{baaz::{Quux, Feez}};",
847 MergeBehavior::Module,
848 );
849 }
850
851 #[test]
merge_last_fail3()852 fn merge_last_fail3() {
853 check_merge_only_fail(
854 r"use foo::bar::baz::{Qux, Fez};",
855 r"use foo::bar::baaz::{Quux, Feez};",
856 MergeBehavior::Module,
857 );
858 }
859
860 #[test]
guess_empty()861 fn guess_empty() {
862 check_guess("", ImportGranularityGuess::Unknown);
863 }
864
865 #[test]
guess_single()866 fn guess_single() {
867 check_guess(r"use foo::{baz::{qux, quux}, bar};", ImportGranularityGuess::Crate);
868 check_guess(r"use foo::bar;", ImportGranularityGuess::Unknown);
869 check_guess(r"use foo::bar::{baz, qux};", ImportGranularityGuess::CrateOrModule);
870 }
871
872 #[test]
guess_unknown()873 fn guess_unknown() {
874 check_guess(
875 r"
876 use foo::bar::baz;
877 use oof::rab::xuq;
878 ",
879 ImportGranularityGuess::Unknown,
880 );
881 }
882
883 #[test]
guess_item()884 fn guess_item() {
885 check_guess(
886 r"
887 use foo::bar::baz;
888 use foo::bar::qux;
889 ",
890 ImportGranularityGuess::Item,
891 );
892 }
893
894 #[test]
guess_module_or_item()895 fn guess_module_or_item() {
896 check_guess(
897 r"
898 use foo::bar::Bar;
899 use foo::qux;
900 ",
901 ImportGranularityGuess::ModuleOrItem,
902 );
903 check_guess(
904 r"
905 use foo::bar::Bar;
906 use foo::bar;
907 ",
908 ImportGranularityGuess::ModuleOrItem,
909 );
910 }
911
912 #[test]
guess_module()913 fn guess_module() {
914 check_guess(
915 r"
916 use foo::bar::baz;
917 use foo::bar::{qux, quux};
918 ",
919 ImportGranularityGuess::Module,
920 );
921 // this is a rather odd case, technically this file isn't following any style properly.
922 check_guess(
923 r"
924 use foo::bar::baz;
925 use foo::{baz::{qux, quux}, bar};
926 ",
927 ImportGranularityGuess::Module,
928 );
929 check_guess(
930 r"
931 use foo::bar::Bar;
932 use foo::baz::Baz;
933 use foo::{Foo, Qux};
934 ",
935 ImportGranularityGuess::Module,
936 );
937 }
938
939 #[test]
guess_crate_or_module()940 fn guess_crate_or_module() {
941 check_guess(
942 r"
943 use foo::bar::baz;
944 use oof::bar::{qux, quux};
945 ",
946 ImportGranularityGuess::CrateOrModule,
947 );
948 }
949
950 #[test]
guess_crate()951 fn guess_crate() {
952 check_guess(
953 r"
954 use frob::bar::baz;
955 use foo::{baz::{qux, quux}, bar};
956 ",
957 ImportGranularityGuess::Crate,
958 );
959 }
960
961 #[test]
guess_skips_differing_vis()962 fn guess_skips_differing_vis() {
963 check_guess(
964 r"
965 use foo::bar::baz;
966 pub use foo::bar::qux;
967 ",
968 ImportGranularityGuess::Unknown,
969 );
970 }
971
972 #[test]
guess_skips_differing_attrs()973 fn guess_skips_differing_attrs() {
974 check_guess(
975 r"
976 pub use foo::bar::baz;
977 #[doc(hidden)]
978 pub use foo::bar::qux;
979 ",
980 ImportGranularityGuess::Unknown,
981 );
982 }
983
984 #[test]
guess_grouping_matters()985 fn guess_grouping_matters() {
986 check_guess(
987 r"
988 use foo::bar::baz;
989 use oof::bar::baz;
990 use foo::bar::qux;
991 ",
992 ImportGranularityGuess::Unknown,
993 );
994 }
995
check_with_config( path: &str, ra_fixture_before: &str, ra_fixture_after: &str, config: &InsertUseConfig, )996 fn check_with_config(
997 path: &str,
998 ra_fixture_before: &str,
999 ra_fixture_after: &str,
1000 config: &InsertUseConfig,
1001 ) {
1002 let (db, file_id, pos) = if ra_fixture_before.contains(CURSOR_MARKER) {
1003 let (db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture_before);
1004 (db, file_id, Some(range_or_offset))
1005 } else {
1006 let (db, file_id) = RootDatabase::with_single_file(ra_fixture_before);
1007 (db, file_id, None)
1008 };
1009 let sema = &Semantics::new(&db);
1010 let source_file = sema.parse(file_id);
1011 let syntax = source_file.syntax().clone_for_update();
1012 let file = pos
1013 .and_then(|pos| syntax.token_at_offset(pos.expect_offset()).next()?.parent())
1014 .and_then(|it| ImportScope::find_insert_use_container(&it, sema))
1015 .or_else(|| ImportScope::from(syntax))
1016 .unwrap();
1017 let path = ast::SourceFile::parse(&format!("use {path};"))
1018 .tree()
1019 .syntax()
1020 .descendants()
1021 .find_map(ast::Path::cast)
1022 .unwrap();
1023
1024 insert_use(&file, path, config);
1025 let result = file.as_syntax_node().ancestors().last().unwrap().to_string();
1026 assert_eq_text!(&trim_indent(ra_fixture_after), &result);
1027 }
1028
check( path: &str, ra_fixture_before: &str, ra_fixture_after: &str, granularity: ImportGranularity, )1029 fn check(
1030 path: &str,
1031 ra_fixture_before: &str,
1032 ra_fixture_after: &str,
1033 granularity: ImportGranularity,
1034 ) {
1035 check_with_config(
1036 path,
1037 ra_fixture_before,
1038 ra_fixture_after,
1039 &InsertUseConfig {
1040 granularity,
1041 enforce_granularity: true,
1042 prefix_kind: PrefixKind::Plain,
1043 group: true,
1044 skip_glob_imports: true,
1045 },
1046 )
1047 }
1048
check_crate(path: &str, ra_fixture_before: &str, ra_fixture_after: &str)1049 fn check_crate(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
1050 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Crate)
1051 }
1052
check_module(path: &str, ra_fixture_before: &str, ra_fixture_after: &str)1053 fn check_module(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
1054 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Module)
1055 }
1056
check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str)1057 fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
1058 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Item)
1059 }
1060
check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior)1061 fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior) {
1062 let use0 = ast::SourceFile::parse(ra_fixture0)
1063 .tree()
1064 .syntax()
1065 .descendants()
1066 .find_map(ast::Use::cast)
1067 .unwrap();
1068
1069 let use1 = ast::SourceFile::parse(ra_fixture1)
1070 .tree()
1071 .syntax()
1072 .descendants()
1073 .find_map(ast::Use::cast)
1074 .unwrap();
1075
1076 let result = try_merge_imports(&use0, &use1, mb);
1077 assert_eq!(result.map(|u| u.to_string()), None);
1078 }
1079
check_guess(ra_fixture: &str, expected: ImportGranularityGuess)1080 fn check_guess(ra_fixture: &str, expected: ImportGranularityGuess) {
1081 let syntax = ast::SourceFile::parse(ra_fixture).tree().syntax().clone();
1082 let file = ImportScope::from(syntax).unwrap();
1083 assert_eq!(super::guess_granularity_from_scope(&file), expected);
1084 }
1085