diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs index 7f1e7ccb44..11201afb8a 100644 --- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -183,13 +183,11 @@ fn add_missing_impl_members_inner( .clone() .into_iter() .chain(other_items.iter().cloned()) - .map(either::Either::Right) .collect::>(); let mut editor = edit.make_editor(impl_def.syntax()); if let Some(assoc_item_list) = impl_def.assoc_item_list() { - let items = new_assoc_items.into_iter().filter_map(either::Either::right).collect(); - assoc_item_list.add_items(&mut editor, items); + assoc_item_list.add_items(&mut editor, new_assoc_items); } else { let assoc_item_list = make::assoc_item_list(Some(new_assoc_items)).clone_for_update(); editor.insert_all( diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs index 6063898076..2c81e2883a 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -2,9 +2,11 @@ use hir::{HasCrate, HasVisibility}; use ide_db::{FxHashSet, path_transform::PathTransform}; use syntax::{ ast::{ - self, AstNode, HasGenericParams, HasName, HasVisibility as _, edit_in_place::Indent, make, + self, AstNode, HasGenericParams, HasName, HasVisibility as _, + edit::{AstNodeEdit, IndentLevel}, + make, }, - ted, + syntax_editor::Position, }; use crate::{ @@ -165,54 +167,66 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' is_unsafe, is_gen, ) - .clone_for_update(); + .indent(IndentLevel(1)); + let item = ast::AssocItem::Fn(f.clone()); - // Get the impl to update, or create one if we need to. - let impl_def = match impl_def { - Some(impl_def) => edit.make_mut(impl_def), + let mut editor = edit.make_editor(strukt.syntax()); + let fn_: Option = match impl_def { + Some(impl_def) => match impl_def.assoc_item_list() { + Some(assoc_item_list) => { + let item = item.indent(IndentLevel::from_node(impl_def.syntax())); + assoc_item_list.add_items(&mut editor, vec![item.clone()]); + Some(item) + } + None => { + let assoc_item_list = make::assoc_item_list(Some(vec![item])); + editor.insert( + Position::last_child_of(impl_def.syntax()), + assoc_item_list.syntax(), + ); + assoc_item_list.assoc_items().next() + } + }, None => { let name = &strukt_name.to_string(); let ty_params = strukt.generic_param_list(); let ty_args = ty_params.as_ref().map(|it| it.to_generic_args()); let where_clause = strukt.where_clause(); + let assoc_item_list = make::assoc_item_list(Some(vec![item])); let impl_def = make::impl_( ty_params, ty_args, make::ty_path(make::ext::ident_path(name)), where_clause, - None, + Some(assoc_item_list), ) .clone_for_update(); // Fixup impl_def indentation let indent = strukt.indent_level(); - impl_def.reindent_to(indent); + let impl_def = impl_def.indent(indent); // Insert the impl block. let strukt = edit.make_mut(strukt.clone()); - ted::insert_all( - ted::Position::after(strukt.syntax()), + editor.insert_all( + Position::after(strukt.syntax()), vec![ make::tokens::whitespace(&format!("\n\n{indent}")).into(), impl_def.syntax().clone().into(), ], ); - - impl_def + impl_def.assoc_item_list().and_then(|list| list.assoc_items().next()) } }; - // Fixup function indentation. - // FIXME: Should really be handled by `AssocItemList::add_item` - f.reindent_to(impl_def.indent_level() + 1); - - let assoc_items = impl_def.get_or_create_assoc_item_list(); - assoc_items.add_item(f.clone().into()); - - if let Some(cap) = ctx.config.snippet_cap { - edit.add_tabstop_before(cap, f) + if let Some(cap) = ctx.config.snippet_cap + && let Some(fn_) = fn_ + { + let tabstop = edit.make_tabstop_before(cap); + editor.add_annotation(fn_.syntax(), tabstop); } + edit.add_file_edits(ctx.vfs_file_id(), editor); }, )?; } diff --git a/crates/ide-assists/src/handlers/generate_impl.rs b/crates/ide-assists/src/handlers/generate_impl.rs index fcb81d239f..b38ee6f7dc 100644 --- a/crates/ide-assists/src/handlers/generate_impl.rs +++ b/crates/ide-assists/src/handlers/generate_impl.rs @@ -201,7 +201,6 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_>) -> &impl_, &target_scope, ); - let assoc_items = assoc_items.into_iter().map(either::Either::Right).collect(); let assoc_item_list = make::assoc_item_list(Some(assoc_items)); make_impl_(Some(assoc_item_list)) }; diff --git a/crates/ide-assists/src/handlers/generate_new.rs b/crates/ide-assists/src/handlers/generate_new.rs index 5bda1226cd..351f134612 100644 --- a/crates/ide-assists/src/handlers/generate_new.rs +++ b/crates/ide-assists/src/handlers/generate_new.rs @@ -168,7 +168,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option ); fn_.syntax().clone() } else { - let items = vec![either::Either::Right(ast::AssocItem::Fn(fn_))]; + let items = vec![ast::AssocItem::Fn(fn_)]; let list = make::assoc_item_list(Some(items)); editor.insert(Position::after(impl_def.syntax()), list.syntax()); list.syntax().clone() @@ -176,7 +176,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option } else { // Generate a new impl to add the method to let indent_level = strukt.indent_level(); - let body = vec![either::Either::Right(ast::AssocItem::Fn(fn_))]; + let body = vec![ast::AssocItem::Fn(fn_)]; let list = make::assoc_item_list(Some(body)); let impl_def = generate_impl_with_item(&ast::Adt::Struct(strukt.clone()), Some(list)); 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 45bb6ce912..175f261317 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 @@ -221,11 +221,7 @@ fn impl_def_from_trait( } else { Some(first.clone()) }; - let items = first_item - .into_iter() - .chain(other.iter().cloned()) - .map(either::Either::Right) - .collect(); + let items = first_item.into_iter().chain(other.iter().cloned()).collect(); make::assoc_item_list(Some(items)) } else { make::assoc_item_list(None) diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 2a7b51c3c2..daeb79cf08 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -229,9 +229,7 @@ pub fn ty_fn_ptr>( } } -pub fn assoc_item_list( - body: Option>>, -) -> ast::AssocItemList { +pub fn assoc_item_list(body: Option>) -> ast::AssocItemList { let is_break_braces = body.is_some(); let body_newline = if is_break_braces { "\n".to_owned() } else { String::new() }; let body_indent = if is_break_braces { " ".to_owned() } else { String::new() };