mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-30 11:37:31 +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
 | ||||
|     // are to lift this limitation, don't forget to make `edit_struct_def()` consider macro files
 | ||||
|     // too.
 | ||||
|     let name = ctx.find_node_at_offset::<ast::Name>()?; | ||||
|     let strukt = name.syntax().parent().and_then(<Either<ast::Struct, ast::Variant>>::cast)?; | ||||
|     let field_list = strukt.as_ref().either(|s| s.field_list(), |v| v.field_list())?; | ||||
|     let strukt_or_variant = ctx | ||||
|         .find_node_at_offset::<ast::Struct>() | ||||
|         .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 { | ||||
|         ast::FieldList::RecordFieldList(it) => it, | ||||
|         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::Right(v) => Either::Right(ctx.sema.to_def(v)?), | ||||
|     }; | ||||
|  | @ -71,11 +79,11 @@ pub(crate) fn convert_named_struct_to_tuple_struct( | |||
|     acc.add( | ||||
|         AssistId::refactor_rewrite("convert_named_struct_to_tuple_struct"), | ||||
|         "Convert to tuple struct", | ||||
|         strukt.syntax().text_range(), | ||||
|         strukt_or_variant.syntax().text_range(), | ||||
|         |edit| { | ||||
|             edit_field_references(ctx, edit, record_fields.fields()); | ||||
|             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 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 { | ||||
|     fn new(inner: Inner) -> A { | ||||
|         A(inner) | ||||
|  |  | |||
|  | @ -51,18 +51,26 @@ pub(crate) fn convert_tuple_struct_to_named_struct( | |||
|     acc: &mut Assists, | ||||
|     ctx: &AssistContext<'_>, | ||||
| ) -> Option<()> { | ||||
|     let name = ctx.find_node_at_offset::<ast::Name>()?; | ||||
|     let strukt = name.syntax().parent().and_then(<Either<ast::Struct, ast::Variant>>::cast)?; | ||||
|     let field_list = strukt.as_ref().either(|s| s.field_list(), |v| v.field_list())?; | ||||
|     let strukt_or_variant = ctx | ||||
|         .find_node_at_offset::<ast::Struct>() | ||||
|         .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 { | ||||
|         ast::FieldList::TupleFieldList(it) => it, | ||||
|         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::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( | ||||
|         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()); | ||||
|             edit_field_references(ctx, edit, tuple_fields.fields(), &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 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 { | ||||
|     fn new(inner: Inner) -> A { | ||||
|         A { field1: inner } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Wirth
						Lukas Wirth