pub mod regular_builder;
pub mod tokens;
pub mod type_state_builder;
pub use self::type_state_builder::generate_type_state_builder;
pub use regular_builder::generate_regular_builder;
pub use tokens::TokenGenerator;
use crate::analysis::StructAnalysis;
pub fn generate_builder(analysis: &StructAnalysis) -> syn::Result<proc_macro2::TokenStream> {
analysis.validate_for_generation()?;
if analysis.has_only_optional_fields() {
generate_regular_builder(analysis)
} else {
generate_type_state_builder(analysis)
}
}
#[derive(Debug, Clone)]
pub struct GenerationConfig {
pub include_documentation: bool,
pub include_error_guidance: bool,
pub generate_debug_impls: bool,
pub use_qualified_paths: bool,
pub const_builder: bool,
}
impl Default for GenerationConfig {
fn default() -> Self {
Self {
include_documentation: true,
include_error_guidance: true,
generate_debug_impls: true,
use_qualified_paths: true,
const_builder: false,
}
}
}
impl GenerationConfig {}
#[cfg(test)]
mod tests {
use super::*;
use crate::analysis::analyze_struct;
use syn::parse_quote;
#[test]
fn test_generate_builder_with_required_fields() {
let input = parse_quote! {
struct Example {
#[builder(required)]
name: String,
age: Option<u32>,
}
};
let analysis = analyze_struct(&input).unwrap();
let result = generate_builder(&analysis);
assert!(result.is_ok());
}
#[test]
fn test_generate_builder_with_optional_only() {
let input = parse_quote! {
struct Example {
name: Option<String>,
age: u32,
}
};
let analysis = analyze_struct(&input).unwrap();
let result = generate_builder(&analysis);
assert!(result.is_ok());
}
#[test]
fn test_generation_config_default() {
let config = GenerationConfig::default();
assert!(config.include_documentation);
assert!(config.include_error_guidance);
assert!(config.generate_debug_impls);
assert!(config.use_qualified_paths);
}
#[test]
fn test_generate_builder_with_custom_config() {
let input = parse_quote! {
struct Example {
#[builder(required)]
name: String,
}
};
let analysis = analyze_struct(&input).unwrap();
let _config = GenerationConfig::default();
let result = generate_builder(&analysis);
assert!(result.is_ok());
}
#[test]
fn test_builder_selection_logic() {
let input_with_required = parse_quote! {
struct WithRequired {
#[builder(required)]
name: String,
age: Option<u32>,
}
};
let analysis = analyze_struct(&input_with_required).unwrap();
assert!(!analysis.has_only_optional_fields());
let input_optional_only = parse_quote! {
struct OptionalOnly {
name: Option<String>,
age: u32,
}
};
let analysis = analyze_struct(&input_optional_only).unwrap();
assert!(analysis.has_only_optional_fields());
}
}