Skip to content

Commit 696a8bf

Browse files
committed
Address comments and add more tests
Fix tests Fmt code
1 parent 3f02225 commit 696a8bf

File tree

1 file changed

+249
-25
lines changed

1 file changed

+249
-25
lines changed

crates/ide_assists/src/handlers/generate_default_from_new.rs

Lines changed: 249 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ use crate::{
33
AssistId,
44
};
55
use ide_db::helpers::FamousDefs;
6+
use itertools::Itertools;
7+
use stdx::format_to;
68
use syntax::{
7-
ast::{self, Impl, NameOwner},
9+
ast::{self, AttrsOwner, GenericParamsOwner, Impl, NameOwner, TypeBoundsOwner},
810
AstNode,
911
};
10-
use crate::utils::generate_trait_impl_text;
1112

1213
// Assist: generate_default_from_new
1314
//
@@ -60,37 +61,66 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext)
6061
}
6162

6263
let insert_location = impl_.syntax().text_range();
63-
let code = match ast::Struct::cast(impl_.self_ty().unwrap().syntax().clone()){
64-
None => {
65-
default_fn_node_for_new(impl_)
66-
}
67-
Some(strukt) => {
68-
generate_trait_impl_text(&ast::Adt::Struct(strukt),"core:default:Default"," fn default() -> Self {{
69-
Self::new()
70-
}}")
71-
}
72-
};
64+
7365
acc.add(
7466
AssistId("generate_default_from_new", crate::AssistKind::Generate),
7567
"Generate a Default impl from a new fn",
7668
insert_location,
7769
move |builder| {
70+
let default_code = " fn default() -> Self {
71+
Self::new()
72+
}";
73+
let code = generate_trait_impl_text_from_impl(&impl_, "Default", default_code);
7874
builder.insert(insert_location.end(), code);
7975
},
8076
)
8177
}
8278

83-
fn default_fn_node_for_new(impl_: Impl) -> String {
84-
format!(
85-
"
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+
impl_
84+
.attrs()
85+
.filter(|attr| attr.as_simple_call().map(|(name, _arg)| name == "cfg").unwrap_or(false))
86+
.for_each(|attr| buf.push_str(format!("{}\n", attr.to_string()).as_str()));
87+
buf.push_str("impl");
88+
89+
if let Some(generic_params) = &generic_params {
90+
let lifetimes = generic_params.lifetime_params().map(|lt| format!("{}", lt.syntax()));
91+
let type_params = generic_params.type_params().map(|type_param| {
92+
let mut buf = String::new();
93+
if let Some(it) = type_param.name() {
94+
format_to!(buf, "{}", it.syntax());
95+
}
96+
if let Some(it) = type_param.colon_token() {
97+
format_to!(buf, "{} ", it);
98+
}
99+
if let Some(it) = type_param.type_bound_list() {
100+
format_to!(buf, "{}", it.syntax());
101+
}
102+
buf
103+
});
104+
let const_params = generic_params.const_params().map(|t| t.syntax().to_string());
105+
let generics = lifetimes.chain(type_params).chain(const_params).format(", ");
106+
format_to!(buf, "<{}>", generics);
107+
}
108+
109+
buf.push(' ');
110+
buf.push_str(trait_text);
111+
buf.push_str(" for ");
112+
buf.push_str(&impl_.self_ty().unwrap().syntax().text().to_string());
113+
114+
match impl_.where_clause() {
115+
Some(where_clause) => {
116+
format_to!(buf, "\n{}\n{{\n{}\n}}", where_clause, code);
117+
}
118+
None => {
119+
format_to!(buf, " {{\n{}\n}}", code);
120+
}
121+
}
86122

87-
impl Default for {} {{
88-
fn default() -> Self {{
89-
Self::new()
90-
}}
91-
}}",
92-
impl_.self_ty().unwrap().syntax().text()
93-
)
123+
buf
94124
}
95125

