11use ide_db:: famous_defs:: FamousDefs ;
2- use stdx:: format_to;
32use syntax:: {
43 AstNode ,
5- ast:: { self , HasGenericParams , HasName , HasTypeBounds , Impl , syntax_factory:: SyntaxFactory } ,
4+ ast:: {
5+ self , HasGenericParams , HasName , HasTypeBounds , Impl ,
6+ edit:: { AstNodeEdit , IndentLevel } ,
7+ syntax_factory:: SyntaxFactory ,
8+ } ,
9+ syntax_editor:: Position ,
610} ;
711
812use crate :: {
@@ -62,32 +66,32 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext<'
6266 return None ;
6367 }
6468
65- let insert_location = impl_. syntax ( ) . text_range ( ) ;
69+ let target = impl_. syntax ( ) . text_range ( ) ;
6670
6771 acc. add (
6872 AssistId :: generate ( "generate_default_from_new" ) ,
6973 "Generate a Default impl from a new fn" ,
70- insert_location ,
74+ target ,
7175 move |builder| {
72- let default_code = " fn default() -> Self {
73- Self::new()
74- }" ;
7576 let make = SyntaxFactory :: without_mappings ( ) ;
76- let code =
77- generate_trait_impl_text_from_impl ( & impl_, self_ty, "Default" , default_code, & make) ;
78- builder. insert ( insert_location. end ( ) , code) ;
77+ let default_impl = generate_default_impl ( & make, & impl_, self_ty) ;
78+ let indent = IndentLevel :: from_node ( impl_. syntax ( ) ) ;
79+ let default_impl = default_impl. indent ( indent) ;
80+
81+ let mut editor = builder. make_editor ( impl_. syntax ( ) ) ;
82+ editor. insert_all (
83+ Position :: after ( impl_. syntax ( ) ) ,
84+ vec ! [
85+ make. whitespace( & format!( "\n \n {indent}" ) ) . into( ) ,
86+ default_impl. syntax( ) . clone( ) . into( ) ,
87+ ] ,
88+ ) ;
89+ builder. add_file_edits ( ctx. vfs_file_id ( ) , editor) ;
7990 } ,
8091 )
8192}
8293
83- // FIXME: based on from utils::generate_impl_text_inner
84- fn generate_trait_impl_text_from_impl (
85- impl_ : & ast:: Impl ,
86- self_ty : ast:: Type ,
87- trait_text : & str ,
88- code : & str ,
89- make : & SyntaxFactory ,
90- ) -> String {
94+ fn generate_default_impl ( make : & SyntaxFactory , impl_ : & ast:: Impl , self_ty : ast:: Type ) -> ast:: Impl {
9195 let generic_params = impl_. generic_param_list ( ) . map ( |generic_params| {
9296 let lifetime_params =
9397 generic_params. lifetime_params ( ) . map ( ast:: GenericParam :: LifetimeParam ) ;
@@ -109,26 +113,45 @@ fn generate_trait_impl_text_from_impl(
109113 make. generic_param_list ( itertools:: chain ( lifetime_params, ty_or_const_params) )
110114 } ) ;
111115
112- let mut buf = String :: with_capacity ( code. len ( ) ) ;
113- buf. push_str ( "\n \n " ) ;
114-
115- // `impl{generic_params} {trait_text} for {impl_.self_ty()}`
116- buf. push_str ( "impl" ) ;
117- if let Some ( generic_params) = & generic_params {
118- format_to ! ( buf, "{generic_params}" )
119- }
120- format_to ! ( buf, " {trait_text} for {self_ty}" ) ;
121-
122- match impl_. where_clause ( ) {
123- Some ( where_clause) => {
124- format_to ! ( buf, "\n {where_clause}\n {{\n {code}\n }}" ) ;
125- }
126- None => {
127- format_to ! ( buf, " {{\n {code}\n }}" ) ;
128- }
129- }
130-
131- buf
116+ let trait_ty: ast:: Type = make. ty_path ( make. ident_path ( "Default" ) ) . into ( ) ;
117+
118+ let self_new_path = make. path_concat ( make. ident_path ( "Self" ) , make. ident_path ( "new" ) ) ;
119+ let self_new_call =
120+ make. expr_call ( make. expr_path ( self_new_path) , make. arg_list ( std:: iter:: empty ( ) ) ) ;
121+ let fn_body = make. block_expr ( std:: iter:: empty ( ) , Some ( self_new_call. into ( ) ) ) ;
122+ let self_ty_ret: ast:: Type = make. ty_path ( make. ident_path ( "Self" ) ) . into ( ) ;
123+ let default_fn = make
124+ . fn_ (
125+ [ ] ,
126+ None ,
127+ make. name ( "default" ) ,
128+ None ,
129+ None ,
130+ make. param_list ( None , std:: iter:: empty ( ) ) ,
131+ fn_body,
132+ Some ( make. ret_type ( self_ty_ret) ) ,
133+ false ,
134+ false ,
135+ false ,
136+ false ,
137+ )
138+ . indent ( 1 . into ( ) ) ;
139+ let body = make. assoc_item_list ( Some ( ast:: AssocItem :: from ( default_fn) ) ) ;
140+
141+ make. impl_trait (
142+ [ ] ,
143+ false ,
144+ None ,
145+ None ,
146+ generic_params,
147+ None ,
148+ false ,
149+ trait_ty,
150+ self_ty,
151+ None ,
152+ impl_. where_clause ( ) ,
153+ Some ( body) ,
154+ )
132155}
133156
134157fn is_default_implemented ( ctx : & AssistContext < ' _ > , impl_ : & Impl ) -> bool {
@@ -631,12 +654,12 @@ mod test {
631654 }
632655 }
633656
634- impl Default for Example {
635- fn default() -> Self {
636- Self::new()
657+ impl Default for Example {
658+ fn default() -> Self {
659+ Self::new()
660+ }
637661 }
638662}
639- }
640663"# ,
641664 ) ;
642665 }
0 commit comments