Skip to content

Commit 6e7838d

Browse files
committed
Factor out business logic of expand_glob_import
1 parent 7f87814 commit 6e7838d

File tree

1 file changed

+75
-82
lines changed

1 file changed

+75
-82
lines changed

src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs

+75-82
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ use hir::{AssocItem, Enum, HasVisibility, Module, ModuleDef, Name, PathResolutio
33
use ide_db::{
44
defs::{Definition, NameRefClass},
55
search::SearchScope,
6+
source_change::SourceChangeBuilder,
67
};
78
use stdx::never;
89
use syntax::{
9-
ast::{self, make},
10+
ast::{self, make, Use, UseTree},
1011
ted, AstNode, Direction, SyntaxNode, SyntaxToken, T,
1112
};
1213

@@ -43,6 +44,7 @@ use crate::{
4344
pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
4445
let star = ctx.find_token_syntax_at_offset(T![*])?;
4546
let use_tree = star.parent().and_then(ast::UseTree::cast)?;
47+
let use_item = star.parent_ancestors().find_map(ast::Use::cast)?;
4648
let (parent, mod_path) = find_parent_and_path(&star)?;
4749
let target_module = match ctx.sema.resolve_path(&mod_path)? {
4850
PathResolution::Def(ModuleDef::Module(it)) => Expandable::Module(it),
@@ -53,46 +55,61 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) ->
5355
let current_scope = ctx.sema.scope(&star.parent()?)?;
5456
let current_module = current_scope.module();
5557

56-
let refs_in_target = find_refs_in_mod(ctx, target_module, current_module)?;
57-
let imported_defs = find_imported_defs(ctx, star)?;
58+
if !is_visible_from(ctx, &target_module, current_module) {
59+
return None;
60+
}
5861

5962
let target = parent.either(|n| n.syntax().clone(), |n| n.syntax().clone());
6063
acc.add(
6164
AssistId("expand_glob_import", AssistKind::RefactorRewrite),
6265
"Expand glob import",
6366
target.text_range(),
6467
|builder| {
65-
let use_tree = builder.make_mut(use_tree);
66-
67-
let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs);
68-
let expanded = make::use_tree_list(names_to_import.iter().map(|n| {
69-
let path = make::ext::ident_path(
70-
&n.display(ctx.db(), current_module.krate().edition(ctx.db())).to_string(),
71-
);
72-
make::use_tree(path, None, None, false)
73-
}))
74-
.clone_for_update();
75-
76-
match use_tree.star_token() {
77-
Some(star) => {
78-
let needs_braces = use_tree.path().is_some() && names_to_import.len() != 1;
79-
if needs_braces {
80-
ted::replace(star, expanded.syntax())
81-
} else {
82-
let without_braces = expanded
83-
.syntax()
84-
.children_with_tokens()
85-
.filter(|child| !matches!(child.kind(), T!['{'] | T!['}']))
86-
.collect();
87-
ted::replace_with_many(star, without_braces)
88-
}
89-
}
90-
None => never!(),
91-
}
68+
build_expanded_import(ctx, builder, use_tree, use_item, target_module, current_module)
9269
},
9370
)
9471
}
9572

73+
fn build_expanded_import(
74+
ctx: &AssistContext<'_>,
75+
builder: &mut SourceChangeBuilder,
76+
use_tree: UseTree,
77+
use_item: Use,
78+
target_module: Expandable,
79+
current_module: Module,
80+
) {
81+
let refs_in_target = find_refs_in_mod(ctx, target_module, current_module);
82+
let imported_defs = find_imported_defs(ctx, use_item);
83+
84+
let use_tree = builder.make_mut(use_tree);
85+
86+
let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs);
87+
let expanded = make::use_tree_list(names_to_import.iter().map(|n| {
88+
let path = make::ext::ident_path(
89+
&n.display(ctx.db(), current_module.krate().edition(ctx.db())).to_string(),
90+
);
91+
make::use_tree(path, None, None, false)
92+
}))
93+
.clone_for_update();
94+
95+
match use_tree.star_token() {
96+
Some(star) => {
97+
let needs_braces = use_tree.path().is_some() && names_to_import.len() != 1;
98+
if needs_braces {
99+
ted::replace(star, expanded.syntax())
100+
} else {
101+
let without_braces = expanded
102+
.syntax()
103+
.children_with_tokens()
104+
.filter(|child| !matches!(child.kind(), T!['{'] | T!['}']))
105+
.collect();
106+
ted::replace_with_many(star, without_braces)
107+
}
108+
}
109+
None => never!(),
110+
}
111+
}
112+
96113
enum Expandable {
97114
Module(Module),
98115
Enum(Enum),
@@ -176,36 +193,24 @@ impl Refs {
176193
}
177194
}
178195

