mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-30 19:49:36 +00:00 
			
		
		
		
	Merge pull request #19901 from BazookaMusic/master
Enable Assist edit for tuple<->named struct for the struct and visiblity keywords
This commit is contained in:
		
						commit
						9edac77f48
					
				
					 2 changed files with 192 additions and 12 deletions
				
			
		|  | @ -56,14 +56,22 @@ pub(crate) fn convert_named_struct_to_tuple_struct( | ||||||
|     // XXX: We don't currently provide this assist for struct definitions inside macros, but if we
 |     // XXX: We don't currently provide this assist for struct definitions inside macros, but if we
 | ||||||
|     // are to lift this limitation, don't forget to make `edit_struct_def()` consider macro files
 |     // are to lift this limitation, don't forget to make `edit_struct_def()` consider macro files
 | ||||||
|     // too.
 |     // too.
 | ||||||
|     let name = ctx.find_node_at_offset::<ast::Name>()?; |     let strukt_or_variant = ctx | ||||||
|     let strukt = name.syntax().parent().and_then(<Either<ast::Struct, ast::Variant>>::cast)?; |         .find_node_at_offset::<ast::Struct>() | ||||||
|     let field_list = strukt.as_ref().either(|s| s.field_list(), |v| v.field_list())?; |         .map(Either::Left) | ||||||
|  |         .or_else(|| ctx.find_node_at_offset::<ast::Variant>().map(Either::Right))?; | ||||||
|  |     let field_list = strukt_or_variant.as_ref().either(|s| s.field_list(), |v| v.field_list())?; | ||||||
|  | 
 | ||||||
|  |     if ctx.offset() > field_list.syntax().text_range().start() { | ||||||
|  |         // Assist could be distracting after the braces
 | ||||||
|  |         return None; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     let record_fields = match field_list { |     let record_fields = match field_list { | ||||||
|         ast::FieldList::RecordFieldList(it) => it, |         ast::FieldList::RecordFieldList(it) => it, | ||||||
|         ast::FieldList::TupleFieldList(_) => return None, |         ast::FieldList::TupleFieldList(_) => return None, | ||||||
|     }; |     }; | ||||||
|     let strukt_def = match &strukt { |     let strukt_def = match &strukt_or_variant { | ||||||
|         Either::Left(s) => Either::Left(ctx.sema.to_def(s)?), |         Either::Left(s) => Either::Left(ctx.sema.to_def(s)?), | ||||||
|         Either::Right(v) => Either::Right(ctx.sema.to_def(v)?), |         Either::Right(v) => Either::Right(ctx.sema.to_def(v)?), | ||||||
|     }; |     }; | ||||||
|  | @ -71,11 +79,11 @@ pub(crate) fn convert_named_struct_to_tuple_struct( | ||||||
|     acc.add( |     acc.add( | ||||||
|         AssistId::refactor_rewrite("convert_named_struct_to_tuple_struct"), |         AssistId::refactor_rewrite("convert_named_struct_to_tuple_struct"), | ||||||
|         "Convert to tuple struct", |         "Convert to tuple struct", | ||||||
|         strukt.syntax().text_range(), |         strukt_or_variant.syntax().text_range(), | ||||||
|         |edit| { |         |edit| { | ||||||
|             edit_field_references(ctx, edit, record_fields.fields()); |             edit_field_references(ctx, edit, record_fields.fields()); | ||||||
|             edit_struct_references(ctx, edit, strukt_def); |             edit_struct_references(ctx, edit, strukt_def); | ||||||
|             edit_struct_def(ctx, edit, &strukt, record_fields); |             edit_struct_def(ctx, edit, &strukt_or_variant, record_fields); | ||||||
|         }, |         }, | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
|  | @ -277,6 +285,88 @@ impl A { | ||||||
| struct Inner; | struct Inner; | ||||||
| struct A(Inner); | struct A(Inner); | ||||||
| 
 | 
 | ||||||
|  | impl A { | ||||||
|  |     fn new(inner: Inner) -> A { | ||||||
|  |         A(inner) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn new_with_default() -> A { | ||||||
|  |         A::new(Inner) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn into_inner(self) -> Inner { | ||||||
|  |         self.0 | ||||||
|  |     } | ||||||
|  | }"#,
 | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn convert_simple_struct_cursor_on_struct_keyword() { | ||||||
|  |         check_assist( | ||||||
|  |             convert_named_struct_to_tuple_struct, | ||||||
|  |             r#" | ||||||
|  | struct Inner; | ||||||
|  | struct$0 A { inner: Inner } | ||||||
|  | 
 | ||||||
|  | impl A { | ||||||
|  |     fn new(inner: Inner) -> A { | ||||||
|  |         A { inner } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn new_with_default() -> A { | ||||||
|  |         A::new(Inner) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn into_inner(self) -> Inner { | ||||||
|  |         self.inner | ||||||
|  |     } | ||||||
|  | }"#,
 | ||||||
|  |             r#" | ||||||
|  | struct Inner; | ||||||
|  | struct A(Inner); | ||||||
|  | 
 | ||||||
|  | impl A { | ||||||
|  |     fn new(inner: Inner) -> A { | ||||||
|  |         A(inner) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn new_with_default() -> A { | ||||||
|  |         A::new(Inner) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn into_inner(self) -> Inner { | ||||||
|  |         self.0 | ||||||
|  |     } | ||||||
|  | }"#,
 | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn convert_simple_struct_cursor_on_visibility_keyword() { | ||||||
|  |         check_assist( | ||||||
|  |             convert_named_struct_to_tuple_struct, | ||||||
|  |             r#" | ||||||
|  | struct Inner; | ||||||
|  | pub$0 struct A { inner: Inner } | ||||||
|  | 
 | ||||||
|  | impl A { | ||||||
|  |     fn new(inner: Inner) -> A { | ||||||
|  |         A { inner } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn new_with_default() -> A { | ||||||
|  |         A::new(Inner) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn into_inner(self) -> Inner { | ||||||
|  |         self.inner | ||||||
|  |     } | ||||||
|  | }"#,
 | ||||||
|  |             r#" | ||||||
|  | struct Inner; | ||||||
|  | pub struct A(Inner); | ||||||
|  | 
 | ||||||
| impl A { | impl A { | ||||||
|     fn new(inner: Inner) -> A { |     fn new(inner: Inner) -> A { | ||||||
|         A(inner) |         A(inner) | ||||||
|  |  | ||||||
|  | @ -51,18 +51,26 @@ pub(crate) fn convert_tuple_struct_to_named_struct( | ||||||
|     acc: &mut Assists, |     acc: &mut Assists, | ||||||
|     ctx: &AssistContext<'_>, |     ctx: &AssistContext<'_>, | ||||||
| ) -> Option<()> { | ) -> Option<()> { | ||||||
|     let name = ctx.find_node_at_offset::<ast::Name>()?; |     let strukt_or_variant = ctx | ||||||
|     let strukt = name.syntax().parent().and_then(<Either<ast::Struct, ast::Variant>>::cast)?; |         .find_node_at_offset::<ast::Struct>() | ||||||
|     let field_list = strukt.as_ref().either(|s| s.field_list(), |v| v.field_list())?; |         .map(Either::Left) | ||||||
|  |         .or_else(|| ctx.find_node_at_offset::<ast::Variant>().map(Either::Right))?; | ||||||
|  |     let field_list = strukt_or_variant.as_ref().either(|s| s.field_list(), |v| v.field_list())?; | ||||||
|  | 
 | ||||||
|  |     if ctx.offset() > field_list.syntax().text_range().start() { | ||||||
|  |         // Assist could be distracting after the braces
 | ||||||
|  |         return None; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     let tuple_fields = match field_list { |     let tuple_fields = match field_list { | ||||||
|         ast::FieldList::TupleFieldList(it) => it, |         ast::FieldList::TupleFieldList(it) => it, | ||||||
|         ast::FieldList::RecordFieldList(_) => return None, |         ast::FieldList::RecordFieldList(_) => return None, | ||||||
|     }; |     }; | ||||||
|     let strukt_def = match &strukt { |     let strukt_def = match &strukt_or_variant { | ||||||
|         Either::Left(s) => Either::Left(ctx.sema.to_def(s)?), |         Either::Left(s) => Either::Left(ctx.sema.to_def(s)?), | ||||||
|         Either::Right(v) => Either::Right(ctx.sema.to_def(v)?), |         Either::Right(v) => Either::Right(ctx.sema.to_def(v)?), | ||||||
|     }; |     }; | ||||||
|     let target = strukt.as_ref().either(|s| s.syntax(), |v| v.syntax()).text_range(); |     let target = strukt_or_variant.as_ref().either(|s| s.syntax(), |v| v.syntax()).text_range(); | ||||||
| 
 | 
 | ||||||
|     acc.add( |     acc.add( | ||||||
|         AssistId::refactor_rewrite("convert_tuple_struct_to_named_struct"), |         AssistId::refactor_rewrite("convert_tuple_struct_to_named_struct"), | ||||||
|  | @ -72,7 +80,7 @@ pub(crate) fn convert_tuple_struct_to_named_struct( | ||||||
|             let names = generate_names(tuple_fields.fields()); |             let names = generate_names(tuple_fields.fields()); | ||||||
|             edit_field_references(ctx, edit, tuple_fields.fields(), &names); |             edit_field_references(ctx, edit, tuple_fields.fields(), &names); | ||||||
|             edit_struct_references(ctx, edit, strukt_def, &names); |             edit_struct_references(ctx, edit, strukt_def, &names); | ||||||
|             edit_struct_def(ctx, edit, &strukt, tuple_fields, names); |             edit_struct_def(ctx, edit, &strukt_or_variant, tuple_fields, names); | ||||||
|         }, |         }, | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
|  | @ -300,6 +308,88 @@ impl A { | ||||||
| struct Inner; | struct Inner; | ||||||
| struct A { field1: Inner } | struct A { field1: Inner } | ||||||
| 
 | 
 | ||||||
|  | impl A { | ||||||
|  |     fn new(inner: Inner) -> A { | ||||||
|  |         A { field1: inner } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn new_with_default() -> A { | ||||||
|  |         A::new(Inner) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn into_inner(self) -> Inner { | ||||||
|  |         self.field1 | ||||||
|  |     } | ||||||
|  | }"#,
 | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn convert_simple_struct_cursor_on_struct_keyword() { | ||||||
|  |         check_assist( | ||||||
|  |             convert_tuple_struct_to_named_struct, | ||||||
|  |             r#" | ||||||
|  | struct Inner; | ||||||
|  | struct$0 A(Inner); | ||||||
|  | 
 | ||||||
|  | impl A { | ||||||
|  |     fn new(inner: Inner) -> A { | ||||||
|  |         A(inner) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn new_with_default() -> A { | ||||||
|  |         A::new(Inner) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn into_inner(self) -> Inner { | ||||||
|  |         self.0 | ||||||
|  |     } | ||||||
|  | }"#,
 | ||||||
|  |             r#" | ||||||
|  | struct Inner; | ||||||
|  | struct A { field1: Inner } | ||||||
|  | 
 | ||||||
|  | impl A { | ||||||
|  |     fn new(inner: Inner) -> A { | ||||||
|  |         A { field1: inner } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn new_with_default() -> A { | ||||||
|  |         A::new(Inner) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn into_inner(self) -> Inner { | ||||||
|  |         self.field1 | ||||||
|  |     } | ||||||
|  | }"#,
 | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn convert_simple_struct_cursor_on_visibility_keyword() { | ||||||
|  |         check_assist( | ||||||
|  |             convert_tuple_struct_to_named_struct, | ||||||
|  |             r#" | ||||||
|  | struct Inner; | ||||||
|  | pub$0 struct A(Inner); | ||||||
|  | 
 | ||||||
|  | impl A { | ||||||
|  |     fn new(inner: Inner) -> A { | ||||||
|  |         A(inner) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn new_with_default() -> A { | ||||||
|  |         A::new(Inner) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn into_inner(self) -> Inner { | ||||||
|  |         self.0 | ||||||
|  |     } | ||||||
|  | }"#,
 | ||||||
|  |             r#" | ||||||
|  | struct Inner; | ||||||
|  | pub struct A { field1: Inner } | ||||||
|  | 
 | ||||||
| impl A { | impl A { | ||||||
|     fn new(inner: Inner) -> A { |     fn new(inner: Inner) -> A { | ||||||
|         A { field1: inner } |         A { field1: inner } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Wirth
						Lukas Wirth