Skip to content

Commit 7db4117

Browse files
committed
respect "one" import granularity config in merge imports assist
1 parent 4f176b3 commit 7db4117

File tree

3 files changed

+228
-20
lines changed

3 files changed

+228
-20
lines changed

crates/ide-assists/src/handlers/merge_imports.rs

Lines changed: 189 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use either::Either;
2-
use ide_db::imports::merge_imports::{try_merge_imports, try_merge_trees, MergeBehavior};
2+
use ide_db::imports::{
3+
insert_use::{ImportGranularity, InsertUseConfig},
4+
merge_imports::{try_merge_imports, try_merge_trees, MergeBehavior},
5+
};
36
use syntax::{
47
algo::neighbor,
58
ast::{self, edit_in_place::Removable},
@@ -30,14 +33,36 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
3033
let (target, edits) = if ctx.has_empty_selection() {
3134
// Merge a neighbor
3235
let tree: ast::UseTree = ctx.find_node_at_offset()?;
33-
let target = tree.syntax().text_range();
36+
let mut target = tree.syntax().text_range();
3437

3538
let edits = if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) {
3639
let mut neighbor = next_prev().find_map(|dir| neighbor(&use_item, dir)).into_iter();
37-
use_item.try_merge_from(&mut neighbor)
40+
use_item.try_merge_from(&mut neighbor, &ctx.config.insert_use)
3841
} else {
3942
let mut neighbor = next_prev().find_map(|dir| neighbor(&tree, dir)).into_iter();
40-
tree.try_merge_from(&mut neighbor)
43+
let mut edits = tree.clone().try_merge_from(&mut neighbor, &ctx.config.insert_use);
44+
45+
if edits.is_none() && ctx.config.insert_use.granularity == ImportGranularity::One {
46+
let one_tree = tree
47+
.parent_use_tree_list()
48+
.map(|it| it.parent_use_tree().top_use_tree())
49+
.filter(|top_tree| top_tree.path().is_none())
50+
.and_then(|one_tree| {
51+
one_tree.syntax().parent().and_then(ast::Use::cast).zip(Some(one_tree))
52+
});
53+
if let Some((use_item, one_tree)) = one_tree {
54+
let mut neighbor = next_prev()
55+
.find_map(|dir| syntax::algo::neighbor(&use_item, dir))
56+
.into_iter();
57+
edits = use_item.try_merge_from(&mut neighbor, &ctx.config.insert_use);
58+
59+
if edits.is_some() {
60+
target = one_tree.syntax().text_range();
61+
}
62+
}
63+
}
64+
65+
edits
4166
};
4267
(target, edits?)
4368
} else {
@@ -54,10 +79,10 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
5479
let edits = match_ast! {
5580
match first_selected {
5681
ast::Use(use_item) => {
57-
use_item.try_merge_from(&mut selected_nodes.filter_map(ast::Use::cast))
82+
use_item.try_merge_from(&mut selected_nodes.filter_map(ast::Use::cast), &ctx.config.insert_use)
5883
},
5984
ast::UseTree(use_tree) => {
60-
use_tree.try_merge_from(&mut selected_nodes.filter_map(ast::UseTree::cast))
85+
use_tree.try_merge_from(&mut selected_nodes.filter_map(ast::UseTree::cast), &ctx.config.insert_use)
6186
},
6287
_ => return None,
6388
}
@@ -89,11 +114,15 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
89114
}
90115

91116
trait Merge: AstNode + Clone {
92-
fn try_merge_from(self, items: &mut dyn Iterator<Item = Self>) -> Option<Vec<Edit>> {
117+
fn try_merge_from(
118+
self,
119+
items: &mut dyn Iterator<Item = Self>,
120+
cfg: &InsertUseConfig,
121+
) -> Option<Vec<Edit>> {
93122
let mut edits = Vec::new();
94123
let mut merged = self.clone();
95124
for item in items {
96-
merged = merged.try_merge(&item)?;
125+
merged = merged.try_merge(&item, cfg)?;
97126
edits.push(Edit::Remove(item.into_either()));
98127
}
99128
if !edits.is_empty() {
@@ -103,21 +132,25 @@ trait Merge: AstNode + Clone {
103132
None
104133
}
105134
}
106-
fn try_merge(&self, other: &Self) -> Option<Self>;
135+
fn try_merge(&self, other: &Self, cfg: &InsertUseConfig) -> Option<Self>;
107136
fn into_either(self) -> Either<ast::Use, ast::UseTree>;
108137
}
109138

110139
impl Merge for ast::Use {
111-
fn try_merge(&self, other: &Self) -> Option<Self> {
112-
try_merge_imports(self, other, MergeBehavior::Crate)
140+
fn try_merge(&self, other: &Self, cfg: &InsertUseConfig) -> Option<Self> {
141+
let mb = match cfg.granularity {
142+
ImportGranularity::One => MergeBehavior::One,
143+
_ => MergeBehavior::Crate,
144+
};
145+
try_merge_imports(self, other, mb)
113146
}
114147
fn into_either(self) -> Either<ast::Use, ast::UseTree> {
115148
Either::Left(self)
116149
}
117150
}
118151

119152
impl Merge for ast::UseTree {
120-
fn try_merge(&self, other: &Self) -> Option<Self> {
153+
fn try_merge(&self, other: &Self, _: &InsertUseConfig) -> Option<Self> {
121154
try_merge_trees(self, other, MergeBehavior::Crate)
122155
}
123156
fn into_either(self) -> Either<ast::Use, ast::UseTree> {
@@ -138,10 +171,35 @@ impl Edit {
138171

139172
#[cfg(test)]
140173
mod tests {
141-
use crate::tests::{check_assist, check_assist_not_applicable};
174+
use crate::tests::{check_assist, check_assist_import_one, check_assist_not_applicable};
142175

143176
use super::*;
144177

178+
macro_rules! check_assist_import_one_variations {
179+
($first: literal, $second: literal, $expected: literal) => {
180+
check_assist_import_one(
181+
merge_imports,
182+
concat!(concat!("use ", $first, ";"), concat!("use ", $second, ";")),
183+
$expected,
184+
);
185+
check_assist_import_one(
186+
merge_imports,
187+
concat!(concat!("use {", $first, "};"), concat!("use ", $second, ";")),
188+
$expected,
189+
);
190+
check_assist_import_one(
191+
merge_imports,
192+
concat!(concat!("use ", $first, ";"), concat!("use {", $second, "};")),
193+
$expected,
194+
);
195+
check_assist_import_one(
196+
merge_imports,
197+
concat!(concat!("use {", $first, "};"), concat!("use {", $second, "};")),
198+
$expected,
199+
);
200+
};
201+
}
202+
145203
#[test]
146204
fn test_merge_equal() {
147205
check_assist(
@@ -153,7 +211,12 @@ use std::fmt::{Display, Debug};
153211
r"
154212
use std::fmt::{Display, Debug};
155213
",
156-
)
214+
);
215+
check_assist_import_one_variations!(
216+
"std::fmt$0::{Display, Debug}",
217+
"std::fmt::{Display, Debug}",
218+
"use {std::fmt::{Display, Debug}};"
219+
);
157220
}
158221

159222
#[test]
@@ -167,7 +230,12 @@ use std::fmt::Display;
167230
r"
168231
use std::fmt::{Debug, Display};
169232
",
170-
)
233+
);
234+
check_assist_import_one_variations!(
235+
"std::fmt$0::Debug",
236+
"std::fmt::Display",
237+
"use {std::fmt::{Debug, Display}};"
238+
);
171239
}
172240

173241
#[test]
@@ -182,6 +250,11 @@ use std::fmt$0::Display;
182250
use std::fmt::{Debug, Display};
183251
",
184252
);
253+
check_assist_import_one_variations!(
254+
"std::fmt::Debug",
255+
"std::fmt$0::Display",
256+
"use {std::fmt::{Debug, Display}};"
257+
);
185258
}
186259

187260
#[test]
@@ -196,6 +269,11 @@ use std::fmt::Display;
196269
use std::fmt::{self, Display};
197270
",
198271
);
272+
check_assist_import_one_variations!(
273+
"std::fmt$0",
274+
"std::fmt::Display",
275+
"use {std::fmt::{self, Display}};"
276+
);
199277
}
200278

201279
#[test]
@@ -207,6 +285,15 @@ use std::{fmt, $0fmt::Display};
207285
",
208286
r"
209287
use std::{fmt::{self, Display}};
288+
",
289+
);
290+
check_assist_import_one(
291+
merge_imports,
292+
r"
293+
use {std::{fmt, $0fmt::Display}};
294+
",
295+
r"
296+
use {std::{fmt::{self, Display}}};
210297
",
211298
);
212299
}
@@ -306,6 +393,15 @@ use std::{fmt$0::Debug, fmt::Display};
306393
",
307394
r"
308395
use std::{fmt::{Debug, Display}};
396+
",
397+
);
398+
check_assist_import_one(
399+
merge_imports,
400+
r"
401+
use {std::{fmt$0::Debug, fmt::Display}};
402+
",
403+
r"
404+
use {std::{fmt::{Debug, Display}}};
309405
",
310406
);
311407
}
@@ -319,6 +415,15 @@ use std::{fmt::Debug, fmt$0::Display};
319415
",
320416
r"
321417
use std::{fmt::{Debug, Display}};
418+
",
419+
);
420+
check_assist_import_one(
421+
merge_imports,
422+
r"
423+
use {std::{fmt::Debug, fmt$0::Display}};
424+
",
425+
r"
426+
use {std::{fmt::{Debug, Display}}};
322427
",
323428
);
324429
}
@@ -335,6 +440,11 @@ use std::{fmt::{self, Debug}};
335440
use std::{fmt::{self, Debug, Display, Write}};
336441
",
337442
);
443+
check_assist_import_one_variations!(
444+
"std$0::{fmt::{Write, Display}}",
445+
"std::{fmt::{self, Debug}}",
446+
"use {std::{fmt::{self, Debug, Display, Write}}};"
447+
);
338448
}
339449

