Skip to content

Commit b824588

Browse files
bors[bot]0xPoe
andauthored
Merge #8845
8845: Generate the impl block via generate_trait_impl_text_from_impl r=Veykril a=hi-rustin Try to close #8827 Co-authored-by: hi-rustin <[email protected]>
2 parents ef6df1d + f5ea2a2 commit b824588

File tree

1 file changed

+275
-12
lines changed

1 file changed

+275
-12
lines changed

crates/ide_assists/src/handlers/generate_default_from_new.rs

Lines changed: 275 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ 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, 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

87122
fn 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

Comments
 (0)