Skip to content

Commit 1c927d2

Browse files
Merge #8802
8802: Keep comments and attrs when extracting struct from enum variant r=Veykril a=DropDemBits Fixes #6730 Still unsure if existing visibilities of fields should be forced to pub (which is what was previously done), or if it's okay to keep it in the extracted struct. Co-authored-by: DropDemBits <[email protected]>
2 parents a5b5582 + 7fefac4 commit 1c927d2

File tree

1 file changed

+126
-9
lines changed

1 file changed

+126
-9
lines changed

crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs

Lines changed: 126 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,20 +151,37 @@ fn create_struct_def(
151151
field_list: &Either<ast::RecordFieldList, ast::TupleFieldList>,
152152
visibility: Option<ast::Visibility>,
153153
) -> ast::Struct {
154-
let pub_vis = Some(make::visibility_pub());
154+
let pub_vis = make::visibility_pub();
155+
156+
let insert_pub = |node: &'_ SyntaxNode| {
157+
let pub_vis = pub_vis.clone_for_update();
158+
ted::insert(ted::Position::before(node), pub_vis.syntax());
159+
};
160+
161+
// for fields without any existing visibility, use pub visibility
155162
let field_list = match field_list {
156163
Either::Left(field_list) => {
157-
make::record_field_list(field_list.fields().flat_map(|field| {
158-
Some(make::record_field(pub_vis.clone(), field.name()?, field.ty()?))
159-
}))
160-
.into()
164+
let field_list = field_list.clone_for_update();
165+
166+
field_list
167+
.fields()
168+
.filter(|field| field.visibility().is_none())
169+
.filter_map(|field| field.name())
170+
.for_each(|it| insert_pub(it.syntax()));
171+
172+
field_list.into()
161173
}
162-
Either::Right(field_list) => make::tuple_field_list(
174+
Either::Right(field_list) => {
175+
let field_list = field_list.clone_for_update();
176+
163177
field_list
164178
.fields()
165-
.flat_map(|field| Some(make::tuple_field(pub_vis.clone(), field.ty()?))),
166-
)
167-
.into(),
179+
.filter(|field| field.visibility().is_none())
180+
.filter_map(|field| field.ty())
181+
.for_each(|it| insert_pub(it.syntax()));
182+
183+
field_list.into()
184+
}
168185
};
169186

170187
make::struct_(visibility, variant_name, None, field_list).clone_for_update()
@@ -290,6 +307,106 @@ enum A { One(One) }"#,
290307
"enum A { $0One { foo: u32 } }",
291308
r#"struct One{ pub foo: u32 }
292309
310+
enum A { One(One) }"#,
311+
);
312+
}
313+
314+
#[test]
315+
fn test_extract_struct_keep_comments_and_attrs_one_field_named() {
316+
check_assist(
317+
extract_struct_from_enum_variant,
318+
r#"
319+
enum A {
320+
$0One {
321+
// leading comment
322+
/// doc comment
323+
#[an_attr]
324+
foo: u32
325+
// trailing comment
326+
}
327+
}"#,
328+
r#"
329+
struct One{
330+
// leading comment
331+
/// doc comment
332+
#[an_attr]
333+
pub foo: u32
334+
// trailing comment
335+
}
336+
337+
enum A {
338+
One(One)
339+
}"#,
340+
);
341+
}
342+
343+
#[test]
344+
fn test_extract_struct_keep_comments_and_attrs_several_fields_named() {
345+
check_assist(
346+
extract_struct_from_enum_variant,
347+
r#"
348+
enum A {
349+
$0One {
350+
// comment
351+
/// doc
352+
#[attr]
353+
foo: u32,
354+
// comment
355+
#[attr]
356+
/// doc
357+
bar: u32
358+
}
359+
}"#,
360+
r#"
361+
struct One{
362+
// comment
363+
/// doc
364+
#[attr]
365+
pub foo: u32,
366+
// comment
367+
#[attr]
368+
/// doc
369+
pub bar: u32
370+
}
371+
372+
enum A {
373+
One(One)
374+
}"#,
375+
);
376+
}
377+
378+
#[test]
379+
fn test_extract_struct_keep_comments_and_attrs_several_fields_tuple() {
380+
check_assist(
381+
extract_struct_from_enum_variant,
382+
"enum A { $0One(/* comment */ #[attr] u32, /* another */ u32 /* tail */) }",
383+
r#"
384+
struct One(/* comment */ #[attr] pub u32, /* another */ pub u32 /* tail */);
385+
386+
enum A { One(One) }"#,
387+
);
388+
}
389+
390+
#[test]
391+
fn test_extract_struct_keep_existing_visibility_named() {
392+
check_assist(
393+
extract_struct_from_enum_variant,
394+
"enum A { $0One{ pub a: u32, pub(crate) b: u32, pub(super) c: u32, d: u32 } }",
395+
r#"
396+
struct One{ pub a: u32, pub(crate) b: u32, pub(super) c: u32, pub d: u32 }
397+
398+
enum A { One(One) }"#,
399+
);
400+
}
401+
402+
#[test]
403+
fn test_extract_struct_keep_existing_visibility_tuple() {
404+
check_assist(
405+
extract_struct_from_enum_variant,
406+
"enum A { $0One(pub u32, pub(crate) u32, pub(super) u32, u32) }",
407+
r#"
408+
struct One(pub u32, pub(crate) u32, pub(super) u32, pub u32);
409+
293410
enum A { One(One) }"#,
294411
);
295412
}

0 commit comments

Comments
 (0)