mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 12:04:43 +00:00 
			
		
		
		
	feat: add an assist to unwrap a type with a generic arg
This assist unwraps a type into its generic type argument, ignoring const and lifetime arguments
This commit is contained in:
		
							parent
							
								
									3b57c00151
								
							
						
					
					
						commit
						4771b84a75
					
				
					 3 changed files with 175 additions and 0 deletions
				
			
		
							
								
								
									
										156
									
								
								crates/ide-assists/src/handlers/unwrap_type_to_generic_arg.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								crates/ide-assists/src/handlers/unwrap_type_to_generic_arg.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,156 @@ | |||
| use ide_db::assists::AssistId; | ||||
| use syntax::{ | ||||
|     AstNode, | ||||
|     ast::{self, GenericArg, HasGenericArgs}, | ||||
| }; | ||||
| 
 | ||||
| use crate::{AssistContext, Assists}; | ||||
| 
 | ||||
| // Assist: unwrap_type_to_generic_arg
 | ||||
| //
 | ||||
| // This assist unwraps a type into its generic type argument.
 | ||||
| //
 | ||||
| // ```
 | ||||
| // fn foo() -> $0Option<i32> {
 | ||||
| //     todo!()
 | ||||
| // }
 | ||||
| // ```
 | ||||
| // ->
 | ||||
| // ```
 | ||||
| // fn foo() -> i32 {
 | ||||
| //     todo!()
 | ||||
| // }
 | ||||
| // ```
 | ||||
| pub(crate) fn unwrap_type_to_generic_arg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { | ||||
|     let path_type = ctx.find_node_at_offset::<ast::PathType>()?; | ||||
|     let path = path_type.path()?; | ||||
|     let segment = path.segment()?; | ||||
|     let args_list = segment.generic_arg_list()?; | ||||
| 
 | ||||
|     let mut generic_arg = None; | ||||
| 
 | ||||
|     for arg in args_list.generic_args() { | ||||
|         match arg { | ||||
|             GenericArg::ConstArg(_) | GenericArg::LifetimeArg(_) => (), | ||||
|             GenericArg::TypeArg(arg) if generic_arg.is_none() => { | ||||
|                 generic_arg = Some(arg); | ||||
|             } | ||||
|             _ => return None, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     let generic_arg = generic_arg?; | ||||
| 
 | ||||
|     acc.add( | ||||
|         AssistId::refactor_extract("unwrap_type_to_generic_arg"), | ||||
|         format!("Unwrap type to type argument {generic_arg}"), | ||||
|         path_type.syntax().text_range(), | ||||
|         |builder| { | ||||
|             let mut editor = builder.make_editor(path_type.syntax()); | ||||
|             editor.replace(path_type.syntax(), generic_arg.syntax()); | ||||
| 
 | ||||
|             builder.add_file_edits(ctx.vfs_file_id(), editor); | ||||
|         }, | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use super::*; | ||||
|     use crate::tests::{check_assist, check_assist_not_applicable}; | ||||
| 
 | ||||
|     #[test] | ||||
|     fn test_unwrap_type_to_generic_arg() { | ||||
|         check_assist( | ||||
|             unwrap_type_to_generic_arg, | ||||
|             r#" | ||||
| //- minicore: option
 | ||||
| fn foo() -> $0Option<i32> { | ||||
|     todo!() | ||||
| } | ||||
| "#,
 | ||||
|             r#" | ||||
| fn foo() -> i32 { | ||||
|     todo!() | ||||
| } | ||||
| "#,
 | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn unwrap_type_to_generic_arg_not_applicable_for_non_generic_arg_list() { | ||||
|         check_assist_not_applicable( | ||||
|             unwrap_type_to_generic_arg, | ||||
|             r#" | ||||
| fn foo() -> $0i32 {} | ||||
| "#,
 | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn unwrap_type_to_generic_arg_not_applicable_for_multiple_generic_args() { | ||||
|         check_assist_not_applicable( | ||||
|             unwrap_type_to_generic_arg, | ||||
|             r#" | ||||
| //- minicore: result
 | ||||
| fn foo() -> $0Result<i32, ()> { | ||||
|     todo!() | ||||
| } | ||||
| "#,
 | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn unwrap_type_to_generic_arg_with_lifetime_and_const() { | ||||
|         check_assist( | ||||
|             unwrap_type_to_generic_arg, | ||||
|             r#" | ||||
| enum Foo<'a, T, const N: usize> { | ||||
|     Bar(T), | ||||
|     Baz(&'a [T; N]), | ||||
| } | ||||
| 
 | ||||
| fn test<'a>() -> $0Foo<'a, i32, 3> { | ||||
|     todo!() | ||||
| } | ||||
| "#,
 | ||||
|             r#" | ||||
| enum Foo<'a, T, const N: usize> { | ||||
|     Bar(T), | ||||
|     Baz(&'a [T; N]), | ||||
| } | ||||
| 
 | ||||
| fn test<'a>() -> i32 { | ||||
|     todo!() | ||||
| } | ||||
| "#,
 | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn unwrap_type_to_generic_arg_in_let_stmt() { | ||||
|         check_assist( | ||||
|             unwrap_type_to_generic_arg, | ||||
|             r#" | ||||
| enum Foo<T> { | ||||
|     Bar(T), | ||||
|     Baz, | ||||
| } | ||||
| 
 | ||||
| fn test() { | ||||
|     let foo: $0Foo<i32> = todo!(); | ||||
| } | ||||
| "#,
 | ||||
|             r#" | ||||
| enum Foo<T> { | ||||
|     Bar(T), | ||||
|     Baz, | ||||
| } | ||||
| 
 | ||||
| fn test() { | ||||
|     let foo: i32 = todo!(); | ||||
| } | ||||
| "#,
 | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | @ -229,6 +229,7 @@ mod handlers { | |||
|     mod unwrap_block; | ||||
|     mod unwrap_return_type; | ||||
|     mod unwrap_tuple; | ||||
|     mod unwrap_type_to_generic_arg; | ||||
|     mod wrap_return_type; | ||||
|     mod wrap_unwrap_cfg_attr; | ||||
| 
 | ||||
|  | @ -369,6 +370,7 @@ mod handlers { | |||
|             unwrap_block::unwrap_block, | ||||
|             unwrap_return_type::unwrap_return_type, | ||||
|             unwrap_tuple::unwrap_tuple, | ||||
|             unwrap_type_to_generic_arg::unwrap_type_to_generic_arg, | ||||
|             wrap_return_type::wrap_return_type, | ||||
|             wrap_unwrap_cfg_attr::wrap_unwrap_cfg_attr, | ||||
| 
 | ||||
|  |  | |||
|  | @ -3481,6 +3481,23 @@ fn main() { | |||
|     ) | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn doctest_unwrap_type_to_generic_arg() { | ||||
|     check_doc_test( | ||||
|         "unwrap_type_to_generic_arg", | ||||
|         r#####" | ||||
| fn foo() -> $0Option<i32> { | ||||
|     todo!() | ||||
| } | ||||
| "#####,
 | ||||
|         r#####" | ||||
| fn foo() -> i32 { | ||||
|     todo!() | ||||
| } | ||||
| "#####,
 | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn doctest_wrap_return_type_in_option() { | ||||
|     check_doc_test( | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vishruth-Thimmaiah
						Vishruth-Thimmaiah