Skip to content

Commit d54e115

Browse files
bors[bot]asv7c2
andauthored
Merge #7889
7889: Make group imports configurable r=lnicola a=asv1 Co-authored-by: asv <[email protected]>
2 parents 708ec98 + 96fc01a commit d54e115

File tree

14 files changed

+79
-23
lines changed

14 files changed

+79
-23
lines changed

crates/ide_assists/src/handlers/auto_import.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
9999
format!("Import `{}`", &import),
100100
range,
101101
|builder| {
102-
let rewriter =
103-
insert_use(&scope, mod_path_to_ast(&import), ctx.config.insert_use.merge);
102+
let rewriter = insert_use(&scope, mod_path_to_ast(&import), ctx.config.insert_use);
104103
builder.rewrite(rewriter);
105104
},
106105
);

crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ fn insert_import(
154154
mod_path.pop_segment();
155155
mod_path.push_segment(variant_hir_name.clone());
156156
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);
158158
}
159159
Some(())
160160
}

crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub(crate) fn replace_qualified_name_with_use(
4444
let mut rewriter = SyntaxRewriter::default();
4545
shorten_paths(&mut rewriter, syntax.clone(), &path);
4646
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);
4848
builder.rewrite(rewriter);
4949
}
5050
},

crates/ide_assists/src/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
2323
insert_use: InsertUseConfig {
2424
merge: Some(MergeBehavior::Full),
2525
prefix_kind: hir::PrefixKind::Plain,
26+
group: true,
2627
},
2728
};
2829

crates/ide_completion/src/item.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::fmt;
55
use hir::{Documentation, ModPath, Mutability};
66
use ide_db::{
77
helpers::{
8-
insert_use::{self, ImportScope, MergeBehavior},
8+
insert_use::{self, ImportScope, InsertUseConfig},
99
mod_path_to_ast, SnippetCap,
1010
},
1111
SymbolKind,
@@ -280,14 +280,11 @@ pub struct ImportEdit {
280280
impl ImportEdit {
281281
/// Attempts to insert the import to the given scope, producing a text edit.
282282
/// 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> {
284284
let _p = profile::span("ImportEdit::to_text_edit");
285285

286-
let rewriter = insert_use::insert_use(
287-
&self.import_scope,
288-
mod_path_to_ast(&self.import_path),
289-
merge_behavior,
290-
);
286+
let rewriter =
287+
insert_use::insert_use(&self.import_scope, mod_path_to_ast(&self.import_path), cfg);
291288
let old_ast = rewriter.rewrite_root()?;
292289
let mut import_insert = TextEdit::builder();
293290
algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut import_insert);

crates/ide_completion/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ pub fn resolve_completion_edits(
156156
.find(|mod_path| mod_path.to_string() == full_import_path)?;
157157

158158
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)
160160
.map(|edit| vec![edit])
161161
}
162162

crates/ide_completion/src/test_utils.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
2525
insert_use: InsertUseConfig {
2626
merge: Some(MergeBehavior::Full),
2727
prefix_kind: PrefixKind::Plain,
28+
group: true,
2829
},
2930
};
3031