340450
#[test]
@@ -349,6 +459,11 @@ use std::{fmt::{Write, Display}};
349459
use std::{fmt::{self, Debug, Display, Write}};
350460
",
351461
);
462+
check_assist_import_one_variations!(
463+
"std$0::{fmt::{self, Debug}}",
464+
"std::{fmt::{Write, Display}}",
465+
"use {std::{fmt::{self, Debug, Display, Write}}};"
466+
);
352467
}
353468

354469
#[test]
@@ -360,6 +475,15 @@ use std::{fmt$0::{self, Debug}, fmt::{Write, Display}};
360475
",
361476
r"
362477
use std::{fmt::{self, Debug, Display, Write}};
478+
",
479+
);
480+
check_assist_import_one(
481+
merge_imports,
482+
r"
483+
use {std::{fmt$0::{self, Debug}, fmt::{Write, Display}}};
484+
",
485+
r"
486+
use {std::{fmt::{self, Debug, Display, Write}}};
363487
",
364488
);
365489
}
@@ -375,7 +499,12 @@ use foo::{bar};
375499
r"
376500
use foo::{bar::{self}};
377501
",
378-
)
502+
);
503+
check_assist_import_one_variations!(
504+
"foo::$0{bar::{self}}",
505+
"foo::{bar}",
506+
"use {foo::{bar::{self}}};"
507+
);
379508
}
380509

