aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_db')
-rw-r--r--crates/ide_db/src/helpers/insert_use.rs17
-rw-r--r--crates/ide_db/src/helpers/insert_use/tests.rs38
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;
19pub struct InsertUseConfig { 19pub 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 {
99pub fn insert_use<'a>( 100pub 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 {
538fn find_insert_position( 539fn 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 @@
1use super::*; 1use super::*;
2 2
3use hir::PrefixKind;
3use test_utils::assert_eq_text; 4use test_utils::assert_eq_text;
4 5
5#[test] 6#[test]
7fn insert_not_group() {
8 check(
9 "use external_crate2::bar::A",
10 r"
11use std::bar::B;
12use external_crate::bar::A;
13use crate::bar::A;
14use self::bar::A;
15use super::bar::A;",
16 r"
17use std::bar::B;
18use external_crate::bar::A;
19use crate::bar::A;
20use self::bar::A;
21use super::bar::A;
22use external_crate2::bar::A;",
23 None,
24 false,
25 false,
26 );
27}
28
29#[test]
6fn insert_existing() { 30fn 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
605fn check_full(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 635fn 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
609fn check_last(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 639fn 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
613fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 643fn 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
617fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior) { 647fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior) {