From 140075b58e936c3a03212f9e88a5625b37f75dae Mon Sep 17 00:00:00 2001 From: Aaron Dewes Date: Fri, 17 May 2024 21:50:32 +0200 Subject: [PATCH] Improve detecting whether default can be derived This checks if a struct contains a required member for which `Default` is not implemented (Enums or other structs which don't have `Default`). If it does, Default will not be derived for that struct. Signed-off-by: Aaron Dewes --- src/main.rs | 19 ++++++++++--------- src/output.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/main.rs b/src/main.rs index b1037e3..94ddf17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -246,7 +246,7 @@ impl Kopium { } self.print_docstr(&s.docs, ""); if s.is_main_container() { - self.print_derives(s); + self.print_derives(s, &structs); //root struct gets kube derives unless opted out if !self.hide_kube { println!( @@ -277,7 +277,7 @@ impl Kopium { println!("pub struct {} {{", s.name); } } else { - self.print_derives(s); + self.print_derives(s, &structs); let spec_trimmed_name = s.name.as_str().replace(&format!("{}Spec", kind), kind); if s.is_enum { println!("pub enum {} {{", spec_trimmed_name); @@ -338,23 +338,24 @@ impl Kopium { } } - fn print_derives(&self, s: &Container) { + fn print_derives(&self, s: &Container, containers: &[Container]) { let mut derives = vec!["Serialize", "Deserialize", "Clone", "Debug"]; if s.is_main_container() && !self.hide_kube { // CustomResource first for root struct derives.insert(0, "CustomResource"); } - if self.builders { + + // TypedBuilder does not work with enums + if self.builders && !s.is_enum { derives.push("TypedBuilder"); } for derive in &self.derive { - if s.is_enum && derive.derived_trait == "Default" { - // Need to drop Default from enum as this cannot be derived. - // Enum defaults need to either be manually derived - // or we can insert enum defaults - continue; + if derive.derived_trait == "Default" { + if !s.can_derive_default(containers) { + continue; + } } if derive.is_applicable_to(s) && !derives.contains(&derive.derived_trait.as_str()) { diff --git a/src/output.rs b/src/output.rs index fb25e07..daabbe0 100644 --- a/src/output.rs +++ b/src/output.rs @@ -80,6 +80,36 @@ impl Container { pub fn contains_conditions(&self) -> bool { self.members.iter().any(|m| m.type_.contains("Vec")) } + + pub fn can_derive_default(&self, containers: &[Container]) -> bool { + if self.is_enum { + // Need to drop Default from enum as this cannot be derived. + // Enum defaults need to either be manually derived + // or we can insert enum defaults + return false; + } + + for m in &self.members { + if !m.type_.contains('<') + && !m.type_.contains("::") + && m.type_ != "String" + && m.type_ != "IntOrString" + && m.type_ != "NaiveDate" + && m.type_ != "DateTime" + && m.type_.chars().next().unwrap_or_default().is_uppercase() + { + if containers + .iter() + .find(|c| c.name == m.type_) + .is_some_and(|c| !c.can_derive_default(containers)) + { + return false; + } + } + } + + true + } } impl Container {