mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-29 05:14:18 +00:00
extract_module: Resolve imports lazily
This commit is contained in:
parent
031bdf2472
commit
1e71ac286b
1 changed files with 27 additions and 41 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue