diff options
-rw-r--r-- | crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs | 135 |
1 files changed, 126 insertions, 9 deletions
diff --git a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs index 66f274fa7..8e2178391 100644 --- a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs | |||
@@ -151,20 +151,37 @@ fn create_struct_def( | |||
151 | field_list: &Either<ast::RecordFieldList, ast::TupleFieldList>, | 151 | field_list: &Either<ast::RecordFieldList, ast::TupleFieldList>, |
152 | visibility: Option<ast::Visibility>, | 152 | visibility: Option<ast::Visibility>, |
153 | ) -> ast::Struct { | 153 | ) -> 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 | ||
155 | let field_list = match field_list { | 162 | let field_list = match field_list { |
156 | Either::Left(field_list) => { | 163 | Either::Left(field_list) => { |
157 | make::record_field_list(field_list.fields().flat_map(|field| { | 164 | let field_list = field_list.clone_for_update(); |
158 | Some(make::record_field(pub_vis.clone(), field.name()?, field.ty()?)) | 165 | |
159 | })) | 166 | field_list |
160 | .into() | 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() | ||
161 | } | 173 | } |
162 | Either::Right(field_list) => make::tuple_field_list( | 174 | Either::Right(field_list) => { |
175 | let field_list = field_list.clone_for_update(); | ||
176 | |||
163 | field_list | 177 | field_list |
164 | .fields() | 178 | .fields() |
165 | .flat_map(|field| Some(make::tuple_field(pub_vis.clone(), field.ty()?))), | 179 | .filter(|field| field.visibility().is_none()) |
166 | ) | 180 | .filter_map(|field| field.ty()) |
167 | .into(), | 181 | .for_each(|it| insert_pub(it.syntax())); |
182 | |||
183 | field_list.into() | ||
184 | } | ||
168 | }; | 185 | }; |
169 | 186 | ||
170 | make::struct_(visibility, variant_name, None, field_list).clone_for_update() | 187 | make::struct_(visibility, variant_name, None, field_list).clone_for_update() |
@@ -295,6 +312,106 @@ enum A { One(One) }"#, | |||
295 | } | 312 | } |
296 | 313 | ||
297 | #[test] | 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 | |||
410 | enum A { One(One) }"#, | ||
411 | ); | ||
412 | } | ||
413 | |||
414 | #[test] | ||
298 | fn test_extract_enum_variant_name_value_namespace() { | 415 | fn test_extract_enum_variant_name_value_namespace() { |
299 | check_assist( | 416 | check_assist( |
300 | extract_struct_from_enum_variant, | 417 | extract_struct_from_enum_variant, |