]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/generate_default_from_new.rs
9592876b43eda6c71e2af92ca0238eeea52badab
[rust.git] / crates / ide_assists / src / handlers / generate_default_from_new.rs
1 use crate::{
2     assist_context::{AssistContext, Assists},
3     AssistId,
4 };
5 use syntax::{
6     ast::{self, Impl, NameOwner},
7     AstNode,
8 };
9 use test_utils::mark;
10
11 // Assist: generate_default_from_new
12 //
13 // Generates default implementation from new method.
14 //
15 // ```
16 // struct Example { _inner: () }
17 //
18 // impl Example {
19 //     pub fn n$0ew() -> Self {
20 //         Self { _inner: () }
21 //     }
22 // }
23 // ```
24 // ->
25 // ```
26 // struct Example { _inner: () }
27 //
28 // impl Example {
29 //     pub fn new() -> Self {
30 //         Self { _inner: () }
31 //     }
32 // }
33 //
34 // impl Default for Example {
35 //     fn default() -> Self {
36 //         Self::new()
37 //     }
38 // }
39 // ```
40 pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
41     let fn_node = ctx.find_node_at_offset::<ast::Fn>()?;
42     let fn_name = fn_node.name()?;
43
44     if fn_name.text() != "new" {
45         mark::hit!(other_function_than_new);
46         return None;
47     }
48
49     if fn_node.param_list()?.params().next().is_some() {
50         mark::hit!(new_function_with_parameters);
51         return None;
52     }
53
54     let impl_ = fn_node.syntax().ancestors().into_iter().find_map(ast::Impl::cast)?;
55
56     let insert_location = impl_.syntax().text_range();
57
58     acc.add(
59         AssistId("generate_default_from_new", crate::AssistKind::Generate),
60         "Generate a Default impl from a new fn",
61         insert_location,
62         move |builder| {
63             let code = default_fn_node_for_new(impl_);
64             builder.insert(insert_location.end(), code);
65         },
66     )
67 }
68
69 fn default_fn_node_for_new(impl_: Impl) -> String {
70     format!(
71         "
72
73 impl Default for {} {{
74     fn default() -> Self {{
75         Self::new()
76     }}
77 }}",
78         impl_.self_ty().unwrap().syntax().text()
79     )
80 }
81
82 #[cfg(test)]
83 mod tests {
84     use crate::tests::{check_assist, check_assist_not_applicable};
85
86     use super::*;
87
88     #[test]
89     fn generate_default() {
90         check_assist(
91             generate_default_from_new,
92             r#"
93 struct Example { _inner: () }
94
95 impl Example {
96     pub fn ne$0w() -> Self {
97         Self { _inner: () }
98     }
99 }
100
101 fn main() {}
102 "#,
103             r#"
104 struct Example { _inner: () }
105
106 impl Example {
107     pub fn new() -> Self {
108         Self { _inner: () }
109     }
110 }
111
112 impl Default for Example {
113     fn default() -> Self {
114         Self::new()
115     }
116 }
117
118 fn main() {}
119 "#,
120         );
121     }
122
123     #[test]
124     fn generate_default2() {
125         check_assist(
126             generate_default_from_new,
127             r#"
128 struct Test { value: u32 }
129
130 impl Test {
131     pub fn ne$0w() -> Self {
132         Self { value: 0 }
133     }
134 }
135 "#,
136             r#"
137 struct Test { value: u32 }
138
139 impl Test {
140     pub fn new() -> Self {
141         Self { value: 0 }
142     }
143 }
144
145 impl Default for Test {
146     fn default() -> Self {
147         Self::new()
148     }
149 }
150 "#,
151         );
152     }
153
154     #[test]
155     fn new_function_with_parameters() {
156         mark::check!(new_function_with_parameters);
157         check_assist_not_applicable(
158             generate_default_from_new,
159             r#"
160 struct Example { _inner: () }
161
162 impl Example {
163     pub fn $0new(value: ()) -> Self {
164         Self { _inner: value }
165     }
166 }
167 "#,
168         );
169     }
170
171     #[test]
172     fn other_function_than_new() {
173         mark::check!(other_function_than_new);
174         check_assist_not_applicable(
175             generate_default_from_new,
176             r#"
177 struct Example { _inner: () }
178
179 impl Exmaple {
180     pub fn a$0dd() -> Self {
181         Self { _inner: () }
182     }
183 }
184
185 "#,
186         );
187     }
188
189     //     #[test]
190     //     fn default_block_is_already_present() {
191     //         check_assist_not_applicable(generate_default_from_new,
192     //         r#"
193     // struct Example { _inner: () }
194
195     // impl Exmaple {
196     //     pub fn n$0ew() -> Self {
197     //         Self { _inner: () }
198     //     }
199     // }
200
201     // impl Default for Example {
202     //     fn default() -> Self {
203     //         Self::new()
204     //     }
205     // }
206     // "#,
207     //         );
208     //     }
209
210     #[test]
211     fn standalone_new_function() {
212         check_assist_not_applicable(
213             generate_default_from_new,
214             r#"
215 fn n$0ew() -> u32 {
216     0
217 }
218 "#,
219         );
220     }
221
222     #[test]
223     fn multiple_struct_blocks() {
224         check_assist(
225             generate_default_from_new,
226             r#"
227 struct Example { _inner: () }
228 struct Test { value: u32 }
229
230 impl Example {
231     pub fn new$0() -> Self {
232         Self { _inner: () }
233     }
234 }
235 "#,
236             r#"
237 struct Example { _inner: () }
238 struct Test { value: u32 }
239
240 impl Example {
241     pub fn new() -> Self {
242         Self { _inner: () }
243     }
244 }
245
246 impl Default for Example {
247     fn default() -> Self {
248         Self::new()
249     }
250 }
251 "#,
252         );
253     }
254
255     #[test]
256     fn when_struct_is_after_impl() {
257         check_assist(
258             generate_default_from_new,
259             r#"
260 impl Example {
261     pub fn $0new() -> Self {
262         Self { _inner: () }
263     }
264 }
265
266 struct Example { _inner: () }
267 "#,
268             r#"
269 impl Example {
270     pub fn new() -> Self {
271         Self { _inner: () }
272     }
273 }
274
275 impl Default for Example {
276     fn default() -> Self {
277         Self::new()
278     }
279 }
280
281 struct Example { _inner: () }
282 "#,
283         );
284     }
285 }