fix: simplify extract_module
This commit is contained in:
parent
e8182a5bb3
commit
9c8a57ed08
@ -16,7 +16,7 @@
|
|||||||
ast::{
|
ast::{
|
||||||
self,
|
self,
|
||||||
edit::{AstNodeEdit, IndentLevel},
|
edit::{AstNodeEdit, IndentLevel},
|
||||||
make, HasName, HasVisibility,
|
make, HasVisibility,
|
||||||
},
|
},
|
||||||
match_ast, ted, AstNode, SourceFile,
|
match_ast, ted, AstNode, SourceFile,
|
||||||
SyntaxKind::{self, WHITESPACE},
|
SyntaxKind::{self, WHITESPACE},
|
||||||
@ -134,16 +134,13 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
|
|||||||
let mut body = body_items.join("\n\n");
|
let mut body = body_items.join("\n\n");
|
||||||
|
|
||||||
if let Some(impl_) = &impl_parent {
|
if let Some(impl_) = &impl_parent {
|
||||||
let mut impl_body_def = String::new();
|
|
||||||
|
|
||||||
if let Some(self_ty) = impl_.self_ty() {
|
if let Some(self_ty) = impl_.self_ty() {
|
||||||
{
|
let impl_indent = old_item_indent + 1;
|
||||||
let impl_indent = old_item_indent + 1;
|
let mut impl_body_def = String::new();
|
||||||
format_to!(
|
format_to!(
|
||||||
impl_body_def,
|
impl_body_def,
|
||||||
"{impl_indent}impl {self_ty} {{\n{body}\n{impl_indent}}}",
|
"{impl_indent}impl {self_ty} {{\n{body}\n{impl_indent}}}",
|
||||||
);
|
);
|
||||||
}
|
|
||||||
body = impl_body_def;
|
body = impl_body_def;
|
||||||
|
|
||||||
// Add the import for enum/struct corresponding to given impl block
|
// Add the import for enum/struct corresponding to given impl block
|
||||||
@ -156,7 +153,6 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut module_def = String::new();
|
let mut module_def = String::new();
|
||||||
|
|
||||||
let module_name = module.name;
|
let module_name = module.name;
|
||||||
format_to!(module_def, "mod {module_name} {{\n{body}\n{old_item_indent}}}");
|
format_to!(module_def, "mod {module_name} {{\n{body}\n{old_item_indent}}}");
|
||||||
|
|
||||||
@ -177,10 +173,6 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
|
|||||||
builder.replace(usage_to_be_processed.0, usage_to_be_processed.1)
|
builder.replace(usage_to_be_processed.0, usage_to_be_processed.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
for import_path_text_range in import_paths_to_be_removed {
|
|
||||||
builder.delete(import_path_text_range);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(impl_) = impl_parent {
|
if let Some(impl_) = impl_parent {
|
||||||
// Remove complete impl block if it has only one child (as such it will be empty
|
// Remove complete impl block if it has only one child (as such it will be empty
|
||||||
// after deleting that child)
|
// after deleting that child)
|
||||||
@ -199,6 +191,14 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
|
|||||||
|
|
||||||
builder.insert(impl_.syntax().text_range().end(), format!("\n\n{module_def}"));
|
builder.insert(impl_.syntax().text_range().end(), format!("\n\n{module_def}"));
|
||||||
} else {
|
} else {
|
||||||
|
for import_path_text_range in import_paths_to_be_removed {
|
||||||
|
if module.text_range.intersect(import_path_text_range).is_some() {
|
||||||
|
module.text_range = module.text_range.cover(import_path_text_range);
|
||||||
|
} else {
|
||||||
|
builder.delete(import_path_text_range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
builder.replace(module.text_range, module_def)
|
builder.replace(module.text_range, module_def)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -394,78 +394,43 @@ fn change_visibility(&mut self, record_fields: Vec<SyntaxNode>) {
|
|||||||
|
|
||||||
fn resolve_imports(
|
fn resolve_imports(
|
||||||
&mut self,
|
&mut self,
|
||||||
curr_parent_module: Option<ast::Module>,
|
module: Option<ast::Module>,
|
||||||
ctx: &AssistContext<'_>,
|
ctx: &AssistContext<'_>,
|
||||||
) -> Vec<TextRange> {
|
) -> Vec<TextRange> {
|
||||||
let mut import_paths_to_be_removed: Vec<TextRange> = vec![];
|
let mut imports_to_remove = vec![];
|
||||||
let mut node_set: FxHashSet<String> = FxHashSet::default();
|
let mut node_set = FxHashSet::default();
|
||||||
|
|
||||||
for item in self.body_items.clone() {
|
for item in self.body_items.clone() {
|
||||||
for x in item.syntax().descendants() {
|
item.syntax()
|
||||||
if let Some(name) = ast::Name::cast(x.clone()) {
|
.descendants()
|
||||||
if let Some(name_classify) = NameClass::classify(&ctx.sema, &name) {
|
.filter_map(|x| {
|
||||||
//Necessary to avoid two same names going through
|
if let Some(name) = ast::Name::cast(x.clone()) {
|
||||||
if !node_set.contains(&name.syntax().to_string()) {
|
NameClass::classify(&ctx.sema, &name).and_then(|nc| match nc {
|
||||||
node_set.insert(name.syntax().to_string());
|
NameClass::Definition(def) => Some((name.syntax().clone(), def)),
|
||||||
let def_opt: Option<Definition> = match name_classify {
|
_ => None,
|
||||||
NameClass::Definition(def) => Some(def),
|
})
|
||||||
_ => None,
|
} else if let Some(name_ref) = ast::NameRef::cast(x) {
|
||||||
};
|
NameRefClass::classify(&ctx.sema, &name_ref).and_then(|nc| match nc {
|
||||||
|
NameRefClass::Definition(def) => Some((name_ref.syntax().clone(), def)),
|
||||||
if let Some(def) = def_opt {
|
_ => None,
|
||||||
if let Some(import_path) = self
|
})
|
||||||
.process_names_and_namerefs_for_import_resolve(
|
} else {
|
||||||
def,
|
None
|
||||||
name.syntax(),
|
}
|
||||||
&curr_parent_module,
|
})
|
||||||
ctx,
|
.for_each(|(node, def)| {
|
||||||
)
|
if node_set.insert(node.to_string()) {
|
||||||
{
|
if let Some(import) = self.process_def_in_sel(def, &node, &module, ctx) {
|
||||||
check_intersection_and_push(
|
check_intersection_and_push(&mut imports_to_remove, import);
|
||||||
&mut import_paths_to_be_removed,
|
|
||||||
import_path,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
if let Some(name_ref) = ast::NameRef::cast(x) {
|
|
||||||
if let Some(name_classify) = NameRefClass::classify(&ctx.sema, &name_ref) {
|
|
||||||
//Necessary to avoid two same names going through
|
|
||||||
if !node_set.contains(&name_ref.syntax().to_string()) {
|
|
||||||
node_set.insert(name_ref.syntax().to_string());
|
|
||||||
let def_opt: Option<Definition> = match name_classify {
|
|
||||||
NameRefClass::Definition(def) => Some(def),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(def) = def_opt {
|
|
||||||
if let Some(import_path) = self
|
|
||||||
.process_names_and_namerefs_for_import_resolve(
|
|
||||||
def,
|
|
||||||
name_ref.syntax(),
|
|
||||||
&curr_parent_module,
|
|
||||||
ctx,
|
|
||||||
)
|
|
||||||
{
|
|
||||||
check_intersection_and_push(
|
|
||||||
&mut import_paths_to_be_removed,
|
|
||||||
import_path,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
import_paths_to_be_removed
|
imports_to_remove
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_names_and_namerefs_for_import_resolve(
|
fn process_def_in_sel(
|
||||||
&mut self,
|
&mut self,
|
||||||
def: Definition,
|
def: Definition,
|
||||||
node_syntax: &SyntaxNode,
|
node_syntax: &SyntaxNode,
|
||||||
@ -474,51 +439,38 @@ fn process_names_and_namerefs_for_import_resolve(
|
|||||||
) -> Option<TextRange> {
|
) -> Option<TextRange> {
|
||||||
//We only need to find in the current file
|
//We only need to find in the current file
|
||||||
let selection_range = ctx.selection_trimmed();
|
let selection_range = ctx.selection_trimmed();
|
||||||
let curr_file_id = ctx.file_id();
|
let file_id = ctx.file_id();
|
||||||
let search_scope = SearchScope::single_file(curr_file_id);
|
let usage_res = def.usages(&ctx.sema).in_scope(&SearchScope::single_file(file_id)).all();
|
||||||
let usage_res = def.usages(&ctx.sema).in_scope(&search_scope).all();
|
let file = ctx.sema.parse(file_id);
|
||||||
let file = ctx.sema.parse(curr_file_id);
|
|
||||||
|
|
||||||
|
// track uses which does not exists in `Use`
|
||||||
let mut exists_inside_sel = false;
|
let mut exists_inside_sel = false;
|
||||||
let mut exists_outside_sel = false;
|
let mut exists_outside_sel = false;
|
||||||
for (_, refs) in usage_res.iter() {
|
'outside: for (_, refs) in usage_res.iter() {
|
||||||
let mut non_use_nodes_itr = refs.iter().filter_map(|x| {
|
for x in refs
|
||||||
if find_node_at_range::<ast::Use>(file.syntax(), x.range).is_none() {
|
.iter()
|
||||||
let path_opt = find_node_at_range::<ast::Path>(file.syntax(), x.range);
|
.filter(|x| find_node_at_range::<ast::Use>(file.syntax(), x.range).is_none())
|
||||||
return path_opt;
|
.filter_map(|x| find_node_at_range::<ast::Path>(file.syntax(), x.range))
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
});
|
|
||||||
|
|
||||||
if non_use_nodes_itr
|
|
||||||
.clone()
|
|
||||||
.any(|x| !selection_range.contains_range(x.syntax().text_range()))
|
|
||||||
{
|
{
|
||||||
exists_outside_sel = true;
|
let in_selectin = selection_range.contains_range(x.syntax().text_range());
|
||||||
}
|
exists_inside_sel |= in_selectin;
|
||||||
if non_use_nodes_itr.any(|x| selection_range.contains_range(x.syntax().text_range())) {
|
exists_outside_sel |= !in_selectin;
|
||||||
exists_inside_sel = true;
|
|
||||||
|
if exists_inside_sel && exists_outside_sel {
|
||||||
|
break 'outside;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let source_exists_outside_sel_in_same_mod = does_source_exists_outside_sel_in_same_mod(
|
let def_in_mod_and_out_sel =
|
||||||
def,
|
check_def_in_mod_and_out_sel(def, ctx, curr_parent_module, selection_range, file_id);
|
||||||
ctx,
|
|
||||||
curr_parent_module,
|
|
||||||
selection_range,
|
|
||||||
curr_file_id,
|
|
||||||
);
|
|
||||||
|
|
||||||
let use_stmt_opt: Option<ast::Use> = usage_res.into_iter().find_map(|(file_id, refs)| {
|
// Find use stmt that use def in current file
|
||||||
if file_id == curr_file_id {
|
let use_stmt: Option<ast::Use> = usage_res
|
||||||
refs.into_iter()
|
.into_iter()
|
||||||
.rev()
|
.filter(|(use_file_id, _)| *use_file_id == file_id)
|
||||||
.find_map(|fref| find_node_at_range(file.syntax(), fref.range))
|
.flat_map(|(_, refs)| refs.into_iter().rev())
|
||||||
} else {
|
.find_map(|fref| find_node_at_range(file.syntax(), fref.range));
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut use_tree_str_opt: Option<Vec<ast::Path>> = None;
|
let mut use_tree_str_opt: Option<Vec<ast::Path>> = None;
|
||||||
//Exists inside and outside selection
|
//Exists inside and outside selection
|
||||||
@ -539,32 +491,32 @@ fn process_names_and_namerefs_for_import_resolve(
|
|||||||
|
|
||||||
//If use_stmt exists, find the use_tree_str, reconstruct it inside new module
|
//If use_stmt exists, find the use_tree_str, reconstruct it inside new module
|
||||||
//If not, insert a use stmt with super and the given nameref
|
//If not, insert a use stmt with super and the given nameref
|
||||||
if let Some((use_tree_str, _)) =
|
match self.process_use_stmt_for_import_resolve(use_stmt, node_syntax) {
|
||||||
self.process_use_stmt_for_import_resolve(use_stmt_opt, node_syntax)
|
Some((use_tree_str, _)) => use_tree_str_opt = Some(use_tree_str),
|
||||||
{
|
None if def_in_mod_and_out_sel => {
|
||||||
use_tree_str_opt = Some(use_tree_str);
|
//Considered only after use_stmt is not present
|
||||||
} else if source_exists_outside_sel_in_same_mod {
|
//def_in_mod_and_out_sel | exists_outside_sel(exists_inside_sel =
|
||||||
//Considered only after use_stmt is not present
|
//true for all cases)
|
||||||
//source_exists_outside_sel_in_same_mod | exists_outside_sel(exists_inside_sel =
|
// false | false -> Do nothing
|
||||||
//true for all cases)
|
// false | true -> If source is in selection -> nothing to do, If source is outside
|
||||||
// false | false -> Do nothing
|
// mod -> ust_stmt transversal
|
||||||
// false | true -> If source is in selection -> nothing to do, If source is outside
|
// true | false -> super import insertion
|
||||||
// mod -> ust_stmt transversal
|
// true | true -> super import insertion
|
||||||
// true | false -> super import insertion
|
self.make_use_stmt_of_node_with_super(node_syntax);
|
||||||
// true | true -> super import insertion
|
}
|
||||||
self.make_use_stmt_of_node_with_super(node_syntax);
|
None => {}
|
||||||
}
|
}
|
||||||
} else if exists_inside_sel && !exists_outside_sel {
|
} else if exists_inside_sel && !exists_outside_sel {
|
||||||
//Changes to be made inside new module, and remove import from outside
|
//Changes to be made inside new module, and remove import from outside
|
||||||
|
|
||||||
if let Some((mut use_tree_str, text_range_opt)) =
|
if let Some((mut use_tree_str, text_range_opt)) =
|
||||||
self.process_use_stmt_for_import_resolve(use_stmt_opt, node_syntax)
|
self.process_use_stmt_for_import_resolve(use_stmt, node_syntax)
|
||||||
{
|
{
|
||||||
if let Some(text_range) = text_range_opt {
|
if let Some(text_range) = text_range_opt {
|
||||||
import_path_to_be_removed = Some(text_range);
|
import_path_to_be_removed = Some(text_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
if source_exists_outside_sel_in_same_mod {
|
if def_in_mod_and_out_sel {
|
||||||
if let Some(first_path_in_use_tree) = use_tree_str.last() {
|
if let Some(first_path_in_use_tree) = use_tree_str.last() {
|
||||||
let first_path_in_use_tree_str = first_path_in_use_tree.to_string();
|
let first_path_in_use_tree_str = first_path_in_use_tree.to_string();
|
||||||
if !first_path_in_use_tree_str.contains("super")
|
if !first_path_in_use_tree_str.contains("super")
|
||||||
@ -577,7 +529,7 @@ fn process_names_and_namerefs_for_import_resolve(
|
|||||||
}
|
}
|
||||||
|
|
||||||
use_tree_str_opt = Some(use_tree_str);
|
use_tree_str_opt = Some(use_tree_str);
|
||||||
} else if source_exists_outside_sel_in_same_mod {
|
} else if def_in_mod_and_out_sel {
|
||||||
self.make_use_stmt_of_node_with_super(node_syntax);
|
self.make_use_stmt_of_node_with_super(node_syntax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -586,13 +538,10 @@ fn process_names_and_namerefs_for_import_resolve(
|
|||||||
let mut use_tree_str = use_tree_str;
|
let mut use_tree_str = use_tree_str;
|
||||||
use_tree_str.reverse();
|
use_tree_str.reverse();
|
||||||
|
|
||||||
if !(!exists_outside_sel && exists_inside_sel && source_exists_outside_sel_in_same_mod)
|
if exists_outside_sel || !exists_inside_sel || !def_in_mod_and_out_sel {
|
||||||
{
|
|
||||||
if let Some(first_path_in_use_tree) = use_tree_str.first() {
|
if let Some(first_path_in_use_tree) = use_tree_str.first() {
|
||||||
let first_path_in_use_tree_str = first_path_in_use_tree.to_string();
|
if first_path_in_use_tree.to_string().contains("super") {
|
||||||
if first_path_in_use_tree_str.contains("super") {
|
use_tree_str.insert(0, make::ext::ident_path("super"));
|
||||||
let super_path = make::ext::ident_path("super");
|
|
||||||
use_tree_str.insert(0, super_path)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -621,33 +570,26 @@ fn make_use_stmt_of_node_with_super(&mut self, node_syntax: &SyntaxNode) -> ast:
|
|||||||
|
|
||||||
fn process_use_stmt_for_import_resolve(
|
fn process_use_stmt_for_import_resolve(
|
||||||
&self,
|
&self,
|
||||||
use_stmt_opt: Option<ast::Use>,
|
use_stmt: Option<ast::Use>,
|
||||||
node_syntax: &SyntaxNode,
|
node_syntax: &SyntaxNode,
|
||||||
) -> Option<(Vec<ast::Path>, Option<TextRange>)> {
|
) -> Option<(Vec<ast::Path>, Option<TextRange>)> {
|
||||||
if let Some(use_stmt) = use_stmt_opt {
|
let use_stmt = use_stmt?;
|
||||||
for desc in use_stmt.syntax().descendants() {
|
for path_seg in use_stmt.syntax().descendants().filter_map(ast::PathSegment::cast) {
|
||||||
if let Some(path_seg) = ast::PathSegment::cast(desc) {
|
if path_seg.syntax().to_string() == node_syntax.to_string() {
|
||||||
if path_seg.syntax().to_string() == node_syntax.to_string() {
|
let mut use_tree_str = vec![path_seg.parent_path()];
|
||||||
let mut use_tree_str = vec![path_seg.parent_path()];
|
get_use_tree_paths_from_path(path_seg.parent_path(), &mut use_tree_str);
|
||||||
get_use_tree_paths_from_path(path_seg.parent_path(), &mut use_tree_str);
|
|
||||||
for ancs in path_seg.syntax().ancestors() {
|
|
||||||
//Here we are looking for use_tree with same string value as node
|
|
||||||
//passed above as the range_to_remove function looks for a comma and
|
|
||||||
//then includes it in the text range to remove it. But the comma only
|
|
||||||
//appears at the use_tree level
|
|
||||||
if let Some(use_tree) = ast::UseTree::cast(ancs) {
|
|
||||||
if use_tree.syntax().to_string() == node_syntax.to_string() {
|
|
||||||
return Some((
|
|
||||||
use_tree_str,
|
|
||||||
Some(range_to_remove(use_tree.syntax())),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Some((use_tree_str, None));
|
//Here we are looking for use_tree with same string value as node
|
||||||
|
//passed above as the range_to_remove function looks for a comma and
|
||||||
|
//then includes it in the text range to remove it. But the comma only
|
||||||
|
//appears at the use_tree level
|
||||||
|
for use_tree in path_seg.syntax().ancestors().filter_map(ast::UseTree::cast) {
|
||||||
|
if use_tree.syntax().to_string() == node_syntax.to_string() {
|
||||||
|
return Some((use_tree_str, Some(range_to_remove(use_tree.syntax()))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Some((use_tree_str, None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -676,145 +618,56 @@ fn check_intersection_and_push(
|
|||||||
import_paths_to_be_removed.push(import_path);
|
import_paths_to_be_removed.push(import_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn does_source_exists_outside_sel_in_same_mod(
|
fn check_def_in_mod_and_out_sel(
|
||||||
def: Definition,
|
def: Definition,
|
||||||
ctx: &AssistContext<'_>,
|
ctx: &AssistContext<'_>,
|
||||||
curr_parent_module: &Option<ast::Module>,
|
curr_parent_module: &Option<ast::Module>,
|
||||||
selection_range: TextRange,
|
selection_range: TextRange,
|
||||||
curr_file_id: FileId,
|
curr_file_id: FileId,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut source_exists_outside_sel_in_same_mod = false;
|
macro_rules! check_item {
|
||||||
|
($x:ident) => {
|
||||||
|
if let Some(source) = $x.source(ctx.db()) {
|
||||||
|
let have_same_parent = if let Some(ast_module) = &curr_parent_module {
|
||||||
|
ctx.sema.to_module_def(ast_module).is_some_and(|it| it == $x.module(ctx.db()))
|
||||||
|
} else {
|
||||||
|
source.file_id.original_file(ctx.db()) == curr_file_id
|
||||||
|
};
|
||||||
|
|
||||||
|
if have_same_parent {
|
||||||
|
return !selection_range.contains_range(source.value.syntax().text_range());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
match def {
|
match def {
|
||||||
Definition::Module(x) => {
|
Definition::Module(x) => {
|
||||||
let source = x.definition_source(ctx.db());
|
let source = x.definition_source(ctx.db());
|
||||||
let have_same_parent = if let Some(ast_module) = &curr_parent_module {
|
let have_same_parent = match (&curr_parent_module, x.parent(ctx.db())) {
|
||||||
if let Some(hir_module) = x.parent(ctx.db()) {
|
(Some(ast_module), Some(hir_module)) => {
|
||||||
compare_hir_and_ast_module(ast_module, hir_module, ctx).is_some()
|
ctx.sema.to_module_def(ast_module).is_some_and(|it| it == hir_module)
|
||||||
} else {
|
|
||||||
let source_file_id = source.file_id.original_file(ctx.db());
|
|
||||||
source_file_id == curr_file_id
|
|
||||||
}
|
}
|
||||||
} else {
|
_ => source.file_id.original_file(ctx.db()) == curr_file_id,
|
||||||
let source_file_id = source.file_id.original_file(ctx.db());
|
|
||||||
source_file_id == curr_file_id
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if have_same_parent {
|
if have_same_parent {
|
||||||
if let ModuleSource::Module(module_) = source.value {
|
if let ModuleSource::Module(module_) = source.value {
|
||||||
source_exists_outside_sel_in_same_mod =
|
return !selection_range.contains_range(module_.syntax().text_range());
|
||||||
!selection_range.contains_range(module_.syntax().text_range());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Definition::Function(x) => {
|
|
||||||
if let Some(source) = x.source(ctx.db()) {
|
|
||||||
let have_same_parent = if let Some(ast_module) = &curr_parent_module {
|
|
||||||
compare_hir_and_ast_module(ast_module, x.module(ctx.db()), ctx).is_some()
|
|
||||||
} else {
|
|
||||||
let source_file_id = source.file_id.original_file(ctx.db());
|
|
||||||
source_file_id == curr_file_id
|
|
||||||
};
|
|
||||||
|
|
||||||
if have_same_parent {
|
|
||||||
source_exists_outside_sel_in_same_mod =
|
|
||||||
!selection_range.contains_range(source.value.syntax().text_range());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Definition::Adt(x) => {
|
|
||||||
if let Some(source) = x.source(ctx.db()) {
|
|
||||||
let have_same_parent = if let Some(ast_module) = &curr_parent_module {
|
|
||||||
compare_hir_and_ast_module(ast_module, x.module(ctx.db()), ctx).is_some()
|
|
||||||
} else {
|
|
||||||
let source_file_id = source.file_id.original_file(ctx.db());
|
|
||||||
source_file_id == curr_file_id
|
|
||||||
};
|
|
||||||
|
|
||||||
if have_same_parent {
|
|
||||||
source_exists_outside_sel_in_same_mod =
|
|
||||||
!selection_range.contains_range(source.value.syntax().text_range());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Definition::Variant(x) => {
|
|
||||||
if let Some(source) = x.source(ctx.db()) {
|
|
||||||
let have_same_parent = if let Some(ast_module) = &curr_parent_module {
|
|
||||||
compare_hir_and_ast_module(ast_module, x.module(ctx.db()), ctx).is_some()
|
|
||||||
} else {
|
|
||||||
let source_file_id = source.file_id.original_file(ctx.db());
|
|
||||||
source_file_id == curr_file_id
|
|
||||||
};
|
|
||||||
|
|
||||||
if have_same_parent {
|
|
||||||
source_exists_outside_sel_in_same_mod =
|
|
||||||
!selection_range.contains_range(source.value.syntax().text_range());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Definition::Const(x) => {
|
|
||||||
if let Some(source) = x.source(ctx.db()) {
|
|
||||||
let have_same_parent = if let Some(ast_module) = &curr_parent_module {
|
|
||||||
compare_hir_and_ast_module(ast_module, x.module(ctx.db()), ctx).is_some()
|
|
||||||
} else {
|
|
||||||
let source_file_id = source.file_id.original_file(ctx.db());
|
|
||||||
source_file_id == curr_file_id
|
|
||||||
};
|
|
||||||
|
|
||||||
if have_same_parent {
|
|
||||||
source_exists_outside_sel_in_same_mod =
|
|
||||||
!selection_range.contains_range(source.value.syntax().text_range());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Definition::Static(x) => {
|
|
||||||
if let Some(source) = x.source(ctx.db()) {
|
|
||||||
let have_same_parent = if let Some(ast_module) = &curr_parent_module {
|
|
||||||
compare_hir_and_ast_module(ast_module, x.module(ctx.db()), ctx).is_some()
|
|
||||||
} else {
|
|
||||||
let source_file_id = source.file_id.original_file(ctx.db());
|
|
||||||
source_file_id == curr_file_id
|
|
||||||
};
|
|
||||||
|
|
||||||
if have_same_parent {
|
|
||||||
source_exists_outside_sel_in_same_mod =
|
|
||||||
!selection_range.contains_range(source.value.syntax().text_range());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Definition::Trait(x) => {
|
|
||||||
if let Some(source) = x.source(ctx.db()) {
|
|
||||||
let have_same_parent = if let Some(ast_module) = &curr_parent_module {
|
|
||||||
compare_hir_and_ast_module(ast_module, x.module(ctx.db()), ctx).is_some()
|
|
||||||
} else {
|
|
||||||
let source_file_id = source.file_id.original_file(ctx.db());
|
|
||||||
source_file_id == curr_file_id
|
|
||||||
};
|
|
||||||
|
|
||||||
if have_same_parent {
|
|
||||||
source_exists_outside_sel_in_same_mod =
|
|
||||||
!selection_range.contains_range(source.value.syntax().text_range());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Definition::TypeAlias(x) => {
|
|
||||||
if let Some(source) = x.source(ctx.db()) {
|
|
||||||
let have_same_parent = if let Some(ast_module) = &curr_parent_module {
|
|
||||||
compare_hir_and_ast_module(ast_module, x.module(ctx.db()), ctx).is_some()
|
|
||||||
} else {
|
|
||||||
let source_file_id = source.file_id.original_file(ctx.db());
|
|
||||||
source_file_id == curr_file_id
|
|
||||||
};
|
|
||||||
|
|
||||||
if have_same_parent {
|
|
||||||
source_exists_outside_sel_in_same_mod =
|
|
||||||
!selection_range.contains_range(source.value.syntax().text_range());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Definition::Function(x) => check_item!(x),
|
||||||
|
Definition::Adt(x) => check_item!(x),
|
||||||
|
Definition::Variant(x) => check_item!(x),
|
||||||
|
Definition::Const(x) => check_item!(x),
|
||||||
|
Definition::Static(x) => check_item!(x),
|
||||||
|
Definition::Trait(x) => check_item!(x),
|
||||||
|
Definition::TypeAlias(x) => check_item!(x),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
source_exists_outside_sel_in_same_mod
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_replacements_for_visibility_change(
|
fn get_replacements_for_visibility_change(
|
||||||
@ -834,24 +687,30 @@ fn get_replacements_for_visibility_change(
|
|||||||
*item = item.clone_for_update();
|
*item = item.clone_for_update();
|
||||||
}
|
}
|
||||||
//Use stmts are ignored
|
//Use stmts are ignored
|
||||||
|
macro_rules! push_to_replacement {
|
||||||
|
($it:ident) => {
|
||||||
|
replacements.push(($it.visibility(), $it.syntax().clone()))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
match item {
|
match item {
|
||||||
ast::Item::Const(it) => replacements.push((it.visibility(), it.syntax().clone())),
|
ast::Item::Const(it) => push_to_replacement!(it),
|
||||||
ast::Item::Enum(it) => replacements.push((it.visibility(), it.syntax().clone())),
|
ast::Item::Enum(it) => push_to_replacement!(it),
|
||||||
ast::Item::ExternCrate(it) => replacements.push((it.visibility(), it.syntax().clone())),
|
ast::Item::ExternCrate(it) => push_to_replacement!(it),
|
||||||
ast::Item::Fn(it) => replacements.push((it.visibility(), it.syntax().clone())),
|
ast::Item::Fn(it) => push_to_replacement!(it),
|
||||||
//Associated item's visibility should not be changed
|
//Associated item's visibility should not be changed
|
||||||
ast::Item::Impl(it) if it.for_token().is_none() => impls.push(it.clone()),
|
ast::Item::Impl(it) if it.for_token().is_none() => impls.push(it.clone()),
|
||||||
ast::Item::MacroDef(it) => replacements.push((it.visibility(), it.syntax().clone())),
|
ast::Item::MacroDef(it) => push_to_replacement!(it),
|
||||||
ast::Item::Module(it) => replacements.push((it.visibility(), it.syntax().clone())),
|
ast::Item::Module(it) => push_to_replacement!(it),
|
||||||
ast::Item::Static(it) => replacements.push((it.visibility(), it.syntax().clone())),
|
ast::Item::Static(it) => push_to_replacement!(it),
|
||||||
ast::Item::Struct(it) => {
|
ast::Item::Struct(it) => {
|
||||||
replacements.push((it.visibility(), it.syntax().clone()));
|
push_to_replacement!(it);
|
||||||
record_field_parents.push((it.visibility(), it.syntax().clone()));
|
record_field_parents.push((it.visibility(), it.syntax().clone()));
|
||||||
}
|
}
|
||||||
ast::Item::Trait(it) => replacements.push((it.visibility(), it.syntax().clone())),
|
ast::Item::Trait(it) => push_to_replacement!(it),
|
||||||
ast::Item::TypeAlias(it) => replacements.push((it.visibility(), it.syntax().clone())),
|
ast::Item::TypeAlias(it) => push_to_replacement!(it),
|
||||||
ast::Item::Union(it) => {
|
ast::Item::Union(it) => {
|
||||||
replacements.push((it.visibility(), it.syntax().clone()));
|
push_to_replacement!(it);
|
||||||
record_field_parents.push((it.visibility(), it.syntax().clone()));
|
record_field_parents.push((it.visibility(), it.syntax().clone()));
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
@ -865,8 +724,11 @@ fn get_use_tree_paths_from_path(
|
|||||||
path: ast::Path,
|
path: ast::Path,
|
||||||
use_tree_str: &mut Vec<ast::Path>,
|
use_tree_str: &mut Vec<ast::Path>,
|
||||||
) -> Option<&mut Vec<ast::Path>> {
|
) -> Option<&mut Vec<ast::Path>> {
|
||||||
path.syntax().ancestors().filter(|x| x.to_string() != path.to_string()).find_map(|x| {
|
path.syntax()
|
||||||
if let Some(use_tree) = ast::UseTree::cast(x) {
|
.ancestors()
|
||||||
|
.filter(|x| x.to_string() != path.to_string())
|
||||||
|
.filter_map(ast::UseTree::cast)
|
||||||
|
.find_map(|use_tree| {
|
||||||
if let Some(upper_tree_path) = use_tree.path() {
|
if let Some(upper_tree_path) = use_tree.path() {
|
||||||
if upper_tree_path.to_string() != path.to_string() {
|
if upper_tree_path.to_string() != path.to_string() {
|
||||||
use_tree_str.push(upper_tree_path.clone());
|
use_tree_str.push(upper_tree_path.clone());
|
||||||
@ -874,9 +736,8 @@ fn get_use_tree_paths_from_path(
|
|||||||
return Some(use_tree);
|
return Some(use_tree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
None
|
||||||
None
|
})?;
|
||||||
})?;
|
|
||||||
|
|
||||||
Some(use_tree_str)
|
Some(use_tree_str)
|
||||||
}
|
}
|
||||||
@ -890,20 +751,6 @@ fn add_change_vis(vis: Option<ast::Visibility>, node_or_token_opt: Option<syntax
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compare_hir_and_ast_module(
|
|
||||||
ast_module: &ast::Module,
|
|
||||||
hir_module: hir::Module,
|
|
||||||
ctx: &AssistContext<'_>,
|
|
||||||
) -> Option<()> {
|
|
||||||
let hir_mod_name = hir_module.name(ctx.db())?;
|
|
||||||
let ast_mod_name = ast_module.name()?;
|
|
||||||
if hir_mod_name.display(ctx.db()).to_string() != ast_mod_name.to_string() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn indent_range_before_given_node(node: &SyntaxNode) -> Option<TextRange> {
|
fn indent_range_before_given_node(node: &SyntaxNode) -> Option<TextRange> {
|
||||||
node.siblings_with_tokens(syntax::Direction::Prev)
|
node.siblings_with_tokens(syntax::Direction::Prev)
|
||||||
.find(|x| x.kind() == WHITESPACE)
|
.find(|x| x.kind() == WHITESPACE)
|
||||||
@ -1799,6 +1646,33 @@ pub(crate) struct S {
|
|||||||
pub(crate) condvar: B,
|
pub(crate) condvar: B,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_remove_import_path_inside_selection() {
|
||||||
|
check_assist(
|
||||||
|
extract_module,
|
||||||
|
r#"
|
||||||
|
$0struct Point;
|
||||||
|
impl Point {
|
||||||
|
pub const fn direction(self, other: Self) -> Option<Direction> {
|
||||||
|
Some(Vertical)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Direction {
|
||||||
|
Horizontal,
|
||||||
|
Vertical,
|
||||||
|
}
|
||||||
|
use Direction::{Horizontal, Vertical};$0
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = Vertical;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user