use super::{CreateSpec, QualityProfile};
use anyhow::Result;
pub struct AstBuilder {
pub(crate) profile: QualityProfile,
}
impl AstBuilder {
#[must_use]
pub fn new(profile: QualityProfile) -> Self {
Self { profile }
}
pub fn build_function(&self, spec: &CreateSpec) -> Result<String> {
let mut code = String::new();
code.push_str(&format!("/// {}\n", spec.purpose));
code.push_str("///\n");
for param in &spec.inputs {
code.push_str(&format!(
"/// * `{}` - {}\n",
param.name,
param
.description
.as_deref()
.unwrap_or("Parameter description")
));
}
code.push_str("///\n");
code.push_str(&format!(
"/// # Returns\n/// {}\n",
spec.outputs
.description
.as_deref()
.unwrap_or("Function return value")
));
if self.profile.thresholds.require_doctests {
code.push_str("///\n/// # Example\n/// ```\n");
code.push_str(&format!("/// let result = {}(", spec.name));
for (i, param) in spec.inputs.iter().enumerate() {
if i > 0 {
code.push_str(", ");
}
code.push_str(&self.generate_example_value(¶m.param_type));
}
code.push_str(");\n/// assert!(result.is_ok());\n/// ```\n");
}
code.push_str(&format!("pub fn {}(", spec.name));
for (i, param) in spec.inputs.iter().enumerate() {
if i > 0 {
code.push_str(", ");
}
code.push_str(&format!("{}: {}", param.name, param.param_type));
}
code.push_str(&format!(") -> Result<{}> {{\n", spec.outputs.param_type));
code.push_str(" // Implementation placeholder\n");
code.push_str(" todo!(\"Implementation needed\")\n");
code.push_str("}\n");
Ok(code)
}
pub fn generate_example_value(&self, param_type: &str) -> String {
match param_type {
"u32" | "i32" => "42".to_string(),
"f32" | "f64" => "3.14".to_string(),
"String" => "\"test\".to_string()".to_string(),
"&str" => "\"test\"".to_string(),
"bool" => "true".to_string(),
_ => "Default::default()".to_string(),
}
}
}