@@ -119,7 +120,7 @@ pub(crate) fn check_edit_with_config(
119120

120121
let mut combined_edit = completion.text_edit().to_owned();
121122
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))
123124
{
124125
combined_edit.union(import_text_edit).expect(
125126
"Failed to apply completion resolve changes: change ranges overlap, but should not",

crates/ide_db/src/helpers/insert_use.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use test_utils::mark;
1919
pub struct InsertUseConfig {
2020
pub merge: Option<MergeBehavior>,
2121
pub prefix_kind: hir::PrefixKind,
22+
pub group: bool,
2223
}
2324

2425
#[derive(Debug, Clone)]
@@ -99,13 +100,13 @@ fn is_inner_comment(token: SyntaxToken) -> bool {
99100
pub fn insert_use<'a>(
100101
scope: &ImportScope,
101102
path: ast::Path,
102-
merge: Option<MergeBehavior>,
103+
cfg: InsertUseConfig,
103104
) -> SyntaxRewriter<'a> {
104105
let _p = profile::span("insert_use");
105106
let mut rewriter = SyntaxRewriter::default();
106107
let use_item = make::use_(None, make::use_tree(path.clone(), None, None, false));
107108
// merge into existing imports if possible
108-
if let Some(mb) = merge {
109+
if let Some(mb) = cfg.merge {
109110
for existing_use in scope.as_syntax_node().children().filter_map(ast::Use::cast) {
110111
if let Some(merged) = try_merge_imports(&existing_use, &use_item, mb) {
111112
rewriter.replace(existing_use.syntax(), merged.syntax());
@@ -116,7 +117,7 @@ pub fn insert_use<'a>(
116117

117118
// either we weren't allowed to merge or there is no import that fits the merge conditions
118119
// 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);
120121

121122
let indent = if let ident_level @ 1..=usize::MAX = scope.indent_level().0 as usize {
122123
Some(make::tokens::whitespace(&" ".repeat(4 * ident_level)).into())
@@ -538,6 +539,7 @@ impl AddBlankLine {
538539
fn find_insert_position(
539540
scope: &ImportScope,
540541
insert_path: ast::Path,
542+
group_imports: bool,
541543
) -> (InsertPosition<SyntaxElement>, AddBlankLine) {
542544
let group = ImportGroup::new(&insert_path);
543545
let path_node_iter = scope
@@ -550,6 +552,14 @@ fn find_insert_position(
550552
let has_tl = tree.use_tree_list().is_some();
551553
Some((path, has_tl, node))
552554
});
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+
553563
// Iterator that discards anything thats not in the required grouping
554564
// This implementation allows the user to rearrange their import groups as this only takes the first group that fits
555565
let group_iter = path_node_iter
@@ -565,6 +575,7 @@ fn find_insert_position(
565575
use_tree_path_cmp(&insert_path, false, path, has_tl) != Ordering::Greater
566576
},
567577
);
578+
568579
match post_insert {
569580
// insert our import before that element
570581
Some((.., node)) => (InsertPosition::Before(node.into()), AddBlankLine::After),

crates/ide_db/src/helpers/insert_use/tests.rs

+34-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,31 @@
11
use super::*;
22

3+
use hir::PrefixKind;
34
use test_utils::assert_eq_text;
45

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+
529
#[test]
630
fn insert_existing() {
731
check_full("std::fs", "use std::fs;", "use std::fs;")
@@ -240,6 +264,7 @@ fn insert_empty_module() {
240264
}",
241265
None,
242266
true,
267+
true,
243268
)
244269
}
245270

@@ -584,6 +609,7 @@ fn check(
584609
ra_fixture_after: &str,
585610
mb: Option<MergeBehavior>,
586611
module: bool,
612+
group: bool,
587613
) {
588614
let mut syntax = ast::SourceFile::parse(ra_fixture_before).tree().syntax().clone();
589615
if module {
@@ -597,21 +623,25 @@ fn check(
597623
.find_map(ast::Path::cast)
598624
.unwrap();
599625

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+
);
601631
let result = rewriter.rewrite(file.as_syntax_node()).to_string();
602632
assert_eq_text!(ra_fixture_after, &result);
603633
}
604634

605635
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)
607637
}
608638

609639
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)
611641
}
612642

613643
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)
615645
}
616646

617647
fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior) {

crates/rust-analyzer/src/cli/analysis_bench.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,11 @@ impl BenchCmd {
108108
add_call_parenthesis: true,
109109
add_call_argument_snippets: true,
110110
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+
},
112116
};
113117
let res = do_work(&mut host, file_id, |analysis| {
114118
analysis.completions(&options, file_position)

crates/rust-analyzer/src/config.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ config_data! {
3535
assist_importMergeBehaviour: MergeBehaviorDef = "\"full\"",
3636
/// The path structure for newly inserted paths to use.
3737
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",
3940
/// Show function name and docs in parameter hints.
4041
callInfo_full: bool = "true",
4142

@@ -574,6 +575,7 @@ impl Config {
574575
ImportPrefixDef::ByCrate => PrefixKind::ByCrate,
575576
ImportPrefixDef::BySelf => PrefixKind::BySelf,
576577
},
578+
group: self.data.assist_importGroup,
577579
}
578580
}
579581
pub fn completion(&self) -> CompletionConfig {

crates/rust-analyzer/src/to_proto.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,11 @@ mod tests {
10871087
add_call_parenthesis: true,
10881088
add_call_argument_snippets: true,
10891089
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+
},
10911095
},
10921096
ide_db::base_db::FilePosition { file_id, offset },
10931097
)

docs/user/generated_config.adoc

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
The strategy to use when inserting new imports or merging imports.
33
[[rust-analyzer.assist.importPrefix]]rust-analyzer.assist.importPrefix (default: `"plain"`)::
44
The path structure for newly inserted paths to use.
5+
[[rust-analyzer.assist.importGroup]]rust-analyzer.assist.importGroup (default: `true`)::
6+
Group inserted imports by the [following order](https://rust-analyzer.github.io/manual.html#auto-import). Groups are separated by newlines.
57
[[rust-analyzer.callInfo.full]]rust-analyzer.callInfo.full (default: `true`)::
68
Show function name and docs in parameter hints.
79
[[rust-analyzer.cargo.autoreload]]rust-analyzer.cargo.autoreload (default: `true`)::

editors/code/package.json

+5
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,11 @@
385385
"Force import paths to be absolute by always starting them with `crate` or the crate name they refer to."
386386
]
387387
},
388+
"rust-analyzer.assist.importGroup": {
389+
"markdownDescription": "Group inserted imports by the [following order](https://rust-analyzer.github.io/manual.html#auto-import). Groups are separated by newlines.",
390+
"default": true,
391+
"type": "boolean"
392+
},
388393
"rust-analyzer.callInfo.full": {
389394
"markdownDescription": "Show function name and docs in parameter hints.",
390395
"default": true,

0 commit comments

Comments
 (0)