Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs')
| -rw-r--r-- | crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs | 54 |
1 files changed, 25 insertions, 29 deletions
diff --git a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index f54f7a02d2..751cd42f6e 100644 --- a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -4,7 +4,7 @@ use itertools::Itertools; use syntax::{ SyntaxKind::WHITESPACE, T, - ast::{self, AstNode, HasName, syntax_factory::SyntaxFactory}, + ast::{self, AstNode, HasName}, syntax_editor::{Position, SyntaxEditor}, }; @@ -12,8 +12,8 @@ use crate::{ AssistConfig, AssistId, assist_context::{AssistContext, Assists}, utils::{ - DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl_with_factory, - filter_assoc_items, gen_trait_fn_body, generate_trait_impl, + DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl, filter_assoc_items, + gen_trait_fn_body, generate_trait_impl, generate_trait_impl_with_item, }, }; @@ -64,9 +64,10 @@ pub(crate) fn replace_derive_with_manual_impl( .filter_map(|attr| attr.path()) .collect::<Vec<_>>(); - let adt = value.parent().and_then(ast::Adt::cast)?; - let attr = ast::Attr::cast(value)?; - let args = attr.token_tree()?; + let attr = ast::Meta::cast(value)?.parent_attr()?; + let adt = attr.syntax().parent().and_then(ast::Adt::cast)?; + let ast::Meta::TokenTreeMeta(meta) = attr.meta()? else { return None }; + let args = meta.token_tree()?; let current_module = ctx.sema.scope(adt.syntax())?.module(); let current_crate = current_module.krate(ctx.db()); @@ -127,10 +128,12 @@ fn add_assist( let label = format!("Convert to manual `impl {replace_trait_path} for {annotated_name}`"); acc.add(AssistId::refactor("replace_derive_with_manual_impl"), label, target, |builder| { - let make = SyntaxFactory::without_mappings(); + let editor = builder.make_editor(attr.syntax()); + let make = editor.make(); let insert_after = Position::after(adt.syntax()); let impl_is_unsafe = trait_.map(|s| s.is_unsafe(ctx.db())).unwrap_or(false); let impl_def = impl_def_from_trait( + &editor, &ctx.sema, ctx.config, adt, @@ -139,9 +142,7 @@ fn add_assist( replace_trait_path, impl_is_unsafe, ); - - let mut editor = builder.make_editor(attr.syntax()); - update_attribute(&mut editor, old_derives, old_tree, old_trait_path, attr); + update_attribute(&editor, old_derives, old_tree, old_trait_path, attr); let trait_path = make.ty_path(replace_trait_path.clone()).into(); @@ -151,7 +152,7 @@ fn add_assist( impl_def.assoc_item_list().and_then(|list| list.assoc_items().next()), ) } else { - (generate_trait_impl(&make, impl_is_unsafe, adt, trait_path), None) + (generate_trait_impl(make, impl_is_unsafe, adt, trait_path), None) }; if let Some(cap) = ctx.config.snippet_cap { @@ -182,6 +183,7 @@ fn add_assist( } fn impl_def_from_trait( + editor: &SyntaxEditor, sema: &hir::Semantics<'_, ide_db::RootDatabase>, config: &AssistConfig, adt: &ast::Adt, @@ -190,6 +192,7 @@ fn impl_def_from_trait( trait_path: &ast::Path, impl_is_unsafe: bool, ) -> Option<ast::Impl> { + let make = editor.make(); let trait_ = trait_?; let target_scope = sema.scope(annotated_name.syntax())?; @@ -206,12 +209,11 @@ fn impl_def_from_trait( if trait_items.is_empty() { return None; } - let make = SyntaxFactory::without_mappings(); - let trait_ty = make.ty_path(trait_path.clone()).into(); - let impl_def = generate_trait_impl(&make, impl_is_unsafe, adt, trait_ty); + let trait_ty: ast::Type = make.ty_path(trait_path.clone()).into(); + let impl_def = generate_trait_impl(make, impl_is_unsafe, adt, trait_ty.clone()); - let assoc_items = add_trait_assoc_items_to_impl_with_factory( - &make, + let assoc_items = add_trait_assoc_items_to_impl( + make, sema, config, &trait_items, @@ -219,14 +221,12 @@ fn impl_def_from_trait( &impl_def, &target_scope, ); - let assoc_item_list = if let Some((first, other)) = - assoc_items.split_first().map(|(first, other)| (first.clone_subtree(), other)) - { - let first_item = if let ast::AssocItem::Fn(ref func) = first - && let Some(body) = gen_trait_fn_body(func, trait_path, adt, None) + let assoc_item_list = if let Some((first, other)) = assoc_items.split_first() { + let first_item = if let ast::AssocItem::Fn(func) = first + && let Some(body) = gen_trait_fn_body(make, func, trait_path, adt, None) && let Some(func_body) = func.body() { - let mut editor = SyntaxEditor::new(first.syntax().clone()); + let (editor, _) = SyntaxEditor::new(first.syntax().clone()); editor.replace(func_body.syntax(), body.syntax()); ast::AssocItem::cast(editor.finish().new_root().clone()) } else { @@ -239,21 +239,17 @@ fn impl_def_from_trait( make.assoc_item_list_empty() }; - let impl_def = impl_def.clone_subtree(); - let mut editor = SyntaxEditor::new(impl_def.syntax().clone()); - editor.replace(impl_def.assoc_item_list()?.syntax(), assoc_item_list.syntax()); - let impl_def = ast::Impl::cast(editor.finish().new_root().clone())?; - Some(impl_def) + Some(generate_trait_impl_with_item(make, impl_is_unsafe, adt, trait_ty, assoc_item_list)) } fn update_attribute( - editor: &mut SyntaxEditor, + editor: &SyntaxEditor, old_derives: &[ast::Path], old_tree: &ast::TokenTree, old_trait_path: &ast::Path, attr: &ast::Attr, ) { - let make = SyntaxFactory::without_mappings(); + let make = editor.make(); let new_derives = old_derives .iter() .filter(|t| t.to_string() != old_trait_path.to_string()) |