aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorasv <[email protected]>2021-03-06 11:02:26 +0000
committerasv <[email protected]>2021-03-07 08:15:17 +0000
commit96fc01a30b88d95619b26fd96c58627dd54cb339 (patch)
tree2959357aae5a465555a924db44979686999c4b4a /crates
parent750d3cb84678b23a55092f2e4726e48ead37a9ff (diff)
Make group imports configurable
Diffstat (limited to 'crates')
-rw-r--r--crates/ide_assists/src/handlers/auto_import.rs3
-rw-r--r--crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs2
-rw-r--r--crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs2
-rw-r--r--crates/ide_assists/src/tests.rs1
-rw-r--r--crates/ide_completion/src/item.rs11
-rw-r--r--crates/ide_completion/src/lib.rs2
-rw-r--r--crates/ide_completion/src/test_utils.rs3
-rw-r--r--crates/ide_db/src/helpers/insert_use.rs17
-rw-r--r--crates/ide_db/src/helpers/insert_use/tests.rs38
-rw-r--r--crates/rust-analyzer/src/cli/analysis_bench.rs6
-rw-r--r--crates/rust-analyzer/src/config.rs4
-rw-r--r--crates/rust-analyzer/src/to_proto.rs6
12 files changed, 72 insertions, 23 deletions
diff --git a/crates/ide_assists/src/handlers/auto_import.rs b/crates/ide_assists/src/handlers/auto_import.rs
index dc38f90e9..1422224ac 100644
--- a/crates/ide_assists/src/handlers/auto_import.rs
+++ b/crates/ide_assists/src/handlers/auto_import.rs
@@ -99,8 +99,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
99 format!("Import `{}`", &import), 99 format!("Import `{}`", &import),
100 range, 100 range,
101 |builder| { 101 |builder| {
102 let rewriter = 102 let rewriter = insert_use(&scope, mod_path_to_ast(&import), ctx.config.insert_use);
103 insert_use(&scope, mod_path_to_ast(&import), ctx.config.insert_use.merge);
104 builder.rewrite(rewriter); 103 builder.rewrite(rewriter);
105 }, 104 },
106 ); 105 );
diff --git a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs
index 5c7678b53..4f0422e96 100644
--- a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -154,7 +154,7 @@ fn insert_import(
154 mod_path.pop_segment(); 154 mod_path.pop_segment();
155 mod_path.push_segment(variant_hir_name.clone()); 155 mod_path.push_segment(variant_hir_name.clone());
156 let scope = ImportScope::find_insert_use_container(scope_node, &ctx.sema)?; 156 let scope = ImportScope::find_insert_use_container(scope_node, &ctx.sema)?;
157 *rewriter += insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use.merge); 157 *rewriter += insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use);
158 } 158 }
159 Some(()) 159 Some(())
160} 160}
diff --git a/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs
index f3bc6cf39..55481af34 100644
--- a/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs
@@ -44,7 +44,7 @@ pub(crate) fn replace_qualified_name_with_use(
44 let mut rewriter = SyntaxRewriter::default(); 44 let mut rewriter = SyntaxRewriter::default();
45 shorten_paths(&mut rewriter, syntax.clone(), &path); 45 shorten_paths(&mut rewriter, syntax.clone(), &path);
46 if let Some(ref import_scope) = ImportScope::from(syntax.clone()) { 46 if let Some(ref import_scope) = ImportScope::from(syntax.clone()) {
47 rewriter += insert_use(import_scope, path, ctx.config.insert_use.merge); 47 rewriter += insert_use(import_scope, path, ctx.config.insert_use);
48 builder.rewrite(rewriter); 48 builder.rewrite(rewriter);
49 } 49 }
50 }, 50 },
diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs
index b7f616760..a7a923beb 100644
--- a/crates/ide_assists/src/tests.rs
+++ b/crates/ide_assists/src/tests.rs
@@ -23,6 +23,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
23 insert_use: InsertUseConfig { 23 insert_use: InsertUseConfig {
24 merge: Some(MergeBehavior::Full), 24 merge: Some(MergeBehavior::Full),
25 prefix_kind: hir::PrefixKind::Plain, 25 prefix_kind: hir::PrefixKind::Plain,
26 group: true,
26 }, 27 },
27}; 28};
28 29
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs
index 884711f11..9b2435c4b 100644
--- a/crates/ide_completion/src/item.rs
+++ b/crates/ide_completion/src/item.rs
@@ -5,7 +5,7 @@ use std::fmt;
5use hir::{Documentation, ModPath, Mutability}; 5use hir::{Documentation, ModPath, Mutability};
6use ide_db::{ 6use ide_db::{
7 helpers::{ 7 helpers::{
8 insert_use::{self, ImportScope, MergeBehavior}, 8 insert_use::{self, ImportScope, InsertUseConfig},
9 mod_path_to_ast, SnippetCap, 9 mod_path_to_ast, SnippetCap,
10 }, 10 },
11 SymbolKind, 11 SymbolKind,
@@ -280,14 +280,11 @@ pub struct ImportEdit {
280impl ImportEdit { 280impl ImportEdit {
281 /// Attempts to insert the import to the given scope, producing a text edit. 281 /// Attempts to insert the import to the given scope, producing a text edit.
282 /// May return no edit in edge cases, such as scope already containing the import. 282 /// May return no edit in edge cases, such as scope already containing the import.
283 pub fn to_text_edit(&self, merge_behavior: Option<MergeBehavior>) -> Option<TextEdit> { 283 pub fn to_text_edit(&self, cfg: InsertUseConfig) -> Option<TextEdit> {
284 let _p = profile::span("ImportEdit::to_text_edit"); 284 let _p = profile::span("ImportEdit::to_text_edit");
285 285
286 let rewriter = insert_use::insert_use( 286 let rewriter =
287 &self.import_scope, 287 insert_use::insert_use(&self.import_scope, mod_path_to_ast(&self.import_path), cfg);
288 mod_path_to_ast(&self.import_path),
289 merge_behavior,
290 );
291 let old_ast = rewriter.rewrite_root()?; 288 let old_ast = rewriter.rewrite_root()?;
292 let mut import_insert = TextEdit::builder(); 289 let mut import_insert = TextEdit::builder();
293 algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut import_insert); 290 algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut import_insert);
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs
index 76f31de9e..b0b809791 100644
--- a/crates/ide_completion/src/lib.rs
+++ b/crates/ide_completion/src/lib.rs
@@ -156,7 +156,7 @@ pub fn resolve_completion_edits(
156 .find(|mod_path| mod_path.to_string() == full_import_path)?; 156 .find(|mod_path| mod_path.to_string() == full_import_path)?;
157 157
158 ImportEdit { import_path, import_scope, import_for_trait_assoc_item } 158 ImportEdit { import_path, import_scope, import_for_trait_assoc_item }
159 .to_text_edit(config.insert_use.merge) 159 .to_text_edit(config.insert_use)
160 .map(|edit| vec![edit]) 160 .map(|edit| vec![edit])
161} 161}
162 162
diff --git a/crates/ide_completion/src/test_utils.rs b/crates/ide_completion/src/test_utils.rs
index baff83305..9da844031 100644
--- a/crates/ide_completion/src/test_utils.rs
+++ b/crates/ide_completion/src/test_utils.rs
@@ -25,6 +25,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
25 insert_use: InsertUseConfig { 25 insert_use: InsertUseConfig {
26 merge: Some(MergeBehavior::Full), 26 merge: Some(MergeBehavior::Full),
27 prefix_kind: PrefixKind::Plain, 27 prefix_kind: PrefixKind::Plain,
28 group: true,
28 }, 29 },
29}; 30};
30 31
@@ -119,7 +120,7 @@ pub(crate) fn check_edit_with_config(
119 120
120 let mut combined_edit = completion.text_edit().to_owned(); 121 let mut combined_edit = completion.text_edit().to_owned();
121 if let Some(import_text_edit) = 122 if let Some(import_text_edit) =
122 completion.import_to_add().and_then(|edit| edit.to_text_edit(config.insert_use.merge)) 123 completion.import_to_add().and_then(|edit| edit.to_text_edit(config.insert_use))
123 { 124 {
124 combined_edit.union(import_text_edit).expect( 125 combined_edit.union(import_text_edit).expect(
125 "Failed to apply completion resolve changes: change ranges overlap, but should not", 126 "Failed to apply completion resolve changes: change ranges overlap, but should not",
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) {
diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs
index 3bd7e678d..49994824f 100644
--- a/crates/rust-analyzer/src/cli/analysis_bench.rs
+++ b/crates/rust-analyzer/src/cli/analysis_bench.rs
@@ -108,7 +108,11 @@ impl BenchCmd {
108 add_call_parenthesis: true, 108 add_call_parenthesis: true,
109 add_call_argument_snippets: true, 109 add_call_argument_snippets: true,
110 snippet_cap: SnippetCap::new(true), 110 snippet_cap: SnippetCap::new(true),
111 insert_use: InsertUseConfig { merge: None, prefix_kind: PrefixKind::Plain }, 111 insert_use: InsertUseConfig {
112 merge: None,
113 prefix_kind: PrefixKind::Plain,
114 group: true,
115 },
112 }; 116 };
113 let res = do_work(&mut host, file_id, |analysis| { 117 let res = do_work(&mut host, file_id, |analysis| {
114 analysis.completions(&options, file_position) 118 analysis.completions(&options, file_position)
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 367136702..cac48e911 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -35,7 +35,8 @@ config_data! {
35 assist_importMergeBehaviour: MergeBehaviorDef = "\"full\"", 35 assist_importMergeBehaviour: MergeBehaviorDef = "\"full\"",
36 /// The path structure for newly inserted paths to use. 36 /// The path structure for newly inserted paths to use.
37 assist_importPrefix: ImportPrefixDef = "\"plain\"", 37 assist_importPrefix: ImportPrefixDef = "\"plain\"",
38 38 /// Group inserted imports by the [following order](https://rust-analyzer.github.io/manual.html#auto-import). Groups are separated by newlines.
39 assist_importGroup: bool = "true",
39 /// Show function name and docs in parameter hints. 40 /// Show function name and docs in parameter hints.
40 callInfo_full: bool = "true", 41 callInfo_full: bool = "true",
41 42
@@ -574,6 +575,7 @@ impl Config {
574 ImportPrefixDef::ByCrate => PrefixKind::ByCrate, 575 ImportPrefixDef::ByCrate => PrefixKind::ByCrate,
575 ImportPrefixDef::BySelf => PrefixKind::BySelf, 576 ImportPrefixDef::BySelf => PrefixKind::BySelf,
576 }, 577 },
578 group: self.data.assist_importGroup,
577 } 579 }
578 } 580 }
579 pub fn completion(&self) -> CompletionConfig { 581 pub fn completion(&self) -> CompletionConfig {
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index c1ca88df6..4235eb6dd 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -1087,7 +1087,11 @@ mod tests {
1087 add_call_parenthesis: true, 1087 add_call_parenthesis: true,
1088 add_call_argument_snippets: true, 1088 add_call_argument_snippets: true,
1089 snippet_cap: SnippetCap::new(true), 1089 snippet_cap: SnippetCap::new(true),
1090 insert_use: InsertUseConfig { merge: None, prefix_kind: PrefixKind::Plain }, 1090 insert_use: InsertUseConfig {
1091 merge: None,
1092 prefix_kind: PrefixKind::Plain,
1093 group: true,
1094 },
1091 }, 1095 },
1092 ide_db::base_db::FilePosition { file_id, offset }, 1096 ide_db::base_db::FilePosition { file_id, offset },
1093 ) 1097 )