Skip to content

Commit 128eef7

Browse files
committed
Improve AST replacing in expand glob import
1 parent 71d2c4a commit 128eef7

File tree

1 file changed

+229
-38
lines changed

1 file changed

+229
-38
lines changed

crates/assists/src/handlers/expand_glob_import.rs

Lines changed: 229 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use ide_db::{
44
defs::{classify_name_ref, Definition, NameRefClass},
55
RootDatabase,
66
};
7-
use syntax::{algo, ast, match_ast, AstNode, SyntaxNode, SyntaxToken, T};
7+
use syntax::{ast, AstNode, SyntaxToken, T};
88

99
use crate::{
1010
assist_context::{AssistBuilder, AssistContext, Assists},
@@ -38,7 +38,7 @@ use crate::{
3838
// ```
3939
pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
4040
let star = ctx.find_token_at_offset(T![*])?;
41-
let mod_path = find_mod_path(&star)?;
41+
let (parent, mod_path) = find_parent_and_path(&star)?;
4242
let module = match ctx.sema.resolve_path(&mod_path)? {
4343
PathResolution::Def(ModuleDef::Module(it)) => it,
4444
_ => return None,
@@ -52,19 +52,23 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti
5252
source_file.syntax().descendants().filter_map(ast::NameRef::cast).collect();
5353
let used_names = find_used_names(ctx, defs_in_mod, name_refs_in_source_file);
5454

55-
let parent = star.parent().parent()?;
55+
let target = parent.syntax();
5656
acc.add(
5757
AssistId("expand_glob_import", AssistKind::RefactorRewrite),
5858
"Expand glob import",
59-
parent.text_range(),
59+
target.text_range(),
6060
|builder| {
61-
replace_ast(builder, &parent, mod_path, used_names);
61+
replace_ast(builder, parent, mod_path, used_names);
6262
},
6363
)
6464
}
6565

66-
fn find_mod_path(star: &SyntaxToken) -> Option<ast::Path> {
67-
star.ancestors().find_map(|n| ast::UseTree::cast(n).and_then(|u| u.path()))
66+
fn find_parent_and_path(star: &SyntaxToken) -> Option<(ast::UseTree, ast::Path)> {
67+
star.ancestors().find_map(|n| {
68+
let use_tree = ast::UseTree::cast(n)?;
69+
let path = use_tree.path()?;
70+
Some((use_tree, path))
71+
})
6872
}
6973

7074
#[derive(PartialEq)]
@@ -137,41 +141,28 @@ fn find_used_names(
137141

138142
fn replace_ast(
139143
builder: &mut AssistBuilder,
140-
node: &SyntaxNode,
144+
parent: ast::UseTree,
141145
path: ast::Path,
142146
used_names: Vec<Name>,
143147
) {
144-
let replacement: Either<ast::UseTree, ast::UseTreeList> = match used_names.as_slice() {
145-
[name] => Either::Left(ast::make::use_tree(
148+
let replacement = match used_names.as_slice() {
149+
[name] => ast::make::use_tree(
146150
ast::make::path_from_text(&format!("{}::{}", path, name)),
147151
None,
148152
None,
149153
false,
150-
)),
151-
names => Either::Right(ast::make::use_tree_list(names.iter().map(|n| {
152-
ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false)
153-
}))),
154-
};
155-
156-
let mut replace_node = |replacement: Either<ast::UseTree, ast::UseTreeList>| {
157-
algo::diff(node, &replacement.either(|u| u.syntax().clone(), |ut| ut.syntax().clone()))
158-
.into_text_edit(builder.text_edit_builder());
154+
),
155+
names => ast::make::use_tree(
156+
path,
157+
Some(ast::make::use_tree_list(names.iter().map(|n| {
158+
ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false)
159+
}))),
160+
None,
161+
false,
162+
),
159163
};
160164

161-
match_ast! {
162-
match node {
163-
ast::UseTree(use_tree) => {
164-
replace_node(replacement);
165-
},
166-
ast::UseTreeList(use_tree_list) => {
167-
replace_node(replacement);
168-
},
169-
ast::Use(use_item) => {
170-
builder.replace_ast(use_item, ast::make::use_(replacement.left_or_else(|ut| ast::make::use_tree(path, Some(ut), None, false))));
171-
},
172-
_ => {},
173-
}
174-
}
165+
builder.replace_ast(parent, replacement);
175166
}
176167

177168
#[cfg(test)]
@@ -260,15 +251,15 @@ fn qux(bar: Bar, baz: Baz) {
260251
expand_glob_import,
261252
r"
262253
mod foo {
263-
mod bar {
254+
pub mod bar {
264255
pub struct Bar;
265256
pub struct Baz;
266257
pub struct Qux;
267258
268259
pub fn f() {}
269260
}
270261
271-
mod baz {
262+
pub mod baz {
272263
pub fn g() {}
273264
}
274265
}
@@ -282,15 +273,15 @@ fn qux(bar: Bar, baz: Baz) {
282273
",
283274
r"
284275
mod foo {
285-
mod bar {
276+
pub mod bar {
286277
pub struct Bar;
287278
pub struct Baz;
288279
pub struct Qux;
289280
290281
pub fn f() {}
291282
}
292283
293-
mod baz {
284+
pub mod baz {
294285
pub fn g() {}
295286
}
296287
}
@@ -302,7 +293,207 @@ fn qux(bar: Bar, baz: Baz) {
302293
g();
303294
}
304295
",
305-
)
296+
);
297+
298+
check_assist(
299+
expand_glob_import,
300+
r"
301+
mod foo {
302+
pub mod bar {
303+
pub struct Bar;
304+
pub struct Baz;
305+
pub struct Qux;
306+
307+
pub fn f() {}
308+
}
309+
310+
pub mod baz {
311+
pub fn g() {}
312+
}
313+
}
314+
315+
use foo::{bar::{Bar, Baz, f}, baz::*<|>};
316+
317+
fn qux(bar: Bar, baz: Baz) {
318+
f();
319+
g();
320+
}
321+
",
322+
r"
323+
mod foo {
324+
pub mod bar {
325+
pub struct Bar;
326+
pub struct Baz;
327+
pub struct Qux;
328+
329+
pub fn f() {}
330+
}
331+
332+
pub mod baz {
333+
pub fn g() {}
334+
}
335+
}
336+
337+
use foo::{bar::{Bar, Baz, f}, baz::g};
338+
339+
fn qux(bar: Bar, baz: Baz) {
340+
f();
341+
g();
342+
}
343+
",
344+
);
345+
346+
check_assist(
347+
expand_glob_import,
348+
r"
349+
mod foo {
350+
pub mod bar {
351+
pub struct Bar;
352+
pub struct Baz;
353+
pub struct Qux;
354+
355+
pub fn f() {}
356+
}
357+
358+
pub mod baz {
359+
pub fn g() {}
360+
361+
pub mod qux {
362+
pub fn h() {}
363+
pub fn m() {}
364+
365+
pub mod q {
366+
pub fn j() {}
367+
}
368+
}
369+
}
370+
}
371+
372+
use foo::{
373+
bar::{*, f},
374+
baz::{g, qux::*<|>}
375+
};
376+
377+
fn qux(bar: Bar, baz: Baz) {
378+
f();
379+
g();
380+
h();
381+
q::j();
382+
}
383+
",
384+
r"
385+
mod foo {
386+
pub mod bar {
387+
pub struct Bar;
388+
pub struct Baz;
389+
pub struct Qux;
390+
391+
pub fn f() {}
392+
}
393+
394+
pub mod baz {
395+
pub fn g() {}
396+
397+
pub mod qux {
398+
pub fn h() {}
399+
pub fn m() {}
400+
401+
pub mod q {
402+
pub fn j() {}
403+
}
404+
}
405+
}
406+
}
407+
408+
use foo::{
409+
bar::{*, f},
410+
baz::{g, qux::{q, h}}
411+
};
412+
413+
fn qux(bar: Bar, baz: Baz) {
414+
f();
415+
g();
416+
h();
417+
q::j();
418+
}
419+
",
420+
);
421+
422+
check_assist(
423+
expand_glob_import,
424+
r"
425+
mod foo {
426+
pub mod bar {
427+
pub struct Bar;
428+
pub struct Baz;
429+
pub struct Qux;
430+
431+
pub fn f() {}
432+
}
433+
434+
pub mod baz {
435+
pub fn g() {}
436+
437+
pub mod qux {
438+
pub fn h() {}
439+
pub fn m() {}
440+
441+
pub mod q {
442+
pub fn j() {}
443+
}
444+
}
445+
}
446+
}
447+
448+
use foo::{
449+
bar::{*, f},
450+
baz::{g, qux::{h, q::*<|>}}
451+
};
452+
453+
fn qux(bar: Bar, baz: Baz) {
454+
f();
455+
g();
456+
h();
457+
j();
458+
}
459+
",
460+
r"
461+
mod foo {
462+
pub mod bar {
463+
pub struct Bar;
464+
pub struct Baz;
465+
pub struct Qux;
466+
467+
pub fn f() {}
468+
}
469+
470+
pub mod baz {
471+
pub fn g() {}
472+
473+
pub mod qux {
474+
pub fn h() {}
475+
pub fn m() {}
476+
477+
pub mod q {
478+
pub fn j() {}
479+
}
480+
}
481+
}
482+
}
483+
484+
use foo::{
485+
bar::{*, f},
486+
baz::{g, qux::{h, q::j}}
487+
};
488+
489+
fn qux(bar: Bar, baz: Baz) {
490+
f();
491+
g();
492+
h();
493+
j();
494+
}
495+
",
496+
);
306497
}
307498

308499
#[test]

0 commit comments

Comments
 (0)