381510
#[test]
@@ -389,7 +518,12 @@ use foo::{bar::{self}};
389518
r"
390519
use foo::{bar::{self}};
391520
",
392-
)
521+
);
522+
check_assist_import_one_variations!(
523+
"foo::$0{bar}",
524+
"foo::{bar::{self}}",
525+
"use {foo::{bar::{self}}};"
526+
);
393527
}
394528

395529
#[test]
@@ -403,7 +537,12 @@ use std::{fmt::{self, Display}};
403537
r"
404538
use std::{fmt::{self, Display, *}};
405539
",
406-
)
540+
);
541+
check_assist_import_one_variations!(
542+
"std$0::{fmt::*}",
543+
"std::{fmt::{self, Display}}",
544+
"use {std::{fmt::{self, Display, *}}};"
545+
);
407546
}
408547

409548
#[test]
@@ -417,7 +556,12 @@ use std::str;
417556
r"
418557
use std::{cell::*, str};
419558
",
420-
)
559+
);
560+
check_assist_import_one_variations!(
561+
"std$0::cell::*",
562+
"std::str",
563+
"use {std::{cell::*, str}};"
564+
);
421565
}
422566

423567
#[test]
@@ -431,7 +575,12 @@ use std::str::*;
431575
r"
432576
use std::{cell::*, str::*};
433577
",
434-
)
578+
);
579+
check_assist_import_one_variations!(
580+
"std$0::cell::*",
581+
"std::str::*",
582+
"use {std::{cell::*, str::*}};"
583+
);
435584
}
436585

437586
#[test]
@@ -524,6 +673,11 @@ use foo::bar::Baz;
524673
use foo::{bar::Baz, *};
525674
",
526675
);
676+
check_assist_import_one_variations!(
677+
"foo::$0*",
678+
"foo::bar::Baz",
679+
"use {foo::{bar::Baz, *}};"
680+
);
527681
}
528682

529683
#[test]
@@ -541,6 +695,21 @@ $0use std::fmt::Result;
541695
use std::fmt::Error;
542696
use std::fmt::{Debug, Display, Write};
543697
use std::fmt::Result;
698+
",
699+
);
700+
check_assist_import_one(
701+
merge_imports,
702+
r"
703+
use std::fmt::Error;
704+
$0use std::fmt::Display;
705+
use std::fmt::Debug;
706+
use std::fmt::Write;
707+
$0use std::fmt::Result;
708+
",
709+
r"
710+
use std::fmt::Error;
711+
use {std::fmt::{Debug, Display, Write}};
712+
use std::fmt::Result;
544713
",
545714
);
546715
}

0 commit comments

Comments
 (0)