11use either:: Either ;
22use ide_db:: syntax_helpers:: node_ext:: walk_ty;
3- use syntax:: ast:: { self , edit:: IndentLevel , make, AstNode , HasGenericParams , HasName } ;
3+ use syntax:: {
4+ ast:: { self , edit:: IndentLevel , make, AstNode , HasGenericParams , HasName } ,
5+ ted,
6+ } ;
47
58use crate :: { AssistContext , AssistId , AssistKind , Assists } ;
69
@@ -34,14 +37,16 @@ pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) ->
3437 || item. syntax ( ) ,
3538 |impl_| impl_. as_ref ( ) . either ( AstNode :: syntax, AstNode :: syntax) ,
3639 ) ;
37- let insert_pos = node. text_range ( ) . start ( ) ;
3840 let target = ty. syntax ( ) . text_range ( ) ;
3941
4042 acc. add (
4143 AssistId ( "extract_type_alias" , AssistKind :: RefactorExtract ) ,
4244 "Extract type as type alias" ,
4345 target,
44- |builder| {
46+ |edit| {
47+ let node = edit. make_syntax_mut ( node. clone ( ) ) ;
48+ let target_ty = edit. make_mut ( ty. clone ( ) ) ;
49+
4550 let mut known_generics = match item. generic_param_list ( ) {
4651 Some ( it) => it. generic_params ( ) . collect ( ) ,
4752 None => Vec :: new ( ) ,
@@ -56,27 +61,29 @@ pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) ->
5661 let generic_params =
5762 generics. map ( |it| make:: generic_param_list ( it. into_iter ( ) . cloned ( ) ) ) ;
5863
64+ // Replace original type with the alias
5965 let ty_args = generic_params
6066 . as_ref ( )
6167 . map_or ( String :: new ( ) , |it| it. to_generic_args ( ) . to_string ( ) ) ;
62- let replacement = format ! ( "Type{ty_args}" ) ;
63- builder. replace ( target, replacement) ;
64-
65- let indent = IndentLevel :: from_node ( node) ;
66- let generic_params = generic_params. map_or ( String :: new ( ) , |it| it. to_string ( ) ) ;
67- match ctx. config . snippet_cap {
68- Some ( cap) => {
69- builder. insert_snippet (
70- cap,
71- insert_pos,
72- format ! ( "type $0Type{generic_params} = {ty};\n \n {indent}" ) ,
73- ) ;
74- }
75- None => {
76- builder. insert (
77- insert_pos,
78- format ! ( "type Type{generic_params} = {ty};\n \n {indent}" ) ,
79- ) ;
68+ // FIXME: replace with a `ast::make` constructor
69+ let new_ty = make:: ty ( & format ! ( "Type{ty_args}" ) ) . clone_for_update ( ) ;
70+ ted:: replace ( target_ty. syntax ( ) , new_ty. syntax ( ) ) ;
71+
72+ // Insert new alias
73+ let indent = IndentLevel :: from_node ( & node) ;
74+ let ty_alias = make:: ty_alias ( "Type" , generic_params, None , None , Some ( ( ty, None ) ) )
75+ . clone_for_update ( ) ;
76+ ted:: insert_all (
77+ ted:: Position :: before ( node) ,
78+ vec ! [
79+ ty_alias. syntax( ) . clone( ) . into( ) ,
80+ make:: tokens:: whitespace( & format!( "\n \n {indent}" ) ) . into( ) ,
81+ ] ,
82+ ) ;
83+
84+ if let Some ( cap) = ctx. config . snippet_cap {
85+ if let Some ( name) = ty_alias. name ( ) {
86+ edit. add_tabstop_before ( cap, name) ;
8087 }
8188 }
8289 } ,
0 commit comments