1
1
use ide_db:: {
2
2
imports:: import_assets:: item_for_path_search, use_trivial_constructor:: use_trivial_constructor,
3
3
} ;
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
+ } ;
7
8
8
9
use crate :: {
9
- utils:: { find_impl_block_start , find_struct_impl, generate_impl_text } ,
10
+ utils:: { find_struct_impl, generate_impl } ,
10
11
AssistContext , AssistId , AssistKind , Assists ,
11
12
} ;
12
13
@@ -26,7 +27,9 @@ use crate::{
26
27
// }
27
28
//
28
29
// impl<T: Clone> Ctx<T> {
29
- // fn $0new(data: T) -> Self { Self { data } }
30
+ // fn $0new(data: T) -> Self {
31
+ // Self { data }
32
+ // }
30
33
// }
31
34
// ```
32
35
pub ( 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
46
49
47
50
let target = strukt. syntax ( ) . text_range ( ) ;
48
51
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
-
57
52
let trivial_constructors = field_list
58
53
. fields ( )
59
54
. map ( |f| {
@@ -76,54 +71,79 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
76
71
& ty,
77
72
) ?;
78
73
79
- Some ( format ! ( "{name}: { expr}" ) )
74
+ Some ( make :: record_expr_field ( make :: name_ref ( & name . text ( ) ) , Some ( expr) ) )
80
75
} )
81
76
. collect :: < Vec < _ > > ( ) ;
82
77
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 ( ) ?;
97
82
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) ;
125
124
}
126
125
}
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 ( ) ) ;
127
147
} )
128
148
}
129
149
@@ -148,7 +168,9 @@ struct Empty;
148
168
struct Foo { empty: Empty }
149
169
150
170
impl Foo {
151
- fn $0new() -> Self { Self { empty: Empty } }
171
+ fn $0new() -> Self {
172
+ Self { empty: Empty }
173
+ }
152
174
}
153
175
"# ,
154
176
) ;
@@ -165,7 +187,9 @@ struct Empty;
165
187
struct Foo { baz: String, empty: Empty }
166
188
167
189
impl Foo {
168
- fn $0new(baz: String) -> Self { Self { baz, empty: Empty } }
190
+ fn $0new(baz: String) -> Self {
191
+ Self { baz, empty: Empty }
192
+ }
169
193
}
170
194
"# ,
171
195
) ;
@@ -182,7 +206,9 @@ enum Empty { Bar }
182
206
struct Foo { empty: Empty }
183
207
184
208
impl Foo {
185
- fn $0new() -> Self { Self { empty: Empty::Bar } }
209
+ fn $0new() -> Self {
210
+ Self { empty: Empty::Bar }
211
+ }
186
212
}
187
213
"# ,
188
214
) ;
@@ -201,7 +227,9 @@ struct Empty {}
201
227
struct Foo { empty: Empty }
202
228
203
229
impl Foo {
204
- fn $0new(empty: Empty) -> Self { Self { empty } }
230
+ fn $0new(empty: Empty) -> Self {
231
+ Self { empty }
232
+ }
205
233
}
206
234
"# ,
207
235
) ;
@@ -218,7 +246,9 @@ enum Empty { Bar {} }
218
246
struct Foo { empty: Empty }
219
247
220
248
impl Foo {
221
- fn $0new(empty: Empty) -> Self { Self { empty } }
249
+ fn $0new(empty: Empty) -> Self {
250
+ Self { empty }
251
+ }
222
252
}
223
253
"# ,
224
254
) ;
@@ -235,7 +265,9 @@ struct Foo {$0}
235
265
struct Foo {}
236
266
237
267
impl Foo {
238
- fn $0new() -> Self { Self { } }
268
+ fn $0new() -> Self {
269
+ Self { }
270
+ }
239
271
}
240
272
"# ,
241
273
) ;
@@ -248,7 +280,9 @@ struct Foo<T: Clone> {$0}
248
280
struct Foo<T: Clone> {}
249
281
250
282
impl<T: Clone> Foo<T> {
251
- fn $0new() -> Self { Self { } }
283
+ fn $0new() -> Self {
284
+ Self { }
285
+ }
252
286
}
253
287
"# ,
254
288
) ;
@@ -261,7 +295,9 @@ struct Foo<'a, T: Foo<'a>> {$0}
261
295
struct Foo<'a, T: Foo<'a>> {}
262
296
263
297
impl<'a, T: Foo<'a>> Foo<'a, T> {
264
- fn $0new() -> Self { Self { } }
298
+ fn $0new() -> Self {
299
+ Self { }
300
+ }
265
301
}
266
302
"# ,
267
303
) ;
@@ -274,7 +310,9 @@ struct Foo { baz: String $0}
274
310
struct Foo { baz: String }
275
311
276
312
impl Foo {
277
- fn $0new(baz: String) -> Self { Self { baz } }
313
+ fn $0new(baz: String) -> Self {
314
+ Self { baz }
315
+ }
278
316
}
279
317
"# ,
280
318
) ;
@@ -287,7 +325,9 @@ struct Foo { baz: String, qux: Vec<i32> $0}
287
325
struct Foo { baz: String, qux: Vec<i32> }
288
326
289
327
impl 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
+ }
291
331
}
292
332
"# ,
293
333
) ;
@@ -304,7 +344,9 @@ struct Foo { pub baz: String, pub qux: Vec<i32> $0}
304
344
struct Foo { pub baz: String, pub qux: Vec<i32> }
305
345
306
346
impl 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
+ }
308
350
}
309
351
"# ,
310
352
) ;
@@ -323,7 +365,9 @@ impl Foo {}
323
365
struct Foo {}
324
366
325
367
impl Foo {
326
- fn $0new() -> Self { Self { } }
368
+ fn $0new() -> Self {
369
+ Self { }
370
+ }
327
371
}
328
372
"# ,
329
373
) ;
@@ -340,7 +384,9 @@ impl Foo {
340
384
struct Foo {}
341
385
342
386
impl Foo {
343
- fn $0new() -> Self { Self { } }
387
+ fn $0new() -> Self {
388
+ Self { }
389
+ }
344
390
345
391
fn qux(&self) {}
346
392
}
@@ -363,7 +409,9 @@ impl Foo {
363
409
struct Foo {}
364
410
365
411
impl Foo {
366
- fn $0new() -> Self { Self { } }
412
+ fn $0new() -> Self {
413
+ Self { }
414
+ }
367
415
368
416
fn qux(&self) {}
369
417
fn baz() -> i32 {
@@ -385,7 +433,9 @@ pub struct Foo {$0}
385
433
pub struct Foo {}
386
434
387
435
impl Foo {
388
- pub fn $0new() -> Self { Self { } }
436
+ pub fn $0new() -> Self {
437
+ Self { }
438
+ }
389
439
}
390
440
"# ,
391
441
) ;
@@ -398,7 +448,9 @@ pub(crate) struct Foo {$0}
398
448
pub(crate) struct Foo {}
399
449
400
450
impl Foo {
401
- pub(crate) fn $0new() -> Self { Self { } }
451
+ pub(crate) fn $0new() -> Self {
452
+ Self { }
453
+ }
402
454
}
403
455
"# ,
404
456
) ;
@@ -493,7 +545,9 @@ pub struct Source<T> {
493
545
}
494
546
495
547
impl<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
+ }
497
551
498
552
pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> {
499
553
Source { file_id: self.file_id, ast: f(self.ast) }
0 commit comments