Skip to content

Commit 50b79a9

Browse files
committed
Make search for applicable generics more precise
1 parent e565eec commit 50b79a9

File tree

1 file changed

+49
-18
lines changed

1 file changed

+49
-18
lines changed

crates/ide-assists/src/handlers/extract_function.rs

+49-18
Original file line numberDiff line numberDiff line change
@@ -823,8 +823,9 @@ impl FunctionBody {
823823
});
824824

825825
let parent = self.parent()?;
826-
let generic_param_lists = parent_generic_param_lists(&parent);
827-
let where_clauses = parent_where_clauses(&parent);
826+
let parents = generic_parents(&parent);
827+
let generic_param_lists = parents.iter().filter_map(|it| it.generic_param_list()).collect();
828+
let where_clauses = parents.iter().filter_map(|it| it.where_clause()).collect();
828829

829830
Some(ContainerInfo {
830831
is_in_tail,
@@ -990,24 +991,54 @@ impl FunctionBody {
990991
}
991992
}
992993

993-
fn parent_where_clauses(parent: &SyntaxNode) -> Vec<ast::WhereClause> {
994-
let mut where_clause: Vec<ast::WhereClause> = parent
995-
.ancestors()
996-
.filter_map(ast::AnyHasGenericParams::cast)
997-
.filter_map(|it| it.where_clause())
998-
.collect();
999-
where_clause.reverse();
1000-
where_clause
994+
enum GenericParent {
995+
Fn(ast::Fn),
996+
Impl(ast::Impl),
997+
Trait(ast::Trait),
1001998
}
1002999

1003-
fn parent_generic_param_lists(parent: &SyntaxNode) -> Vec<ast::GenericParamList> {
1004-
let mut generic_param_list: Vec<ast::GenericParamList> = parent
1005-
.ancestors()
1006-
.filter_map(ast::AnyHasGenericParams::cast)
1007-
.filter_map(|it| it.generic_param_list())
1008-
.collect();
1009-
generic_param_list.reverse();
1010-
generic_param_list
1000+
impl GenericParent {
1001+
fn generic_param_list(&self) -> Option<ast::GenericParamList> {
1002+
match self {
1003+
GenericParent::Fn(fn_) => fn_.generic_param_list(),
1004+
GenericParent::Impl(impl_) => impl_.generic_param_list(),
1005+
GenericParent::Trait(trait_) => trait_.generic_param_list(),
1006+
}
1007+
}
1008+
1009+
fn where_clause(&self) -> Option<ast::WhereClause> {
1010+
match self {
1011+
GenericParent::Fn(fn_) => fn_.where_clause(),
1012+
GenericParent::Impl(impl_) => impl_.where_clause(),
1013+
GenericParent::Trait(trait_) => trait_.where_clause(),
1014+
}
1015+
}
1016+
}
1017+
1018+
/// Search `parent`'s ancestors for items with potentially applicable generic parameters
1019+
fn generic_parents(parent: &SyntaxNode) -> Vec<GenericParent> {
1020+
let mut list = Vec::new();
1021+
if let Some(parent_item) = parent.ancestors().find_map(ast::Item::cast) {
1022+
match parent_item {
1023+
ast::Item::Fn(ref fn_) => {
1024+
if let Some(parent_parent) = parent_item
1025+
.syntax()
1026+
.parent()
1027+
.and_then(|it| it.parent())
1028+
.and_then(ast::Item::cast)
1029+
{
1030+
match parent_parent {
1031+
ast::Item::Impl(impl_) => list.push(GenericParent::Impl(impl_)),
1032+
ast::Item::Trait(trait_) => list.push(GenericParent::Trait(trait_)),
1033+
_ => (),
1034+
}
1035+
}
1036+
list.push(GenericParent::Fn(fn_.clone()));
1037+
}
1038+
_ => (),
1039+
}
1040+
}
1041+
list
10111042
}
10121043

10131044
/// checks if relevant var is used with `&mut` access inside body

0 commit comments

Comments
 (0)