Skip to content

Commit 45dac9a

Browse files
committed
Move comments to the extracted struct
1 parent 7d77775 commit 45dac9a

File tree

1 file changed

+42
-9
lines changed

1 file changed

+42
-9
lines changed

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

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ pub(crate) fn extract_struct_from_enum_variant(
105105
.generic_param_list()
106106
.and_then(|known_generics| extract_generic_params(&known_generics, &field_list));
107107
let generics = generic_params.as_ref().map(|generics| generics.clone_for_update());
108-
let def = create_struct_def(variant_name.clone(), &field_list, generics, &enum_ast);
108+
let def =
109+
create_struct_def(variant_name.clone(), &variant, &field_list, generics, &enum_ast);
109110

110111
let enum_ast = variant.parent_enum();
111112
let indent = enum_ast.indent_level();
@@ -228,6 +229,7 @@ fn tag_generics_in_variant(ty: &ast::Type, generics: &mut [(ast::GenericParam, b
228229

229230
fn create_struct_def(
230231
name: ast::Name,
232+
variant: &ast::Variant,
231233
field_list: &Either<ast::RecordFieldList, ast::TupleFieldList>,
232234
generics: Option<ast::GenericParamList>,
233235
enum_: &ast::Enum,
@@ -272,6 +274,12 @@ fn create_struct_def(
272274

273275
let strukt = make::struct_(enum_vis, name, generics, field_list).clone_for_update();
274276

277+
// take comments from variant
278+
ted::insert_all(
279+
ted::Position::first_child_of(strukt.syntax()),
280+
take_all_comments(variant.syntax()),
281+
);
282+
275283
// copy attributes from enum
276284
ted::insert_all(
277285
ted::Position::first_child_of(strukt.syntax()),
@@ -340,6 +348,31 @@ fn update_variant(variant: &ast::Variant, generics: Option<ast::GenericParamList
340348
Some(())
341349
}
342350

351+
// Note: this also detaches whitespace after comments,
352+
// since `SyntaxNode::splice_children` (and by extension `ted::insert_all_raw`)
353+
// detaches nodes. If we only took the comments, we'd leave behind the old whitespace.
354+
fn take_all_comments(node: &SyntaxNode) -> Vec<SyntaxElement> {
355+
let mut remove_next_ws = false;
356+
node.children_with_tokens()
357+
.filter_map(move |child| match child.kind() {
358+
COMMENT => {
359+
remove_next_ws = true;
360+
child.detach();
361+
Some(child)
362+
}
363+
WHITESPACE if remove_next_ws => {
364+
remove_next_ws = false;
365+
child.detach();
366+
Some(make::tokens::single_newline().into())
367+
}
368+
_ => {
369+
remove_next_ws = false;
370+
None
371+
}
372+
})
373+
.collect()
374+
}
375+
343376
fn apply_references(
344377
insert_use_cfg: InsertUseConfig,
345378
segment: ast::PathSegment,
@@ -602,7 +635,7 @@ enum A { One(One) }"#,
602635
}
603636

604637
#[test]
605-
fn test_extract_struct_keep_comments_and_attrs_on_variant_struct() {
638+
fn test_extract_struct_move_struct_variant_comments() {
606639
check_assist(
607640
extract_struct_from_enum_variant,
608641
r#"
@@ -616,22 +649,22 @@ enum A {
616649
}
617650
}"#,
618651
r#"
652+
/* comment */
653+
// other
654+
/// comment
619655
struct One{
620656
a: u32
621657
}
622658
623659
enum A {
624-
/* comment */
625-
// other
626-
/// comment
627660
#[attr]
628661
One(One)
629662
}"#,
630663
);
631664
}
632665

633666
#[test]
634-
fn test_extract_struct_keep_comments_and_attrs_on_variant_tuple() {
667+
fn test_extract_struct_move_tuple_variant_comments() {
635668
check_assist(
636669
extract_struct_from_enum_variant,
637670
r#"
@@ -643,12 +676,12 @@ enum A {
643676
$0One(u32, u32)
644677
}"#,
645678
r#"
679+
/* comment */
680+
// other
681+
/// comment
646682
struct One(u32, u32);
647683
648684
enum A {
649-
/* comment */
650-
// other
651-
/// comment
652685
#[attr]
653686
One(One)
654687
}"#,

0 commit comments

Comments
 (0)