]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs
Rollup merge of #102592 - WaffleLapkin:less_lifetimes, r=cjgillot
[rust.git] / src / tools / rust-analyzer / crates / ide-db / src / imports / insert_use / tests.rs
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]
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]
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]
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]
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]
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]
106 fn insert_existing() {
107     check_crate("std::fs", "use std::fs;", "use std::fs;")
108 }
109
110 #[test]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
569 fn merge_groups() {
570     check_module("std::io", r"use std::fmt;", r"use std::{fmt, io};")
571 }
572
573 #[test]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
861 fn guess_empty() {
862     check_guess("", ImportGranularityGuess::Unknown);
863 }
864
865 #[test]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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
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
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
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
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
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
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
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 }