extract_module: Resolve imports lazily

This commit is contained in:
iDawer 2022-03-28 21:31:07 +05:00
parent 031bdf2472
commit 1e71ac286b

View file

@ -81,38 +81,34 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext) -> Option<(
} }
let mut module = extract_target(&node, ctx.selection_trimmed())?; let mut module = extract_target(&node, ctx.selection_trimmed())?;
if module.body_items.len() == 0 { if module.body_items.is_empty() {
return None; return None;
} }
let old_item_indent = module.body_items[0].indent_level(); let old_item_indent = module.body_items[0].indent_level();
//This takes place in three steps:
//
//- Firstly, we will update the references(usages) e.g. converting a
// function call bar() to modname::bar(), and similarly for other items
//
//- Secondly, changing the visibility of each item inside the newly selected module
// i.e. making a fn a() {} to pub(crate) fn a() {}
//
//- Thirdly, resolving all the imports this includes removing paths from imports
// outside the module, shifting/cloning them inside new module, or shifting the imports, or making
// new import statemnts
//We are getting item usages and record_fields together, record_fields
//for change_visibility and usages for first point mentioned above in the process
let (usages_to_be_processed, record_fields) = module.get_usages_and_record_fields(ctx);
let import_paths_to_be_removed = module.resolve_imports(curr_parent_module, ctx);
if module.body_items.len() == 0 {
return None;
}
acc.add( acc.add(
AssistId("extract_module", AssistKind::RefactorExtract), AssistId("extract_module", AssistKind::RefactorExtract),
"Extract Module", "Extract Module",
module.text_range, module.text_range,
|builder| { |builder| {
//This takes place in three steps:
//
//- Firstly, we will update the references(usages) e.g. converting a
// function call bar() to modname::bar(), and similarly for other items
//
//- Secondly, changing the visibility of each item inside the newly selected module
// i.e. making a fn a() {} to pub(crate) fn a() {}
//
//- Thirdly, resolving all the imports this includes removing paths from imports
// outside the module, shifting/cloning them inside new module, or shifting the imports, or making
// new import statemnts
//We are getting item usages and record_fields together, record_fields
//for change_visibility and usages for first point mentioned above in the process
let (usages_to_be_processed, record_fields) = module.get_usages_and_record_fields(ctx);
let import_paths_to_be_removed = module.resolve_imports(curr_parent_module, ctx);
module.change_visibility(record_fields); module.change_visibility(record_fields);
let mut body_items: Vec<String> = Vec::new(); let mut body_items: Vec<String> = Vec::new();
@ -221,19 +217,13 @@ fn extract_target(node: &SyntaxNode, selection_range: TextRange) -> Option<Modul
let mut body_items: Vec<ast::Item> = node let mut body_items: Vec<ast::Item> = node
.children() .children()
.filter_map(|child| { .filter(|child| selection_range.contains_range(child.text_range()))
if selection_range.contains_range(child.text_range()) { .filter_map(|child| match ast::Item::cast(child) {
let child_kind = child.kind(); Some(it @ ast::Item::Use(_)) => {
if let Some(item) = ast::Item::cast(child) { use_items.push(it);
if ast::Use::can_cast(child_kind) { None
use_items.push(item);
} else {
return Some(item);
}
}
return None;
} }
None item => item,
}) })
.collect(); .collect();
@ -368,9 +358,7 @@ impl Module {
source_file: &SourceFile, source_file: &SourceFile,
FileReference { range, name, .. }: FileReference, FileReference { range, name, .. }: FileReference,
) -> Option<(TextRange, String)> { ) -> Option<(TextRange, String)> {
let path: Option<ast::Path> = find_node_at_range(source_file.syntax(), range); let path: ast::Path = find_node_at_range(source_file.syntax(), range)?;
let path = path?;
for desc in path.syntax().descendants() { for desc in path.syntax().descendants() {
if desc.to_string() == name.syntax().to_string() if desc.to_string() == name.syntax().to_string()
@ -609,9 +597,8 @@ impl Module {
let use_ = let use_ =
make::use_(None, make::use_tree(make::join_paths(use_tree_str), None, None, false)); make::use_(None, make::use_tree(make::join_paths(use_tree_str), None, None, false));
if let Some(item) = ast::Item::cast(use_.syntax().clone()) { let item = ast::Item::from(use_);
self.use_items.insert(0, item); self.use_items.insert(0, item);
}
} }
import_path_to_be_removed import_path_to_be_removed
@ -825,7 +812,6 @@ fn get_replacements_for_visibilty_change(
let mut impls = Vec::new(); let mut impls = Vec::new();
items.into_iter().for_each(|item| { items.into_iter().for_each(|item| {
let item = item;
if !is_clone_for_updated { if !is_clone_for_updated {
*item = item.clone_for_update(); *item = item.clone_for_update();
} }