179-
fn find_refs_in_mod(
180-
ctx: &AssistContext<'_>,
181-
expandable: Expandable,
182-
visible_from: Module,
183-
) -> Option<Refs> {
184-
if !is_expandable_visible_from(ctx, &expandable, visible_from) {
185-
return None;
186-
}
187-
196+
fn find_refs_in_mod(ctx: &AssistContext<'_>, expandable: Expandable, visible_from: Module) -> Refs {
188197
match expandable {
189198
Expandable::Module(module) => {
190199
let module_scope = module.scope(ctx.db(), Some(visible_from));
191200
let refs =
192201
module_scope.into_iter().filter_map(|(n, d)| Ref::from_scope_def(n, d)).collect();
193-
Some(Refs(refs))
202+
Refs(refs)
194203
}
195-
Expandable::Enum(enm) => Some(Refs(
204+
Expandable::Enum(enm) => Refs(
196205
enm.variants(ctx.db())
197206
.into_iter()
198207
.map(|v| Ref { visible_name: v.name(ctx.db()), def: Definition::Variant(v) })
199208
.collect(),
200-
)),
209+
),
201210
}
202211
}
203212

204-
fn is_expandable_visible_from(
205-
ctx: &AssistContext<'_>,
206-
expandable: &Expandable,
207-
from: Module,
208-
) -> bool {
213+
fn is_visible_from(ctx: &AssistContext<'_>, expandable: &Expandable, from: Module) -> bool {
209214
fn is_mod_visible_from(ctx: &AssistContext<'_>, module: Module, from: Module) -> bool {
210215
match module.parent(ctx.db()) {
211216
Some(parent) => {
@@ -246,41 +251,29 @@ fn is_expandable_visible_from(
246251
// use foo::*$0;
247252
// use baz::Baz;
248253
// ↑ ---------------
249-
fn find_imported_defs(ctx: &AssistContext<'_>, star: SyntaxToken) -> Option<Vec<Definition>> {
250-
let parent_use_item_syntax = star.parent_ancestors().find_map(|n| {
251-
if ast::Use::can_cast(n.kind()) {
252-
Some(n)
253-
} else {
254-
None
255-
}
256-
})?;
257-
258-
Some(
259-
[Direction::Prev, Direction::Next]
260-
.into_iter()
261-
.flat_map(|dir| {
262-
parent_use_item_syntax
263-
.siblings(dir.to_owned())
264-
.filter(|n| ast::Use::can_cast(n.kind()))
265-
})
266-
.flat_map(|n| n.descendants().filter_map(ast::NameRef::cast))
267-
.filter_map(|r| match NameRefClass::classify(&ctx.sema, &r)? {
268-
NameRefClass::Definition(
269-
def @ (Definition::Macro(_)
270-
| Definition::Module(_)
271-
| Definition::Function(_)
272-
| Definition::Adt(_)
273-
| Definition::Variant(_)
274-
| Definition::Const(_)
275-
| Definition::Static(_)
276-
| Definition::Trait(_)
277-
| Definition::TypeAlias(_)),
278-
_,
279-
) => Some(def),
280-
_ => None,
281-
})
282-
.collect(),
283-
)
254+
fn find_imported_defs(ctx: &AssistContext<'_>, use_item: Use) -> Vec<Definition> {
255+
[Direction::Prev, Direction::Next]
256+
.into_iter()
257+
.flat_map(|dir| {
258+
use_item.syntax().siblings(dir.to_owned()).filter(|n| ast::Use::can_cast(n.kind()))
259+
})
260+
.flat_map(|n| n.descendants().filter_map(ast::NameRef::cast))
261+
.filter_map(|r| match NameRefClass::classify(&ctx.sema, &r)? {
262+
NameRefClass::Definition(
263+
def @ (Definition::Macro(_)
264+
| Definition::Module(_)
265+
| Definition::Function(_)
266+
| Definition::Adt(_)
267+
| Definition::Variant(_)
268+
| Definition::Const(_)
269+
| Definition::Static(_)
270+
| Definition::Trait(_)
271+
| Definition::TypeAlias(_)),
272+
_,
273+
) => Some(def),
274+
_ => None,
275+
})
276+
.collect()
284277
}
285278

286279
fn find_names_to_import(

0 commit comments

Comments
 (0)