4 use test_utils::{assert_eq_text, extract_range_or_offset, CURSOR_MARKER};
7 fn respects_cfg_attr_fn() {
20 ImportGranularity::Crate,
25 fn respects_cfg_attr_const() {
30 const FOO: Bar = {$0};
38 ImportGranularity::Crate,
43 fn insert_skips_lone_glob_imports() {
53 ImportGranularity::Crate,
58 fn insert_not_group() {
59 cov_mark::check!(insert_no_grouping_last);
61 "use external_crate2::bar::A",
64 use external_crate::bar::A;
70 use external_crate::bar::A;
74 use external_crate2::bar::A;",
76 granularity: ImportGranularity::Item,
77 enforce_granularity: true,
78 prefix_kind: PrefixKind::Plain,
80 skip_glob_imports: true,
86 fn insert_not_group_empty() {
87 cov_mark::check!(insert_no_grouping_last2);
89 "use external_crate2::bar::A",
91 r"use external_crate2::bar::A;
95 granularity: ImportGranularity::Item,
96 enforce_granularity: true,
97 prefix_kind: PrefixKind::Plain,
99 skip_glob_imports: true,
105 fn insert_existing() {
106 check_crate("std::fs", "use std::fs;", "use std::fs;")
128 fn insert_start_indent() {
143 cov_mark::check!(insert_group);
161 fn insert_middle_indent() {
180 cov_mark::check!(insert_group_last);
198 fn insert_end_indent() {
216 fn insert_middle_nested() {
221 use std::bar::{D, Z}; // example of weird imports due to user
227 use std::bar::{D, Z}; // example of weird imports due to user
234 fn insert_middle_groups() {
254 fn insert_first_matching_group() {
278 fn insert_missing_group_std() {
279 cov_mark::check!(insert_group_new_group);
294 fn insert_missing_group_self() {
295 cov_mark::check!(insert_group_no_group);
310 fn insert_no_imports() {
321 fn insert_empty_file() {
322 cov_mark::check!(insert_group_empty_file);
323 // empty files will get two trailing newlines
324 // this is due to the test case insert_no_imports above
335 fn insert_empty_module() {
336 cov_mark::check!(insert_group_empty_module);
347 ImportGranularity::Item,
352 fn insert_after_inner_attr() {
353 cov_mark::check!(insert_group_empty_inner_attr);
356 r"#![allow(unused_imports)]",
357 r"#![allow(unused_imports)]
364 fn insert_after_inner_attr2() {
367 r"#![allow(unused_imports)]
371 r"#![allow(unused_imports)]
381 fn inserts_after_single_line_inner_comments() {
384 "//! Single line inner comments do not allow any code before them.",
385 r#"//! Single line inner comments do not allow any code before them.
387 use foo::bar::Baz;"#,
392 fn inserts_after_multiline_inner_comments() {
395 r#"/*! Multiline inner comments do not allow any code before them. */
397 /*! Still an inner comment, cannot place any code before. */
399 r#"/*! Multiline inner comments do not allow any code before them. */
401 /*! Still an inner comment, cannot place any code before. */
409 fn inserts_after_all_inner_items() {
412 r#"#![allow(unused_imports)]
413 /*! Multiline line comment 2 */
416 //! Single line comment 1
418 //! Single line comment 2
420 r#"#![allow(unused_imports)]
421 /*! Multiline line comment 2 */
424 //! Single line comment 1
426 //! Single line comment 2
435 check_module("std::io", r"use std::fmt;", r"use std::{fmt, io};")
439 fn merge_groups_last() {
442 r"use std::fmt::{Result, Display};",
443 r"use std::fmt::{Result, Display};
449 fn merge_last_into_self() {
450 check_module("foo::bar::baz", r"use foo::bar;", r"use foo::bar::{self, baz};");
454 fn merge_groups_full() {
457 r"use std::fmt::{Result, Display};",
458 r"use std::{fmt::{Result, Display}, io};",
463 fn merge_groups_long_full() {
464 check_crate("std::foo::bar::Baz", r"use std::foo::bar::Qux;", r"use std::foo::bar::{Baz, Qux};")
468 fn merge_groups_long_last() {
470 "std::foo::bar::Baz",
471 r"use std::foo::bar::Qux;",
472 r"use std::foo::bar::{Baz, Qux};",
477 fn merge_groups_long_full_list() {
479 "std::foo::bar::Baz",
480 r"use std::foo::bar::{Qux, Quux};",
481 r"use std::foo::bar::{Baz, Quux, Qux};",
486 fn merge_groups_long_last_list() {
488 "std::foo::bar::Baz",
489 r"use std::foo::bar::{Qux, Quux};",
490 r"use std::foo::bar::{Baz, Quux, Qux};",
495 fn merge_groups_long_full_nested() {
497 "std::foo::bar::Baz",
498 r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
499 r"use std::foo::bar::{Baz, Qux, quux::{Fez, Fizz}};",
504 fn merge_groups_long_last_nested() {
506 "std::foo::bar::Baz",
507 r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
508 r"use std::foo::bar::Baz;
509 use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
514 fn merge_groups_full_nested_deep() {
516 "std::foo::bar::quux::Baz",
517 r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
518 r"use std::foo::bar::{Qux, quux::{Baz, Fez, Fizz}};",
523 fn merge_groups_full_nested_long() {
525 "std::foo::bar::Baz",
526 r"use std::{foo::bar::Qux};",
527 r"use std::{foo::bar::{Baz, Qux}};",
532 fn merge_groups_last_nested_long() {
534 "std::foo::bar::Baz",
535 r"use std::{foo::bar::Qux};",
536 r"use std::{foo::bar::{Baz, Qux}};",
541 fn merge_groups_skip_pub() {
544 r"pub use std::fmt::{Result, Display};",
545 r"pub use std::fmt::{Result, Display};
551 fn merge_groups_skip_pub_crate() {
554 r"pub(crate) use std::fmt::{Result, Display};",
555 r"pub(crate) use std::fmt::{Result, Display};
561 fn merge_groups_skip_attributed() {
565 #[cfg(feature = "gated")] use std::fmt::{Result, Display};
568 #[cfg(feature = "gated")] use std::fmt::{Result, Display};
575 fn split_out_merge() {
576 // FIXME: This is suboptimal, we want to get `use std::fmt::{self, Result}`
580 r"use std::{fmt, io};",
581 r"use std::fmt::Result;
582 use std::{fmt, io};",
587 fn merge_into_module_import() {
588 check_crate("std::fmt::Result", r"use std::{fmt, io};", r"use std::{fmt::{self, Result}, io};")
592 fn merge_groups_self() {
593 check_crate("std::fmt::Debug", r"use std::fmt;", r"use std::fmt::{self, Debug};")
597 fn merge_mod_into_glob() {
600 r"use token::TokenKind::*;",
601 r"use token::TokenKind::{*, self};",
603 granularity: ImportGranularity::Crate,
604 enforce_granularity: true,
605 prefix_kind: PrefixKind::Plain,
607 skip_glob_imports: false,
610 // FIXME: have it emit `use token::TokenKind::{self, *}`?
614 fn merge_self_glob() {
618 r"use self::{*, self};",
620 granularity: ImportGranularity::Crate,
621 enforce_granularity: true,
622 prefix_kind: PrefixKind::Plain,
624 skip_glob_imports: false,
627 // FIXME: have it emit `use {self, *}`?
631 fn merge_glob_nested() {
633 "foo::bar::quux::Fez",
634 r"use foo::bar::{Baz, quux::*};",
635 r"use foo::bar::{Baz, quux::{self::*, Fez}};",
640 fn merge_nested_considers_first_segments() {
642 "hir_ty::display::write_bounds_like_dyn_trait",
643 r"use hir_ty::{autoderef, display::{HirDisplayError, HirFormatter}, method_resolution};",
644 r"use hir_ty::{autoderef, display::{HirDisplayError, HirFormatter, write_bounds_like_dyn_trait}, method_resolution};",
649 fn skip_merge_last_too_long() {
652 r"use foo::bar::baz::Qux;",
654 use foo::bar::baz::Qux;",
659 fn skip_merge_last_too_long2() {
661 "foo::bar::baz::Qux",
664 use foo::bar::baz::Qux;",
669 fn insert_short_before_long() {
672 r"use foo::bar::baz::Qux;",
674 use foo::bar::baz::Qux;",
679 fn merge_last_fail() {
680 check_merge_only_fail(
681 r"use foo::bar::{baz::{Qux, Fez}};",
682 r"use foo::bar::{baaz::{Quux, Feez}};",
683 MergeBehavior::Module,
688 fn merge_last_fail1() {
689 check_merge_only_fail(
690 r"use foo::bar::{baz::{Qux, Fez}};",
691 r"use foo::bar::baaz::{Quux, Feez};",
692 MergeBehavior::Module,
697 fn merge_last_fail2() {
698 check_merge_only_fail(
699 r"use foo::bar::baz::{Qux, Fez};",
700 r"use foo::bar::{baaz::{Quux, Feez}};",
701 MergeBehavior::Module,
706 fn merge_last_fail3() {
707 check_merge_only_fail(
708 r"use foo::bar::baz::{Qux, Fez};",
709 r"use foo::bar::baaz::{Quux, Feez};",
710 MergeBehavior::Module,
716 check_guess("", ImportGranularityGuess::Unknown);
721 check_guess(r"use foo::{baz::{qux, quux}, bar};", ImportGranularityGuess::Crate);
722 check_guess(r"use foo::bar;", ImportGranularityGuess::Unknown);
723 check_guess(r"use foo::bar::{baz, qux};", ImportGranularityGuess::CrateOrModule);
733 ImportGranularityGuess::Unknown,
744 ImportGranularityGuess::Item,
751 ImportGranularityGuess::Item,
760 use foo::bar::{qux, quux};
762 ImportGranularityGuess::Module,
764 // this is a rather odd case, technically this file isn't following any style properly.
768 use foo::{baz::{qux, quux}, bar};
770 ImportGranularityGuess::Module,
778 ImportGranularityGuess::Module,
783 fn guess_crate_or_module() {
787 use oof::bar::{qux, quux};
789 ImportGranularityGuess::CrateOrModule,
798 use foo::{baz::{qux, quux}, bar};
800 ImportGranularityGuess::Crate,
805 fn guess_skips_differing_vis() {
809 pub use foo::bar::qux;
811 ImportGranularityGuess::Unknown,
816 fn guess_skips_differing_attrs() {
819 pub use foo::bar::baz;
821 pub use foo::bar::qux;
823 ImportGranularityGuess::Unknown,
828 fn guess_grouping_matters() {
835 ImportGranularityGuess::Unknown,
839 fn check_with_config(
841 ra_fixture_before: &str,
842 ra_fixture_after: &str,
843 config: &InsertUseConfig,
845 let (text, pos) = if ra_fixture_before.contains(CURSOR_MARKER) {
846 let (range_or_offset, text) = extract_range_or_offset(ra_fixture_before);
847 (text, Some(range_or_offset))
849 (ra_fixture_before.to_owned(), None)
851 let syntax = ast::SourceFile::parse(&text).tree().syntax().clone_for_update();
853 .and_then(|pos| syntax.token_at_offset(pos.expect_offset()).next()?.parent())
854 .and_then(|it| super::ImportScope::find_insert_use_container(&it))
855 .or_else(|| super::ImportScope::from(syntax))
857 let path = ast::SourceFile::parse(&format!("use {};", path))
861 .find_map(ast::Path::cast)
864 insert_use(&file, path, config);
865 let result = file.as_syntax_node().ancestors().last().unwrap().to_string();
866 assert_eq_text!(ra_fixture_after, &result);
871 ra_fixture_before: &str,
872 ra_fixture_after: &str,
873 granularity: ImportGranularity,
881 enforce_granularity: true,
882 prefix_kind: PrefixKind::Plain,
884 skip_glob_imports: true,
889 fn check_crate(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
890 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Crate)
893 fn check_module(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
894 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Module)
897 fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
898 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Item)
901 fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior) {
902 let use0 = ast::SourceFile::parse(ra_fixture0)
906 .find_map(ast::Use::cast)
909 let use1 = ast::SourceFile::parse(ra_fixture1)
913 .find_map(ast::Use::cast)
916 let result = try_merge_imports(&use0, &use1, mb);
917 assert_eq!(result.map(|u| u.to_string()), None);
920 fn check_guess(ra_fixture: &str, expected: ImportGranularityGuess) {
921 let syntax = ast::SourceFile::parse(ra_fixture).tree().syntax().clone();
922 let file = super::ImportScope::from(syntax).unwrap();
923 assert_eq!(file.guess_granularity_from_scope(), expected);