From e666d6297ee2758cdaf3994a734c808e5f072a57 Mon Sep 17 00:00:00 2001 From: Paolo Borelli Date: Sun, 26 Feb 2023 11:38:30 +0100 Subject: [PATCH] Refactor `impl Default` generation Move the detection of a default constructor function in the analysis. Move the logic about using Object::new into object. --- src/analysis/info_base.rs | 16 ++++++++++++- src/codegen/general.rs | 50 ++++++++++----------------------------- src/codegen/object.rs | 30 ++++++++++++++++------- src/codegen/record.rs | 4 +++- 4 files changed, 53 insertions(+), 47 deletions(-) diff --git a/src/analysis/info_base.rs b/src/analysis/info_base.rs index fdece4b1f..de245d7d3 100644 --- a/src/analysis/info_base.rs +++ b/src/analysis/info_base.rs @@ -1,5 +1,5 @@ use super::{imports::Imports, *}; -use crate::{codegen::Visibility, library, version::Version}; +use crate::{codegen::Visibility, config::gobjects::GStatus, library, version::Version}; #[derive(Debug, Default)] pub struct InfoBase { @@ -38,4 +38,18 @@ impl InfoBase { .filter(|f| f.status.need_generate() && f.kind == library::FunctionKind::Function) .collect() } + + pub fn default_constructor(&self) -> Option<&functions::Info> { + self.functions.iter().find(|f| { + !f.hidden + && f.status.need_generate() + && f.kind == library::FunctionKind::Constructor + && f.status == GStatus::Generate + // For now we only look for new() with no params + && f.name == "new" + && f.parameters.rust_parameters.is_empty() + // Cannot generate Default implementation for Option<> + && f.ret.parameter.as_ref().map_or(false, |x| !*x.lib_par.nullable) + }) + } } diff --git a/src/codegen/general.rs b/src/codegen/general.rs index c2ee67474..e680495dc 100644 --- a/src/codegen/general.rs +++ b/src/codegen/general.rs @@ -966,47 +966,23 @@ pub fn write_vec(w: &mut dyn Write, v: &[T]) -> Result<()> { Ok(()) } -pub fn declare_default_from_new( +pub fn declare_default( w: &mut dyn Write, env: &Env, name: &str, - functions: &[analysis::functions::Info], - has_builder: bool, + func: &analysis::functions::Info, ) -> Result<()> { - if let Some(func) = functions.iter().find(|f| { - !f.hidden - && f.status.need_generate() - && f.name == "new" - // Cannot generate Default implementation for Option<> - && f.ret.parameter.as_ref().map_or(false, |x| !*x.lib_par.nullable) - }) { - if func.parameters.rust_parameters.is_empty() { - writeln!(w)?; - version_condition(w, env, None, func.version, false, 0)?; - writeln!( - w, - "impl Default for {name} {{ - fn default() -> Self {{ - Self::new() - }} - }}" - )?; - } else if has_builder { - // create an alternative default implementation the uses `glib::object::Object::new()` - writeln!(w)?; - version_condition(w, env, None, func.version, false, 0)?; - writeln!( - w, - "impl Default for {name} {{ - fn default() -> Self {{ - glib::object::Object::new::() - }} - }}" - )?; - } - } - - Ok(()) + writeln!(w)?; + version_condition(w, env, None, func.version, false, 0)?; + writeln!( + w, + "impl Default for {name} {{ + fn default() -> Self {{ + Self::{}() + }} + }}", + &func.name + ) } /// Escapes string in format suitable for placing inside double quotes. diff --git a/src/codegen/object.rs b/src/codegen/object.rs index 3d05d5418..a398586df 100644 --- a/src/codegen/object.rs +++ b/src/codegen/object.rs @@ -274,14 +274,7 @@ pub fn generate( } writeln!(w, "}}")?; - - general::declare_default_from_new( - w, - env, - &analysis.name, - &analysis.functions, - has_builder_properties(&analysis.builder_properties), - )?; + generate_default(w, env, analysis)?; } trait_impls::generate( @@ -340,6 +333,27 @@ pub fn generate( Ok(()) } +fn generate_default(w: &mut dyn Write, env: &Env, analysis: &analysis::object::Info) -> Result<()> { + let name = &analysis.name; + if let Some(func) = analysis.default_constructor() { + general::declare_default(w, env, name, func) + } else if has_builder_properties(&analysis.builder_properties) { + // create an alternative default implementation the uses `glib::object::Object::new()` + writeln!(w)?; + version_condition(w, env, None, analysis.version, false, 0)?; + writeln!( + w, + "impl Default for {name} {{ + fn default() -> Self {{ + glib::object::Object::new::() + }} + }}" + ) + } else { + Ok(()) + } +} + fn generate_builder(w: &mut dyn Write, env: &Env, analysis: &analysis::object::Info) -> Result<()> { let glib_crate_name = if env.namespaces.is_glib_crate { "crate" diff --git a/src/codegen/record.rs b/src/codegen/record.rs index c06f6b119..ea6cb5396 100644 --- a/src/codegen/record.rs +++ b/src/codegen/record.rs @@ -113,7 +113,9 @@ pub fn generate(w: &mut dyn Write, env: &Env, analysis: &analysis::record::Info) writeln!(w, "}}")?; } - general::declare_default_from_new(w, env, &analysis.name, &analysis.functions, false)?; + if let Some(func) = analysis.default_constructor() { + general::declare_default(w, env, &analysis.name, func)?; + } trait_impls::generate( w,