diff options
Diffstat (limited to 'crates/ide_db')
-rw-r--r-- | crates/ide_db/src/helpers/insert_use.rs | 17 | ||||
-rw-r--r-- | crates/ide_db/src/helpers/insert_use/tests.rs | 38 |
2 files changed, 48 insertions, 7 deletions
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs index fd4035198..f52aee344 100644 --- a/crates/ide_db/src/helpers/insert_use.rs +++ b/crates/ide_db/src/helpers/insert_use.rs | |||
@@ -19,6 +19,7 @@ use test_utils::mark; | |||
19 | pub struct InsertUseConfig { | 19 | pub struct InsertUseConfig { |
20 | pub merge: Option<MergeBehavior>, | 20 | pub merge: Option<MergeBehavior>, |
21 | pub prefix_kind: hir::PrefixKind, | 21 | pub prefix_kind: hir::PrefixKind, |
22 | pub group: bool, | ||
22 | } | 23 | } |
23 | 24 | ||
24 | #[derive(Debug, Clone)] | 25 | #[derive(Debug, Clone)] |
@@ -99,13 +100,13 @@ fn is_inner_comment(token: SyntaxToken) -> bool { | |||
99 | pub fn insert_use<'a>( | 100 | pub fn insert_use<'a>( |
100 | scope: &ImportScope, | 101 | scope: &ImportScope, |
101 | path: ast::Path, | 102 | path: ast::Path, |
102 | merge: Option<MergeBehavior>, | 103 | cfg: InsertUseConfig, |
103 | ) -> SyntaxRewriter<'a> { | 104 | ) -> SyntaxRewriter<'a> { |
104 | let _p = profile::span("insert_use"); | 105 | let _p = profile::span("insert_use"); |
105 | let mut rewriter = SyntaxRewriter::default(); | 106 | let mut rewriter = SyntaxRewriter::default(); |
106 | let use_item = make::use_(None, make::use_tree(path.clone(), None, None, false)); | 107 | let use_item = make::use_(None, make::use_tree(path.clone(), None, None, false)); |
107 | // merge into existing imports if possible | 108 | // merge into existing imports if possible |
108 | if let Some(mb) = merge { | 109 | if let Some(mb) = cfg.merge { |
109 | for existing_use in scope.as_syntax_node().children().filter_map(ast::Use::cast) { | 110 | for existing_use in scope.as_syntax_node().children().filter_map(ast::Use::cast) { |
110 | if let Some(merged) = try_merge_imports(&existing_use, &use_item, mb) { | 111 | if let Some(merged) = try_merge_imports(&existing_use, &use_item, mb) { |
111 | rewriter.replace(existing_use.syntax(), merged.syntax()); | 112 | rewriter.replace(existing_use.syntax(), merged.syntax()); |
@@ -116,7 +117,7 @@ pub fn insert_use<'a>( | |||
116 | 117 | ||
117 | // either we weren't allowed to merge or there is no import that fits the merge conditions | 118 | // either we weren't allowed to merge or there is no import that fits the merge conditions |
118 | // so look for the place we have to insert to | 119 | // so look for the place we have to insert to |
119 | let (insert_position, add_blank) = find_insert_position(scope, path); | 120 | let (insert_position, add_blank) = find_insert_position(scope, path, cfg.group); |
120 | 121 | ||
121 | let indent = if let ident_level @ 1..=usize::MAX = scope.indent_level().0 as usize { | 122 | let indent = if let ident_level @ 1..=usize::MAX = scope.indent_level().0 as usize { |
122 | Some(make::tokens::whitespace(&" ".repeat(4 * ident_level)).into()) | 123 | Some(make::tokens::whitespace(&" ".repeat(4 * ident_level)).into()) |
@@ -538,6 +539,7 @@ impl AddBlankLine { | |||
538 | fn find_insert_position( | 539 | fn find_insert_position( |
539 | scope: &ImportScope, | 540 | scope: &ImportScope, |
540 | insert_path: ast::Path, | 541 | insert_path: ast::Path, |
542 | group_imports: bool, | ||
541 | ) -> (InsertPosition<SyntaxElement>, AddBlankLine) { | 543 | ) -> (InsertPosition<SyntaxElement>, AddBlankLine) { |
542 | let group = ImportGroup::new(&insert_path); | 544 | let group = ImportGroup::new(&insert_path); |
543 | let path_node_iter = scope | 545 | let path_node_iter = scope |
@@ -550,6 +552,14 @@ fn find_insert_position( | |||
550 | let has_tl = tree.use_tree_list().is_some(); | 552 | let has_tl = tree.use_tree_list().is_some(); |
551 | Some((path, has_tl, node)) | 553 | Some((path, has_tl, node)) |
552 | }); | 554 | }); |
555 | |||
556 | if !group_imports { | ||
557 | if let Some((_, _, node)) = path_node_iter.last() { | ||
558 | return (InsertPosition::After(node.into()), AddBlankLine::Before); | ||
559 | } | ||
560 | return (InsertPosition::First, AddBlankLine::AfterTwice); | ||
561 | } | ||
562 | |||
553 | // Iterator that discards anything thats not in the required grouping | 563 | // Iterator that discards anything thats not in the required grouping |
554 | // This implementation allows the user to rearrange their import groups as this only takes the first group that fits | 564 | // This implementation allows the user to rearrange their import groups as this only takes the first group that fits |
555 | let group_iter = path_node_iter | 565 | let group_iter = path_node_iter |
@@ -565,6 +575,7 @@ fn find_insert_position( | |||
565 | use_tree_path_cmp(&insert_path, false, path, has_tl) != Ordering::Greater | 575 | use_tree_path_cmp(&insert_path, false, path, has_tl) != Ordering::Greater |
566 | }, | 576 | }, |
567 | ); | 577 | ); |
578 | |||
568 | match post_insert { | 579 | match post_insert { |
569 | // insert our import before that element | 580 | // insert our import before that element |
570 | Some((.., node)) => (InsertPosition::Before(node.into()), AddBlankLine::After), | 581 | Some((.., node)) => (InsertPosition::Before(node.into()), AddBlankLine::After), |
diff --git a/crates/ide_db/src/helpers/insert_use/tests.rs b/crates/ide_db/src/helpers/insert_use/tests.rs index 4bbe66f1f..67d0d6fb6 100644 --- a/crates/ide_db/src/helpers/insert_use/tests.rs +++ b/crates/ide_db/src/helpers/insert_use/tests.rs | |||
@@ -1,8 +1,32 @@ | |||
1 | use super::*; | 1 | use super::*; |
2 | 2 | ||
3 | use hir::PrefixKind; | ||
3 | use test_utils::assert_eq_text; | 4 | use test_utils::assert_eq_text; |
4 | 5 | ||
5 | #[test] | 6 | #[test] |
7 | fn insert_not_group() { | ||
8 | check( | ||
9 | "use external_crate2::bar::A", | ||
10 | r" | ||
11 | use std::bar::B; | ||
12 | use external_crate::bar::A; | ||
13 | use crate::bar::A; | ||
14 | use self::bar::A; | ||
15 | use super::bar::A;", | ||
16 | r" | ||
17 | use std::bar::B; | ||
18 | use external_crate::bar::A; | ||
19 | use crate::bar::A; | ||
20 | use self::bar::A; | ||
21 | use super::bar::A; | ||
22 | use external_crate2::bar::A;", | ||
23 | None, | ||
24 | false, | ||
25 | false, | ||
26 | ); | ||
27 | } | ||
28 | |||
29 | #[test] | ||
6 | fn insert_existing() { | 30 | fn insert_existing() { |
7 | check_full("std::fs", "use std::fs;", "use std::fs;") | 31 | check_full("std::fs", "use std::fs;", "use std::fs;") |
8 | } | 32 | } |
@@ -240,6 +264,7 @@ fn insert_empty_module() { | |||
240 | }", | 264 | }", |
241 | None, | 265 | None, |
242 | true, | 266 | true, |
267 | true, | ||
243 | ) | 268 | ) |
244 | } | 269 | } |
245 | 270 | ||
@@ -584,6 +609,7 @@ fn check( | |||
584 | ra_fixture_after: &str, | 609 | ra_fixture_after: &str, |
585 | mb: Option<MergeBehavior>, | 610 | mb: Option<MergeBehavior>, |
586 | module: bool, | 611 | module: bool, |
612 | group: bool, | ||
587 | ) { | 613 | ) { |
588 | let mut syntax = ast::SourceFile::parse(ra_fixture_before).tree().syntax().clone(); | 614 | let mut syntax = ast::SourceFile::parse(ra_fixture_before).tree().syntax().clone(); |
589 | if module { | 615 | if module { |
@@ -597,21 +623,25 @@ fn check( | |||
597 | .find_map(ast::Path::cast) | 623 | .find_map(ast::Path::cast) |
598 | .unwrap(); | 624 | .unwrap(); |
599 | 625 | ||
600 | let rewriter = insert_use(&file, path, mb); | 626 | let rewriter = insert_use( |
627 | &file, | ||
628 | path, | ||
629 | InsertUseConfig { merge: mb, prefix_kind: PrefixKind::Plain, group }, | ||
630 | ); | ||
601 | let result = rewriter.rewrite(file.as_syntax_node()).to_string(); | 631 | let result = rewriter.rewrite(file.as_syntax_node()).to_string(); |
602 | assert_eq_text!(ra_fixture_after, &result); | 632 | assert_eq_text!(ra_fixture_after, &result); |
603 | } | 633 | } |
604 | 634 | ||
605 | fn check_full(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { | 635 | fn check_full(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { |
606 | check(path, ra_fixture_before, ra_fixture_after, Some(MergeBehavior::Full), false) | 636 | check(path, ra_fixture_before, ra_fixture_after, Some(MergeBehavior::Full), false, true) |
607 | } | 637 | } |
608 | 638 | ||
609 | fn check_last(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { | 639 | fn check_last(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { |
610 | check(path, ra_fixture_before, ra_fixture_after, Some(MergeBehavior::Last), false) | 640 | check(path, ra_fixture_before, ra_fixture_after, Some(MergeBehavior::Last), false, true) |
611 | } | 641 | } |
612 | 642 | ||
613 | fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { | 643 | fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { |
614 | check(path, ra_fixture_before, ra_fixture_after, None, false) | 644 | check(path, ra_fixture_before, ra_fixture_after, None, false, true) |
615 | } | 645 | } |
616 | 646 | ||
617 | fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior) { | 647 | fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior) { |