1
Fork 0

Factor out business logic of expand_glob_import

This commit is contained in:
Olivier FAURE 2025-02-15 13:23:32 +01:00
parent 7f8781419c
commit 6e7838d81d

View file

@ -3,10 +3,11 @@ use hir::{AssocItem, Enum, HasVisibility, Module, ModuleDef, Name, PathResolutio
use ide_db::{
defs::{Definition, NameRefClass},
search::SearchScope,
source_change::SourceChangeBuilder,
};
use stdx::never;
use syntax::{
ast::{self, make},
ast::{self, make, Use, UseTree},
ted, AstNode, Direction, SyntaxNode, SyntaxToken, T,
};
@ -43,6 +44,7 @@ use crate::{
pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
let star = ctx.find_token_syntax_at_offset(T![*])?;
let use_tree = star.parent().and_then(ast::UseTree::cast)?;
let use_item = star.parent_ancestors().find_map(ast::Use::cast)?;
let (parent, mod_path) = find_parent_and_path(&star)?;
let target_module = match ctx.sema.resolve_path(&mod_path)? {
PathResolution::Def(ModuleDef::Module(it)) => Expandable::Module(it),
@ -53,8 +55,9 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) ->
let current_scope = ctx.sema.scope(&star.parent()?)?;
let current_module = current_scope.module();
let refs_in_target = find_refs_in_mod(ctx, target_module, current_module)?;
let imported_defs = find_imported_defs(ctx, star)?;
if !is_visible_from(ctx, &target_module, current_module) {
return None;
}
let target = parent.either(|n| n.syntax().clone(), |n| n.syntax().clone());
acc.add(
@ -62,6 +65,22 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) ->
"Expand glob import",
target.text_range(),
|builder| {
build_expanded_import(ctx, builder, use_tree, use_item, target_module, current_module)
},
)
}
fn build_expanded_import(
ctx: &AssistContext<'_>,
builder: &mut SourceChangeBuilder,
use_tree: UseTree,
use_item: Use,
target_module: Expandable,
current_module: Module,
) {
let refs_in_target = find_refs_in_mod(ctx, target_module, current_module);
let imported_defs = find_imported_defs(ctx, use_item);
let use_tree = builder.make_mut(use_tree);
let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs);
@ -89,8 +108,6 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) ->
}
None => never!(),
}
},
)
}
enum Expandable {
@ -176,36 +193,24 @@ impl Refs {
}
}
fn find_refs_in_mod(
ctx: &AssistContext<'_>,
expandable: Expandable,
visible_from: Module,
) -> Option<Refs> {
if !is_expandable_visible_from(ctx, &expandable, visible_from) {
return None;
}
fn find_refs_in_mod(ctx: &AssistContext<'_>, expandable: Expandable, visible_from: Module) -> Refs {
match expandable {
Expandable::Module(module) => {
let module_scope = module.scope(ctx.db(), Some(visible_from));
let refs =
module_scope.into_iter().filter_map(|(n, d)| Ref::from_scope_def(n, d)).collect();
Some(Refs(refs))
Refs(refs)
}
Expandable::Enum(enm) => Some(Refs(
Expandable::Enum(enm) => Refs(
enm.variants(ctx.db())
.into_iter()
.map(|v| Ref { visible_name: v.name(ctx.db()), def: Definition::Variant(v) })
.collect(),
)),
),
}
}
fn is_expandable_visible_from(
ctx: &AssistContext<'_>,
expandable: &Expandable,
from: Module,
) -> bool {
fn is_visible_from(ctx: &AssistContext<'_>, expandable: &Expandable, from: Module) -> bool {
fn is_mod_visible_from(ctx: &AssistContext<'_>, module: Module, from: Module) -> bool {
match module.parent(ctx.db()) {
Some(parent) => {
@ -246,22 +251,11 @@ fn is_expandable_visible_from(
// use foo::*$0;
// use baz::Baz;
// ↑ ---------------
fn find_imported_defs(ctx: &AssistContext<'_>, star: SyntaxToken) -> Option<Vec<Definition>> {
let parent_use_item_syntax = star.parent_ancestors().find_map(|n| {
if ast::Use::can_cast(n.kind()) {
Some(n)
} else {
None
}
})?;
Some(
fn find_imported_defs(ctx: &AssistContext<'_>, use_item: Use) -> Vec<Definition> {
[Direction::Prev, Direction::Next]
.into_iter()
.flat_map(|dir| {
parent_use_item_syntax
.siblings(dir.to_owned())
.filter(|n| ast::Use::can_cast(n.kind()))
use_item.syntax().siblings(dir.to_owned()).filter(|n| ast::Use::can_cast(n.kind()))
})
.flat_map(|n| n.descendants().filter_map(ast::NameRef::cast))
.filter_map(|r| match NameRefClass::classify(&ctx.sema, &r)? {
@ -279,8 +273,7 @@ fn find_imported_defs(ctx: &AssistContext<'_>, star: SyntaxToken) -> Option<Vec<
) => Some(def),
_ => None,
})
.collect(),
)
.collect()
}
fn find_names_to_import(