11use ide_db:: {
22 imports:: import_assets:: item_for_path_search, use_trivial_constructor:: use_trivial_constructor,
33} ;
4- use itertools:: Itertools ;
5- use stdx:: format_to;
6- use syntax:: ast:: { self , AstNode , HasName , HasVisibility , StructKind } ;
4+ use syntax:: {
5+ ast:: { self , edit_in_place:: Indent , make, AstNode , HasName , HasVisibility , StructKind } ,
6+ ted,
7+ } ;
78
89use crate :: {
9- utils:: { find_impl_block_start , find_struct_impl, generate_impl_text } ,
10+ utils:: { find_struct_impl, generate_impl } ,
1011 AssistContext , AssistId , AssistKind , Assists ,
1112} ;
1213
@@ -26,7 +27,9 @@ use crate::{
2627// }
2728//
2829// impl<T: Clone> Ctx<T> {
29- // fn $0new(data: T) -> Self { Self { data } }
30+ // fn $0new(data: T) -> Self {
31+ // Self { data }
32+ // }
3033// }
3134// ```
3235pub ( crate ) fn generate_new ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
@@ -46,14 +49,6 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
4649
4750 let target = strukt. syntax ( ) . text_range ( ) ;
4851 acc. add ( AssistId ( "generate_new" , AssistKind :: Generate ) , "Generate `new`" , target, |builder| {
49- let mut buf = String :: with_capacity ( 512 ) ;
50-
51- if impl_def. is_some ( ) {
52- buf. push ( '\n' ) ;
53- }
54-
55- let vis = strukt. visibility ( ) . map_or ( String :: new ( ) , |v| format ! ( "{v} " ) ) ;
56-
5752 let trivial_constructors = field_list
5853 . fields ( )
5954 . map ( |f| {
@@ -76,54 +71,79 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
7671 & ty,
7772 ) ?;
7873
79- Some ( format ! ( "{name}: { expr}" ) )
74+ Some ( make :: record_expr_field ( make :: name_ref ( & name . text ( ) ) , Some ( expr) ) )
8075 } )
8176 . collect :: < Vec < _ > > ( ) ;
8277
83- let params = field_list
84- . fields ( )
85- . enumerate ( )
86- . filter_map ( |( i, f) | {
87- if trivial_constructors[ i] . is_none ( ) {
88- let name = f. name ( ) ?;
89- let ty = f. ty ( ) ?;
90-
91- Some ( format ! ( "{name}: {ty}" ) )
92- } else {
93- None
94- }
95- } )
96- . format ( ", " ) ;
78+ let params = field_list. fields ( ) . enumerate ( ) . filter_map ( |( i, f) | {
79+ if trivial_constructors[ i] . is_none ( ) {
80+ let name = f. name ( ) ?;
81+ let ty = f. ty ( ) ?;
9782
98- let fields = field_list
99- . fields ( )
100- . enumerate ( )
101- . filter_map ( |( i, f) | {
102- let constructor = trivial_constructors[ i] . clone ( ) ;
103- if constructor. is_some ( ) {
104- constructor
105- } else {
106- Some ( f. name ( ) ?. to_string ( ) )
107- }
108- } )
109- . format ( ", " ) ;
110-
111- format_to ! ( buf, " {vis}fn new({params}) -> Self {{ Self {{ {fields} }} }}" ) ;
112-
113- let start_offset = impl_def
114- . and_then ( |impl_def| find_impl_block_start ( impl_def, & mut buf) )
115- . unwrap_or_else ( || {
116- buf = generate_impl_text ( & ast:: Adt :: Struct ( strukt. clone ( ) ) , & buf) ;
117- strukt. syntax ( ) . text_range ( ) . end ( )
118- } ) ;
119-
120- match ctx. config . snippet_cap {
121- None => builder. insert ( start_offset, buf) ,
122- Some ( cap) => {
123- buf = buf. replace ( "fn new" , "fn $0new" ) ;
124- builder. insert_snippet ( cap, start_offset, buf) ;
83+ Some ( make:: param ( make:: ident_pat ( false , false , name) . into ( ) , ty) )
84+ } else {
85+ None
86+ }
87+ } ) ;
88+ let params = make:: param_list ( None , params) ;
89+
90+ let fields = field_list. fields ( ) . enumerate ( ) . filter_map ( |( i, f) | {
91+ let constructor = trivial_constructors[ i] . clone ( ) ;
92+ if constructor. is_some ( ) {
93+ constructor
94+ } else {
95+ Some ( make:: record_expr_field ( make:: name_ref ( & f. name ( ) ?. text ( ) ) , None ) )
96+ }
97+ } ) ;
98+ let fields = make:: record_expr_field_list ( fields) ;
99+
100+ let record_expr = make:: record_expr ( make:: ext:: ident_path ( "Self" ) , fields) ;
101+ let body = make:: block_expr ( None , Some ( record_expr. into ( ) ) ) ;
102+
103+ let ret_type = make:: ret_type ( make:: ty_path ( make:: ext:: ident_path ( "Self" ) ) ) ;
104+
105+ let fn_ = make:: fn_ (
106+ strukt. visibility ( ) ,
107+ make:: name ( "new" ) ,
108+ None ,
109+ None ,
110+ params,
111+ body,
112+ Some ( ret_type) ,
113+ false ,
114+ false ,
115+ false ,
116+ )
117+ . clone_for_update ( ) ;
118+ fn_. indent ( 1 . into ( ) ) ;
119+
120+ // Add a tabstop before the name
121+ if let Some ( cap) = ctx. config . snippet_cap {
122+ if let Some ( name) = fn_. name ( ) {
123+ builder. add_tabstop_before ( cap, name) ;
125124 }
126125 }
126+
127+ // Get the mutable version of the impl to modify
128+ let impl_def = if let Some ( impl_def) = impl_def {
129+ builder. make_mut ( impl_def)
130+ } else {
131+ // Generate a new impl to add the method to
132+ let impl_def = generate_impl ( & ast:: Adt :: Struct ( strukt. clone ( ) ) ) ;
133+
134+ // Insert it after the adt
135+ let strukt = builder. make_mut ( strukt. clone ( ) ) ;
136+
137+ ted:: insert_all_raw (
138+ ted:: Position :: after ( strukt. syntax ( ) ) ,
139+ vec ! [ make:: tokens:: blank_line( ) . into( ) , impl_def. syntax( ) . clone( ) . into( ) ] ,
140+ ) ;
141+
142+ impl_def
143+ } ;
144+
145+ // Add the `new` method at the start of the impl
146+ impl_def. get_or_create_assoc_item_list ( ) . add_item_at_start ( fn_. into ( ) ) ;
127147 } )
128148}
129149
@@ -148,7 +168,9 @@ struct Empty;
148168struct Foo { empty: Empty }
149169
150170impl Foo {
151- fn $0new() -> Self { Self { empty: Empty } }
171+ fn $0new() -> Self {
172+ Self { empty: Empty }
173+ }
152174}
153175"# ,
154176 ) ;
@@ -165,7 +187,9 @@ struct Empty;
165187struct Foo { baz: String, empty: Empty }
166188
167189impl Foo {
168- fn $0new(baz: String) -> Self { Self { baz, empty: Empty } }
190+ fn $0new(baz: String) -> Self {
191+ Self { baz, empty: Empty }
192+ }
169193}
170194"# ,
171195 ) ;
@@ -182,7 +206,9 @@ enum Empty { Bar }
182206struct Foo { empty: Empty }
183207
184208impl Foo {
185- fn $0new() -> Self { Self { empty: Empty::Bar } }
209+ fn $0new() -> Self {
210+ Self { empty: Empty::Bar }
211+ }
186212}
187213"# ,
188214 ) ;
@@ -201,7 +227,9 @@ struct Empty {}
201227struct Foo { empty: Empty }
202228
203229impl Foo {
204- fn $0new(empty: Empty) -> Self { Self { empty } }
230+ fn $0new(empty: Empty) -> Self {
231+ Self { empty }
232+ }
205233}
206234"# ,
207235 ) ;
@@ -218,7 +246,9 @@ enum Empty { Bar {} }
218246struct Foo { empty: Empty }
219247
220248impl Foo {
221- fn $0new(empty: Empty) -> Self { Self { empty } }
249+ fn $0new(empty: Empty) -> Self {
250+ Self { empty }
251+ }
222252}
223253"# ,
224254 ) ;
@@ -235,7 +265,9 @@ struct Foo {$0}
235265struct Foo {}
236266
237267impl Foo {
238- fn $0new() -> Self { Self { } }
268+ fn $0new() -> Self {
269+ Self { }
270+ }
239271}
240272"# ,
241273 ) ;
@@ -248,7 +280,9 @@ struct Foo<T: Clone> {$0}
248280struct Foo<T: Clone> {}
249281
250282impl<T: Clone> Foo<T> {
251- fn $0new() -> Self { Self { } }
283+ fn $0new() -> Self {
284+ Self { }
285+ }
252286}
253287"# ,
254288 ) ;
@@ -261,7 +295,9 @@ struct Foo<'a, T: Foo<'a>> {$0}
261295struct Foo<'a, T: Foo<'a>> {}
262296
263297impl<'a, T: Foo<'a>> Foo<'a, T> {
264- fn $0new() -> Self { Self { } }
298+ fn $0new() -> Self {
299+ Self { }
300+ }
265301}
266302"# ,
267303 ) ;
@@ -274,7 +310,9 @@ struct Foo { baz: String $0}
274310struct Foo { baz: String }
275311
276312impl Foo {
277- fn $0new(baz: String) -> Self { Self { baz } }
313+ fn $0new(baz: String) -> Self {
314+ Self { baz }
315+ }
278316}
279317"# ,
280318 ) ;
@@ -287,7 +325,9 @@ struct Foo { baz: String, qux: Vec<i32> $0}
287325struct Foo { baz: String, qux: Vec<i32> }
288326
289327impl Foo {
290- fn $0new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } }
328+ fn $0new(baz: String, qux: Vec<i32>) -> Self {
329+ Self { baz, qux }
330+ }
291331}
292332"# ,
293333 ) ;
@@ -304,7 +344,9 @@ struct Foo { pub baz: String, pub qux: Vec<i32> $0}
304344struct Foo { pub baz: String, pub qux: Vec<i32> }
305345
306346impl Foo {
307- fn $0new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } }
347+ fn $0new(baz: String, qux: Vec<i32>) -> Self {
348+ Self { baz, qux }
349+ }
308350}
309351"# ,
310352 ) ;
@@ -323,7 +365,9 @@ impl Foo {}
323365struct Foo {}
324366
325367impl Foo {
326- fn $0new() -> Self { Self { } }
368+ fn $0new() -> Self {
369+ Self { }
370+ }
327371}
328372"# ,
329373 ) ;
@@ -340,7 +384,9 @@ impl Foo {
340384struct Foo {}
341385
342386impl Foo {
343- fn $0new() -> Self { Self { } }
387+ fn $0new() -> Self {
388+ Self { }
389+ }
344390
345391 fn qux(&self) {}
346392}
@@ -363,7 +409,9 @@ impl Foo {
363409struct Foo {}
364410
365411impl Foo {
366- fn $0new() -> Self { Self { } }
412+ fn $0new() -> Self {
413+ Self { }
414+ }
367415
368416 fn qux(&self) {}
369417 fn baz() -> i32 {
@@ -385,7 +433,9 @@ pub struct Foo {$0}
385433pub struct Foo {}
386434
387435impl Foo {
388- pub fn $0new() -> Self { Self { } }
436+ pub fn $0new() -> Self {
437+ Self { }
438+ }
389439}
390440"# ,
391441 ) ;
@@ -398,7 +448,9 @@ pub(crate) struct Foo {$0}
398448pub(crate) struct Foo {}
399449
400450impl Foo {
401- pub(crate) fn $0new() -> Self { Self { } }
451+ pub(crate) fn $0new() -> Self {
452+ Self { }
453+ }
402454}
403455"# ,
404456 ) ;
@@ -493,7 +545,9 @@ pub struct Source<T> {
493545}
494546
495547impl<T> Source<T> {
496- pub fn $0new(file_id: HirFileId, ast: T) -> Self { Self { file_id, ast } }
548+ pub fn $0new(file_id: HirFileId, ast: T) -> Self {
549+ Self { file_id, ast }
550+ }
497551
498552 pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> {
499553 Source { file_id: self.file_id, ast: f(self.ast) }
0 commit comments