@@ -31,19 +31,27 @@ pub(crate) fn extract_struct_from_enum_variant(
3131 ctx : & AssistContext ,
3232) -> Option < ( ) > {
3333 let variant = ctx. find_node_at_offset :: < ast:: Variant > ( ) ?;
34+
35+ fn is_applicable_variant ( variant : & ast:: Variant ) -> bool {
36+ 1 < match variant. kind ( ) {
37+ ast:: StructKind :: Record ( field_list) => field_list. fields ( ) . count ( ) ,
38+ ast:: StructKind :: Tuple ( field_list) => field_list. fields ( ) . count ( ) ,
39+ ast:: StructKind :: Unit => 0 ,
40+ }
41+ }
42+
43+ if !is_applicable_variant ( & variant) {
44+ return None ;
45+ }
46+
3447 let field_list = match variant. kind ( ) {
3548 ast:: StructKind :: Tuple ( field_list) => field_list,
3649 _ => return None ,
3750 } ;
3851
39- // skip 1-tuple variants
40- if field_list. fields ( ) . count ( ) == 1 {
41- return None ;
42- }
43-
4452 let variant_name = variant. name ( ) ?;
4553 let variant_hir = ctx. sema . to_def ( & variant) ?;
46- if existing_struct_def ( ctx. db ( ) , & variant_name, & variant_hir) {
54+ if existing_definition ( ctx. db ( ) , & variant_name, & variant_hir) {
4755 return None ;
4856 }
4957 let enum_ast = variant. parent_enum ( ) ;
@@ -100,12 +108,21 @@ pub(crate) fn extract_struct_from_enum_variant(
100108 )
101109}
102110
103- fn existing_struct_def ( db : & RootDatabase , variant_name : & ast:: Name , variant : & EnumVariant ) -> bool {
111+ fn existing_definition ( db : & RootDatabase , variant_name : & ast:: Name , variant : & EnumVariant ) -> bool {
104112 variant
105113 . parent_enum ( db)
106114 . module ( db)
107115 . scope ( db, None )
108116 . into_iter ( )
117+ . filter ( |( _, def) | match def {
118+ // only check type-namespace
119+ hir:: ScopeDef :: ModuleDef ( def) => matches ! ( def,
120+ ModuleDef :: Module ( _) | ModuleDef :: Adt ( _) |
121+ ModuleDef :: EnumVariant ( _) | ModuleDef :: Trait ( _) |
122+ ModuleDef :: TypeAlias ( _) | ModuleDef :: BuiltinType ( _)
123+ ) ,
124+ _ => false ,
125+ } )
109126 . any ( |( name, _) | name == variant_name. as_name ( ) )
110127}
111128
@@ -211,12 +228,39 @@ mod tests {
211228 use super :: * ;
212229
213230 #[ test]
214- fn test_extract_struct_several_fields ( ) {
231+ fn test_extract_struct_several_fields_tuple ( ) {
215232 check_assist (
216233 extract_struct_from_enum_variant,
217234 "enum A { <|>One(u32, u32) }" ,
218235 r#"struct One(pub u32, pub u32);
219236
237+ enum A { One(One) }"# ,
238+ ) ;
239+ }
240+
241+ #[ test]
242+ fn test_extract_struct_several_fields_named ( ) {
243+ check_assist (
244+ extract_struct_from_enum_variant,
245+ "enum A { <|>One { foo: u32, bar: u32 } }" ,
246+ r#"struct One {
247+ pub foo: u32,
248+ pub bar: u32
249+ }
250+
251+ enum A { One(One) }"# ,
252+ ) ;
253+ }
254+
255+ #[ test]
256+ fn test_extract_enum_variant_name_value_namespace ( ) {
257+ check_assist (
258+ extract_struct_from_enum_variant,
259+ r#"const One: () = ();
260+ enum A { <|>One(u32, u32) }"# ,
261+ r#"const One: () = ();
262+ struct One(pub u32, pub u32);
263+
220264enum A { One(One) }"# ,
221265 ) ;
222266 }
@@ -298,7 +342,7 @@ fn another_fn() {
298342 fn test_extract_enum_not_applicable_if_struct_exists ( ) {
299343 check_not_applicable (
300344 r#"struct One;
301- enum A { <|>One(u8) }"# ,
345+ enum A { <|>One(u8, u32 ) }"# ,
302346 ) ;
303347 }
304348
0 commit comments