96126
fn is_default_implemented(ctx: &AssistContext, impl_: &Impl) -> bool {
@@ -185,7 +215,7 @@ impl Default for Test {
185215
}
186216

187217
#[test]
188-
fn generate_default3() {
218+
fn new_function_with_generic() {
189219
check_pass(
190220
r#"
191221
pub struct Foo<T> {
@@ -194,7 +224,7 @@ pub struct Foo<T> {
194224
195225
impl<T> Foo<T> {
196226
pub fn ne$0w() -> Self {
197-
todo!()
227+
unimplemented!()
198228
}
199229
}
200230
"#,
@@ -205,7 +235,7 @@ pub struct Foo<T> {
205235
206236
impl<T> Foo<T> {
207237
pub fn new() -> Self {
208-
todo!()
238+
unimplemented!()
209239
}
210240
}
211241
@@ -218,6 +248,200 @@ impl<T> Default for Foo<T> {
218248
);
219249
}
220250

251+
#[test]
252+
fn new_function_with_generics() {
253+
check_pass(
254+
r#"
255+
pub struct Foo<T, B> {
256+
_tars: *mut T,
257+
_bar: *mut B,
258+
}
259+
260+
impl<T, B> Foo<T, B> {
261+
pub fn ne$0w() -> Self {
262+
unimplemented!()
263+
}
264+
}
265+
"#,
266+
r#"
267+
pub struct Foo<T, B> {
268+
_tars: *mut T,
269+
_bar: *mut B,
270+
}
271+
272+
impl<T, B> Foo<T, B> {
273+
pub fn new() -> Self {
274+
unimplemented!()
275+
}
276+
}
277+
278+
impl<T, B> Default for Foo<T, B> {
279+
fn default() -> Self {
280+
Self::new()
281+
}
282+
}
283+
"#,
284+
);
285+
}
286+
287+
#[test]
288+
fn new_function_with_generic_and_bound() {
289+
check_pass(
290+
r#"
291+
pub struct Foo<T> {
292+
t: T,
293+
}
294+
295+
impl<T: From<i32>> Foo<T> {
296+
pub fn ne$0w() -> Self {
297+
Foo { t: 0.into() }
298+
}
299+
}
300+
"#,
301+
r#"
302+
pub struct Foo<T> {
303+
t: T,
304+
}
305+
306+
impl<T: From<i32>> Foo<T> {
307+
pub fn new() -> Self {
308+
Foo { t: 0.into() }
309+
}
310+
}
311+
312+
impl<T: From<i32>> Default for Foo<T> {
313+
fn default() -> Self {
314+
Self::new()
315+
}
316+
}
317+
"#,
318+
);
319+
}
320+
321+
#[test]
322+
fn new_function_with_generics_and_bounds() {
323+
check_pass(
324+
r#"
325+
pub struct Foo<T, B> {
326+
_tars: T,
327+
_bar: B,
328+
}
329+
330+
impl<T: From<i32>, B: From<i64>> Foo<T, B> {
331+
pub fn ne$0w() -> Self {
332+
unimplemented!()
333+
}
334+
}
335+
"#,
336+
r#"
337+
pub struct Foo<T, B> {
338+
_tars: T,
339+
_bar: B,
340+
}
341+
342+
impl<T: From<i32>, B: From<i64>> Foo<T, B> {
343+
pub fn new() -> Self {
344+
unimplemented!()
345+
}
346+
}
347+
348+
impl<T: From<i32>, B: From<i64>> Default for Foo<T, B> {
349+
fn default() -> Self {
350+
Self::new()
351+
}
352+
}
353+
"#,
354+
);
355+
}
356+
357+
#[test]
358+
fn new_function_with_generic_and_where() {
359+
check_pass(
360+
r#"
361+
pub struct Foo<T> {
362+
t: T,
363+
}
364+
365+
impl<T: From<i32>> Foo<T>
366+
where
367+
Option<T>: Debug
368+
{
369+
pub fn ne$0w() -> Self {
370+
Foo { t: 0.into() }
371+
}
372+
}
373+
"#,
374+
r#"
375+
pub struct Foo<T> {
376+
t: T,
377+
}
378+
379+
impl<T: From<i32>> Foo<T>
380+
where
381+
Option<T>: Debug
382+
{
383+
pub fn new() -> Self {
384+
Foo { t: 0.into() }
385+
}
386+
}
387+
388+
impl<T: From<i32>> Default for Foo<T>
389+
where
390+
Option<T>: Debug
391+
{
392+
fn default() -> Self {
393+
Self::new()
394+
}
395+
}
396+
"#,
397+
);
398+
}
399+
400+
#[test]
401+
fn new_function_with_generics_and_wheres() {
402+
check_pass(
403+
r#"
404+
pub struct Foo<T, B> {
405+
_tars: T,
406+
_bar: B,
407+
}
408+
409+
impl<T: From<i32>, B: From<i64>> Foo<T, B>
410+
where
411+
Option<T>: Debug, Option<B>: Debug,
412+
{
413+
pub fn ne$0w() -> Self {
414+
unimplemented!()
415+
}
416+
}
417+
"#,
418+
r#"
419+
pub struct Foo<T, B> {
420+
_tars: T,
421+
_bar: B,
422+
}
423+
424+
impl<T: From<i32>, B: From<i64>> Foo<T, B>
425+
where
426+
Option<T>: Debug, Option<B>: Debug,
427+
{
428+
pub fn new() -> Self {
429+
unimplemented!()
430+
}
431+
}
432+
433+
impl<T: From<i32>, B: From<i64>> Default for Foo<T, B>
434+
where
435+
Option<T>: Debug, Option<B>: Debug,
436+
{
437+
fn default() -> Self {
438+
Self::new()
439+
}
440+
}
441+
"#,
442+
);
443+
}
444+
221445
#[test]
222446
fn new_function_with_parameters() {
223447
cov_mark::check!(new_function_with_parameters);

0 commit comments

Comments
 (0)