aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists')
-rw-r--r--crates/ide_assists/src/handlers/generate_default_from_new.rs115
1 files changed, 97 insertions, 18 deletions
diff --git a/crates/ide_assists/src/handlers/generate_default_from_new.rs b/crates/ide_assists/src/handlers/generate_default_from_new.rs
index 9592876b4..2df5adc85 100644
--- a/crates/ide_assists/src/handlers/generate_default_from_new.rs
+++ b/crates/ide_assists/src/handlers/generate_default_from_new.rs
@@ -2,6 +2,7 @@ use crate::{
2 assist_context::{AssistContext, Assists}, 2 assist_context::{AssistContext, Assists},
3 AssistId, 3 AssistId,
4}; 4};
5use hir::TypeRef;
5use syntax::{ 6use syntax::{
6 ast::{self, Impl, NameOwner}, 7 ast::{self, Impl, NameOwner},
7 AstNode, 8 AstNode,
@@ -52,6 +53,9 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext)
52 } 53 }
53 54
54 let impl_ = fn_node.syntax().ancestors().into_iter().find_map(ast::Impl::cast)?; 55 let impl_ = fn_node.syntax().ancestors().into_iter().find_map(ast::Impl::cast)?;
56 if is_default_implemented(ctx, &impl_).is_some() {
57 return None;
58 }
55 59
56 let insert_location = impl_.syntax().text_range(); 60 let insert_location = impl_.syntax().text_range();
57 61
@@ -79,6 +83,21 @@ impl Default for {} {{
79 ) 83 )
80} 84}
81 85
86fn is_default_implemented(ctx: &AssistContext, impl_: &Impl) -> Option<bool> {
87 let db = ctx.sema.db;
88 let module = impl_.syntax().parent()?;
89 let sema_scope = ctx.sema.scope(&module);
90 let impls = sema_scope.module()?.impl_defs(db);
91 let mut name = None;
92 for i in impls {
93 if let Some(TypeRef::Path(p)) = i.target_trait(db) {
94 name = p.segments().iter().map(|s| s.name.to_string()).find(|n| n == "Default");
95 }
96 }
97
98 name.map(|n| !n.is_empty())
99}
100
82#[cfg(test)] 101#[cfg(test)]
83mod tests { 102mod tests {
84 use crate::tests::{check_assist, check_assist_not_applicable}; 103 use crate::tests::{check_assist, check_assist_not_applicable};
@@ -186,26 +205,27 @@ impl Exmaple {
186 ); 205 );
187 } 206 }
188 207
189 // #[test] 208 #[test]
190 // fn default_block_is_already_present() { 209 fn default_block_is_already_present() {
191 // check_assist_not_applicable(generate_default_from_new, 210 check_assist_not_applicable(
192 // r#" 211 generate_default_from_new,
193 // struct Example { _inner: () } 212 r#"
213struct Example { _inner: () }
194 214
195 // impl Exmaple { 215impl Exmaple {
196 // pub fn n$0ew() -> Self { 216 pub fn n$0ew() -> Self {
197 // Self { _inner: () } 217 Self { _inner: () }
198 // } 218 }
199 // } 219}
200 220
201 // impl Default for Example { 221impl Default for Example {
202 // fn default() -> Self { 222 fn default() -> Self {
203 // Self::new() 223 Self::new()
204 // } 224 }
205 // } 225}
206 // "#, 226"#,
207 // ); 227 );
208 // } 228 }
209 229
210 #[test] 230 #[test]
211 fn standalone_new_function() { 231 fn standalone_new_function() {
@@ -282,4 +302,63 @@ struct Example { _inner: () }
282"#, 302"#,
283 ); 303 );
284 } 304 }
305
306 #[test]
307 fn struct_in_module() {
308 check_assist(
309 generate_default_from_new,
310 r#"
311mod test {
312 struct Example { _inner: () }
313
314 impl Example {
315 pub fn n$0ew() -> Self {
316 Self { _inner: () }
317 }
318 }
319}
320"#,
321 r#"
322mod test {
323 struct Example { _inner: () }
324
325 impl Example {
326 pub fn new() -> Self {
327 Self { _inner: () }
328 }
329 }
330
331impl Default for Example {
332 fn default() -> Self {
333 Self::new()
334 }
335}
336}
337"#,
338 );
339 }
340
341 #[test]
342 fn struct_in_module_with_default() {
343 check_assist_not_applicable(
344 generate_default_from_new,
345 r#"
346mod test {
347 struct Example { _inner: () }
348
349 impl Example {
350 pub fn n$0ew() -> Self {
351 Self { _inner: () }
352 }
353 }
354
355 impl Default for Example {
356 fn default() -> Self {
357 Self::new()
358 }
359 }
360}
361"#,
362 );
363 }
285} 364}