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 9e4e6c1daf7..4cc04fff633 100644 --- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -1511,11 +1511,111 @@ fn main() { struct S; impl Tr for S { fn method() { - ${0:todo!()} - } + ${0:todo!()} + } } } "#, ); } + + #[test] + fn test_add_missing_impl_members_indentation() { + // few trait members, no braces + check_assist( + add_missing_impl_members, + r#" +mod m { + trait Foo { fn foo(&self); } + struct S; + impl Foo for S$0 +}"#, + r#" +mod m { + trait Foo { fn foo(&self); } + struct S; + impl Foo for S { + fn foo(&self) { + ${0:todo!()} + } + } +}"#, + ); + // few trait members, empty impl def. + check_assist( + add_missing_impl_members, + r#" +mod m { + trait Foo { fn foo(&self); } + struct S; + impl Foo for S { $0 } +}"#, + r#" +mod m { + trait Foo { fn foo(&self); } + struct S; + impl Foo for S { + fn foo(&self) { + ${0:todo!()} + } + } +}"#, + ); + // todo - in mod and outside + check_assist( + add_missing_impl_members, + r#" +mod m { + trait Foo { + type Output; + + const CONST: usize = 42; + const CONST_2: i32; + + fn foo(&self); + fn bar(&self); + fn baz(&self); + } + + struct S; + + impl Foo for S { + fn bar(&self) {} +$0 + } +}"#, + r#" +mod m { + trait Foo { + type Output; + + const CONST: usize = 42; + const CONST_2: i32; + + fn foo(&self); + fn bar(&self); + fn baz(&self); + } + + struct S; + + impl Foo for S { + fn bar(&self) {} + + $0type Output; + + const CONST_2: i32; + + fn foo(&self) { + todo!() + } + + fn baz(&self) { + todo!() + } + + } +}"#, + ); + } } diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs index 77f4b0e3e02..1c9d4157cd6 100644 --- a/crates/ide-assists/src/utils.rs +++ b/crates/ide-assists/src/utils.rs @@ -9,7 +9,7 @@ use syntax::{ ast::{ self, - edit::{self, AstNodeEdit}, + edit::{AstNodeEdit, IndentLevel}, edit_in_place::{AttrsOwnerEdit, Removable}, make, HasArgList, HasAttrs, HasGenericParams, HasName, HasTypeBounds, Whitespace, }, @@ -154,7 +154,7 @@ pub fn add_trait_assoc_items_to_impl( match &item { ast::AssocItem::Fn(fn_) if fn_.body().is_none() => { let body = make::block_expr(None, Some(make::ext::expr_todo())) - .indent(edit::IndentLevel(1)); + .indent(IndentLevel::from_node(impl_.syntax()) + 1); ted::replace(fn_.get_or_create_body().syntax(), body.clone_for_update().syntax()) } ast::AssocItem::TypeAlias(type_alias) => { diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index a493c92e7da..995e8d8d152 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs @@ -465,6 +465,8 @@ pub fn get_or_create_assoc_item_list(&self) -> ast::AssocItemList { } impl ast::AssocItemList { + /// Attention! This function does align the first line of `item` with respect to `self`, + /// but it does _not_ change indentation of other lines (if any). pub fn add_item(&self, item: ast::AssocItem) { let (indent, position, whitespace) = match self.assoc_items().last() { Some(last_item) => (