use super::tao::TaoConfig;
use super::util::{add_assert, new_kb_test};
use crate::codegen::template::basic::{
AppendedFragment, AtomicFragment, FileFragment, ItemDeclarationAPI,
};
use crate::codegen::StructConfig;
use indoc::formatdoc;
use std::cell::RefCell;
use std::rc::Rc;
#[derive(Default)]
pub struct AttributeFormatConfig {
pub tao_cfg: TaoConfig,
pub owner_type: StructConfig,
pub owner_form: StructConfig,
pub value_type: StructConfig,
pub value_form: StructConfig,
pub owner_into_archetype: String,
pub value_into_archetype: String,
}
fn attribute_fragment(cfg: &AttributeFormatConfig) -> AtomicFragment {
AtomicFragment {
imports: vec![
"zamm_yin::tao::relation::attribute::AttributeTrait".to_owned(),
cfg.owner_form.import.clone(),
cfg.value_form.import.clone(),
],
atom: formatdoc! {r#"
impl AttributeTrait for {name} {{
type OwnerForm = {owner_form};
type ValueForm = {value_form};
}}"#, name = cfg.tao_cfg.this.name,
owner_form = cfg.owner_form.name,
value_form = cfg.value_form.name,
},
}
}
fn attribute_test_fragment(cfg: &AttributeFormatConfig) -> AppendedFragment {
let mut imports = vec![
"zamm_yin::tao::archetype::ArchetypeFormTrait".to_owned(),
"zamm_yin::tao::archetype::AttributeArchetypeFormTrait".to_owned(),
];
if cfg.owner_type.name != cfg.owner_form.name {
imports.push(cfg.owner_type.import.clone());
}
if cfg.value_type.name != cfg.value_form.name {
imports.push(cfg.value_type.import.clone());
}
let mut test_frag = AppendedFragment::default();
let name = &cfg.tao_cfg.this.name;
let check_attribute_constraints = new_kb_test(&mut test_frag, "check_attribute_constraints");
check_attribute_constraints
.borrow_mut()
.add_attribute("allow(clippy::useless_conversion)".to_owned());
add_assert(
&check_attribute_constraints,
format!("{}::archetype().owner_archetype()", name),
format!(
"{owner_type}::archetype(){owner_into_archetype}",
owner_type = cfg.owner_type.name,
owner_into_archetype = cfg.owner_into_archetype,
),
);
add_assert(
&check_attribute_constraints,
format!("{}::archetype().value_archetype()", name),
format!(
"{value_type}::archetype(){value_into_archetype}",
value_type = cfg.value_type.name,
value_into_archetype = cfg.value_into_archetype,
),
);
test_frag.append(Rc::new(RefCell::new(AtomicFragment {
imports,
atom: formatdoc! {r#"
#[test]
fn get_owner() {{
initialize_kb();
let mut instance = {name}::new();
let owner_of_instance = {owner_type}::new();
instance.set_owner(&owner_of_instance);
assert_eq!(instance.owner(), Some(owner_of_instance));
assert_eq!(instance.value(), None);
}}
#[test]
fn get_value() {{
initialize_kb();
let mut instance = {name}::new();
let value_of_instance = {value_type}::new();
instance.set_value(&value_of_instance);
assert_eq!(instance.owner(), None);
assert_eq!(instance.value(), Some(value_of_instance));
}}"#,
name = cfg.tao_cfg.this.name,
owner_type = cfg.owner_type.name,
value_type = cfg.value_type.name,
},
})));
test_frag
}
pub fn add_attr_fragments(cfg: &AttributeFormatConfig, file: &mut FileFragment) {
file.append(Rc::new(RefCell::new(attribute_fragment(cfg))));
file.append_test(Rc::new(RefCell::new(attribute_test_fragment(cfg))));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_attribute_generation() {
let mut f = FileFragment::new();
add_attr_fragments(
&AttributeFormatConfig {
tao_cfg: TaoConfig {
this: StructConfig {
name: "MyNewAttr".to_owned(),
..StructConfig::default()
},
parent_name: "MyAttr".to_owned(),
archetype: StructConfig::new("crate::AttributeArchetype".to_owned()),
..TaoConfig::default()
},
owner_type: StructConfig {
name: "MyOwner".to_owned(),
import: "zamm_yin::tao::MyOwner".to_owned(),
},
owner_form: StructConfig {
name: "MyOwner".to_owned(),
import: "zamm_yin::tao::MyOwner".to_owned(),
},
value_type: StructConfig {
name: "MyValue".to_owned(),
import: "zamm_yin::tao::MyValue".to_owned(),
},
value_form: StructConfig {
name: "MyValue".to_owned(),
import: "zamm_yin::tao::MyValue".to_owned(),
},
owner_into_archetype: ".as_archetype()".to_owned(),
value_into_archetype: ".as_archetype()".to_owned(),
},
&mut f,
);
let code = f.generate_code();
assert!(code.contains("AttributeArchetype"));
assert!(code.contains("type OwnerForm = MyOwner"));
assert!(code.contains("type ValueForm = MyValue"));
assert!(code.contains("check_attribute_constraints"));
assert!(code.contains(
"assert_eq!(
MyNewAttr::archetype().owner_archetype(),
MyOwner::archetype().as_archetype()
)"
));
}
}