Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/utils.rs')
-rw-r--r--crates/ide-assists/src/utils.rs140
1 files changed, 11 insertions, 129 deletions
diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs
index bf1062d207..8efc1bb230 100644
--- a/crates/ide-assists/src/utils.rs
+++ b/crates/ide-assists/src/utils.rs
@@ -536,15 +536,11 @@ pub(crate) fn generate_impl_with_item(
adt: &ast::Adt,
body: Option<ast::AssocItemList>,
) -> ast::Impl {
- generate_impl_inner_with_factory(make, false, adt, None, true, body)
+ generate_impl_inner(make, false, adt, None, true, body)
}
-pub(crate) fn generate_impl_with_factory(make: &SyntaxFactory, adt: &ast::Adt) -> ast::Impl {
- generate_impl_inner_with_factory(make, false, adt, None, true, None)
-}
-
-pub(crate) fn generate_impl(adt: &ast::Adt) -> ast::Impl {
- generate_impl_inner(false, adt, None, true, None)
+pub(crate) fn generate_impl(make: &SyntaxFactory, adt: &ast::Adt) -> ast::Impl {
+ generate_impl_inner(make, false, adt, None, true, None)
}
/// Generates the corresponding `impl <trait> for Type {}` including type
@@ -557,7 +553,7 @@ pub(crate) fn generate_trait_impl(
adt: &ast::Adt,
trait_: ast::Type,
) -> ast::Impl {
- generate_impl_inner_with_factory(make, is_unsafe, adt, Some(trait_), true, None)
+ generate_impl_inner(make, is_unsafe, adt, Some(trait_), true, None)
}
/// Generates the corresponding `impl <trait> for Type {}` including type
@@ -569,7 +565,7 @@ pub(crate) fn generate_trait_impl_intransitive(
adt: &ast::Adt,
trait_: ast::Type,
) -> ast::Impl {
- generate_impl_inner_with_factory(make, false, adt, Some(trait_), false, None)
+ generate_impl_inner(make, false, adt, Some(trait_), false, None)
}
pub(crate) fn generate_trait_impl_intransitive_with_item(
@@ -578,7 +574,7 @@ pub(crate) fn generate_trait_impl_intransitive_with_item(
trait_: ast::Type,
body: ast::AssocItemList,
) -> ast::Impl {
- generate_impl_inner_with_factory(make, false, adt, Some(trait_), false, Some(body))
+ generate_impl_inner(make, false, adt, Some(trait_), false, Some(body))
}
pub(crate) fn generate_trait_impl_with_item(
@@ -588,79 +584,10 @@ pub(crate) fn generate_trait_impl_with_item(
trait_: ast::Type,
body: ast::AssocItemList,
) -> ast::Impl {
- generate_impl_inner_with_factory(make, is_unsafe, adt, Some(trait_), true, Some(body))
+ generate_impl_inner(make, is_unsafe, adt, Some(trait_), true, Some(body))
}
fn generate_impl_inner(
- is_unsafe: bool,
- adt: &ast::Adt,
- trait_: Option<ast::Type>,
- trait_is_transitive: bool,
- body: Option<ast::AssocItemList>,
-) -> ast::Impl {
- // Ensure lifetime params are before type & const params
- let generic_params = adt.generic_param_list().map(|generic_params| {
- let lifetime_params =
- generic_params.lifetime_params().map(ast::GenericParam::LifetimeParam);
- let ty_or_const_params = generic_params.type_or_const_params().filter_map(|param| {
- let param = match param {
- ast::TypeOrConstParam::Type(param) => {
- // remove defaults since they can't be specified in impls
- let mut bounds =
- param.type_bound_list().map_or_else(Vec::new, |it| it.bounds().collect());
- if let Some(trait_) = &trait_ {
- // Add the current trait to `bounds` if the trait is transitive,
- // meaning `impl<T> Trait for U<T>` requires `T: Trait`.
- if trait_is_transitive {
- bounds.push(make::type_bound(trait_.clone()));
- }
- };
- // `{ty_param}: {bounds}`
- let param = make::type_param(param.name()?, make::type_bound_list(bounds));
- ast::GenericParam::TypeParam(param)
- }
- ast::TypeOrConstParam::Const(param) => {
- // remove defaults since they can't be specified in impls
- let param = make::const_param(param.name()?, param.ty()?);
- ast::GenericParam::ConstParam(param)
- }
- };
- Some(param)
- });
-
- make::generic_param_list(itertools::chain(lifetime_params, ty_or_const_params))
- });
- let generic_args =
- generic_params.as_ref().map(|params| params.to_generic_args().clone_for_update());
- let adt_assoc_bounds = trait_
- .as_ref()
- .zip(generic_params.as_ref())
- .and_then(|(trait_, params)| generic_param_associated_bounds(adt, trait_, params));
-
- let ty = make::ty_path(make::ext::ident_path(&adt.name().unwrap().text()));
-
- let cfg_attrs = adt.attrs().filter(|attr| matches!(attr.meta(), Some(ast::Meta::CfgMeta(_))));
- match trait_ {
- Some(trait_) => make::impl_trait(
- cfg_attrs,
- is_unsafe,
- None,
- None,
- generic_params,
- generic_args,
- false,
- trait_,
- ty,
- adt_assoc_bounds,
- adt.where_clause(),
- body,
- ),
- None => make::impl_(cfg_attrs, generic_params, generic_args, ty, adt.where_clause(), body),
- }
- .clone_for_update()
-}
-
-fn generate_impl_inner_with_factory(
make: &SyntaxFactory,
is_unsafe: bool,
adt: &ast::Adt,
@@ -702,10 +629,10 @@ fn generate_impl_inner_with_factory(
});
let generic_args =
generic_params.as_ref().map(|params| params.to_generic_args().clone_for_update());
- let adt_assoc_bounds =
- trait_.as_ref().zip(generic_params.as_ref()).and_then(|(trait_, params)| {
- generic_param_associated_bounds_with_factory(make, adt, trait_, params)
- });
+ let adt_assoc_bounds = trait_
+ .as_ref()
+ .zip(generic_params.as_ref())
+ .and_then(|(trait_, params)| generic_param_associated_bounds(make, adt, trait_, params));
let ty: ast::Type = make.ty_path(make.ident_path(&adt.name().unwrap().text())).into();
@@ -730,51 +657,6 @@ fn generate_impl_inner_with_factory(
}
fn generic_param_associated_bounds(
- adt: &ast::Adt,
- trait_: &ast::Type,
- generic_params: &ast::GenericParamList,
-) -> Option<ast::WhereClause> {
- let in_type_params = |name: &ast::NameRef| {
- generic_params
- .generic_params()
- .filter_map(|param| match param {
- ast::GenericParam::TypeParam(type_param) => type_param.name(),
- _ => None,
- })
- .any(|param| param.text() == name.text())
- };
- let adt_body = match adt {
- ast::Adt::Enum(e) => e.variant_list().map(|it| it.syntax().clone()),
- ast::Adt::Struct(s) => s.field_list().map(|it| it.syntax().clone()),
- ast::Adt::Union(u) => u.record_field_list().map(|it| it.syntax().clone()),
- };
- let mut trait_where_clause = adt_body
- .into_iter()
- .flat_map(|it| it.descendants())
- .filter_map(ast::Path::cast)
- .filter_map(|path| {
- let qualifier = path.qualifier()?.as_single_segment()?;
- let qualifier = qualifier
- .name_ref()
- .or_else(|| match qualifier.type_anchor()?.ty()? {
- ast::Type::PathType(path_type) => path_type.path()?.as_single_name_ref(),
- _ => None,
- })
- .filter(in_type_params)?;
- Some((qualifier, path.segment()?.name_ref()?))
- })
- .map(|(qualifier, assoc_name)| {
- let segments = [qualifier, assoc_name].map(make::path_segment);
- let path = make::path_from_segments(segments, false);
- let bounds = Some(make::type_bound(trait_.clone()));
- make::where_pred(either::Either::Right(make::ty_path(path)), bounds)
- })
- .unique_by(|it| it.syntax().to_string())
- .peekable();
- trait_where_clause.peek().is_some().then(|| make::where_clause(trait_where_clause))
-}
-
-fn generic_param_associated_bounds_with_factory(
make: &SyntaxFactory,
adt: &ast::Adt,
trait_: &ast::Type,