@@ -3,8 +3,10 @@ use crate::{
33 AssistId ,
44} ;
55use ide_db:: helpers:: FamousDefs ;
6+ use itertools:: Itertools ;
7+ use stdx:: format_to;
68use syntax:: {
7- ast:: { self , Impl , NameOwner } ,
9+ ast:: { self , GenericParamsOwner , Impl , NameOwner , TypeBoundsOwner } ,
810 AstNode ,
911} ;
1012
@@ -65,23 +67,56 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext)
6567 "Generate a Default impl from a new fn" ,
6668 insert_location,
6769 move |builder| {
68- let code = default_fn_node_for_new ( impl_) ;
70+ let default_code = " fn default() -> Self {
71+ Self::new()
72+ }" ;
73+ let code = generate_trait_impl_text_from_impl ( & impl_, "Default" , default_code) ;
6974 builder. insert ( insert_location. end ( ) , code) ;
7075 } ,
7176 )
7277}
7378
74- fn default_fn_node_for_new ( impl_ : Impl ) -> String {
75- format ! (
76- "
79+ fn generate_trait_impl_text_from_impl ( impl_ : & ast:: Impl , trait_text : & str , code : & str ) -> String {
80+ let generic_params = impl_. generic_param_list ( ) ;
81+ let mut buf = String :: with_capacity ( code. len ( ) ) ;
82+ buf. push_str ( "\n \n " ) ;
83+ buf. push_str ( "impl" ) ;
84+
85+ if let Some ( generic_params) = & generic_params {
86+ let lifetimes = generic_params. lifetime_params ( ) . map ( |lt| format ! ( "{}" , lt. syntax( ) ) ) ;
87+ let type_params = generic_params. type_params ( ) . map ( |type_param| {
88+ let mut buf = String :: new ( ) ;
89+ if let Some ( it) = type_param. name ( ) {
90+ format_to ! ( buf, "{}" , it. syntax( ) ) ;
91+ }
92+ if let Some ( it) = type_param. colon_token ( ) {
93+ format_to ! ( buf, "{} " , it) ;
94+ }
95+ if let Some ( it) = type_param. type_bound_list ( ) {
96+ format_to ! ( buf, "{}" , it. syntax( ) ) ;
97+ }
98+ buf
99+ } ) ;
100+ let const_params = generic_params. const_params ( ) . map ( |t| t. syntax ( ) . to_string ( ) ) ;
101+ let generics = lifetimes. chain ( type_params) . chain ( const_params) . format ( ", " ) ;
102+ format_to ! ( buf, "<{}>" , generics) ;
103+ }
104+
105+ buf. push ( ' ' ) ;
106+ buf. push_str ( trait_text) ;
107+ buf. push_str ( " for " ) ;
108+ buf. push_str ( & impl_. self_ty ( ) . unwrap ( ) . syntax ( ) . text ( ) . to_string ( ) ) ;
109+
110+ match impl_. where_clause ( ) {
111+ Some ( where_clause) => {
112+ format_to ! ( buf, "\n {}\n {{\n {}\n }}" , where_clause, code) ;
113+ }
114+ None => {
115+ format_to ! ( buf, " {{\n {}\n }}" , code) ;
116+ }
117+ }
77118
78- impl Default for {} {{
79- fn default() -> Self {{
80- Self::new()
81- }}
82- }}" ,
83- impl_. self_ty( ) . unwrap( ) . syntax( ) . text( )
84- )
119+ buf
85120}
86121
87122fn is_default_implemented ( ctx : & AssistContext , impl_ : & Impl ) -> bool {
@@ -175,6 +210,234 @@ impl Default for Test {
175210 ) ;
176211 }
177212
213+ #[ test]
214+ fn new_function_with_generic ( ) {
215+ check_pass (
216+ r#"
217+ pub struct Foo<T> {
218+ _bar: *mut T,
219+ }
220+
221+ impl<T> Foo<T> {
222+ pub fn ne$0w() -> Self {
223+ unimplemented!()
224+ }
225+ }
226+ "# ,
227+ r#"
228+ pub struct Foo<T> {
229+ _bar: *mut T,
230+ }
231+
232+ impl<T> Foo<T> {
233+ pub fn new() -> Self {
234+ unimplemented!()
235+ }
236+ }
237+
238+ impl<T> Default for Foo<T> {
239+ fn default() -> Self {
240+ Self::new()
241+ }
242+ }
243+ "# ,
244+ ) ;
245+ }
246+
247+ #[ test]
248+ fn new_function_with_generics ( ) {
249+ check_pass (
250+ r#"
251+ pub struct Foo<T, B> {
252+ _tars: *mut T,
253+ _bar: *mut B,
254+ }
255+
256+ impl<T, B> Foo<T, B> {
257+ pub fn ne$0w() -> Self {
258+ unimplemented!()
259+ }
260+ }
261+ "# ,
262+ r#"
263+ pub struct Foo<T, B> {
264+ _tars: *mut T,
265+ _bar: *mut B,
266+ }
267+
268+ impl<T, B> Foo<T, B> {
269+ pub fn new() -> Self {
270+ unimplemented!()
271+ }
272+ }
273+
274+ impl<T, B> Default for Foo<T, B> {
275+ fn default() -> Self {
276+ Self::new()
277+ }
278+ }
279+ "# ,
280+ ) ;
281+ }
282+
283+ #[ test]
284+ fn new_function_with_generic_and_bound ( ) {
285+ check_pass (
286+ r#"
287+ pub struct Foo<T> {
288+ t: T,
289+ }
290+
291+ impl<T: From<i32>> Foo<T> {
292+ pub fn ne$0w() -> Self {
293+ Foo { t: 0.into() }
294+ }
295+ }
296+ "# ,
297+ r#"
298+ pub struct Foo<T> {
299+ t: T,
300+ }
301+
302+ impl<T: From<i32>> Foo<T> {
303+ pub fn new() -> Self {
304+ Foo { t: 0.into() }
305+ }
306+ }
307+
308+ impl<T: From<i32>> Default for Foo<T> {
309+ fn default() -> Self {
310+ Self::new()
311+ }
312+ }
313+ "# ,
314+ ) ;
315+ }
316+
317+ #[ test]
318+ fn new_function_with_generics_and_bounds ( ) {
319+ check_pass (
320+ r#"
321+ pub struct Foo<T, B> {
322+ _tars: T,
323+ _bar: B,
324+ }
325+
326+ impl<T: From<i32>, B: From<i64>> Foo<T, B> {
327+ pub fn ne$0w() -> Self {
328+ unimplemented!()
329+ }
330+ }
331+ "# ,
332+ r#"
333+ pub struct Foo<T, B> {
334+ _tars: T,
335+ _bar: B,
336+ }
337+
338+ impl<T: From<i32>, B: From<i64>> Foo<T, B> {
339+ pub fn new() -> Self {
340+ unimplemented!()
341+ }
342+ }
343+
344+ impl<T: From<i32>, B: From<i64>> Default for Foo<T, B> {
345+ fn default() -> Self {
346+ Self::new()
347+ }
348+ }
349+ "# ,
350+ ) ;
351+ }
352+
353+ #[ test]
354+ fn new_function_with_generic_and_where ( ) {
355+ check_pass (
356+ r#"
357+ pub struct Foo<T> {
358+ t: T,
359+ }
360+
361+ impl<T: From<i32>> Foo<T>
362+ where
363+ Option<T>: Debug
364+ {
365+ pub fn ne$0w() -> Self {
366+ Foo { t: 0.into() }
367+ }
368+ }
369+ "# ,
370+ r#"
371+ pub struct Foo<T> {
372+ t: T,
373+ }
374+
375+ impl<T: From<i32>> Foo<T>
376+ where
377+ Option<T>: Debug
378+ {
379+ pub fn new() -> Self {
380+ Foo { t: 0.into() }
381+ }
382+ }
383+
384+ impl<T: From<i32>> Default for Foo<T>
385+ where
386+ Option<T>: Debug
387+ {
388+ fn default() -> Self {
389+ Self::new()
390+ }
391+ }
392+ "# ,
393+ ) ;
394+ }
395+
396+ #[ test]
397+ fn new_function_with_generics_and_wheres ( ) {
398+ check_pass (
399+ r#"
400+ pub struct Foo<T, B> {
401+ _tars: T,
402+ _bar: B,
403+ }
404+
405+ impl<T: From<i32>, B: From<i64>> Foo<T, B>
406+ where
407+ Option<T>: Debug, Option<B>: Debug,
408+ {
409+ pub fn ne$0w() -> Self {
410+ unimplemented!()
411+ }
412+ }
413+ "# ,
414+ r#"
415+ pub struct Foo<T, B> {
416+ _tars: T,
417+ _bar: B,
418+ }
419+
420+ impl<T: From<i32>, B: From<i64>> Foo<T, B>
421+ where
422+ Option<T>: Debug, Option<B>: Debug,
423+ {
424+ pub fn new() -> Self {
425+ unimplemented!()
426+ }
427+ }
428+
429+ impl<T: From<i32>, B: From<i64>> Default for Foo<T, B>
430+ where
431+ Option<T>: Debug, Option<B>: Debug,
432+ {
433+ fn default() -> Self {
434+ Self::new()
435+ }
436+ }
437+ "# ,
438+ ) ;
439+ }
440+
178441 #[ test]
179442 fn new_function_with_parameters ( ) {
180443 cov_mark:: check!( new_function_with_parameters) ;
0 commit comments