alef 0.115.9

Opinionated polyglot binding generator for Rust libraries
Documentation
use crate::backends::csharp::type_map::csharp_type;
use crate::codegen::naming::{csharp_variant_name, to_csharp_name};
use crate::core::ir::{EnumDef, EnumVariant, FieldDef};

pub(crate) fn variant_field_type(enum_def: &EnumDef, field: &FieldDef) -> String {
    let ty = if field.sanitized && field.type_rust_path.is_some() {
        "object".to_string()
    } else {
        csharp_type(&field.ty).to_string()
    };
    let ty = if field.optional && !ty.ends_with('?') {
        format!("{ty}?")
    } else {
        ty
    };
    if enum_def
        .variants
        .iter()
        .any(|variant| ty.starts_with(&format!("{}<", csharp_variant_name(&variant.name))))
    {
        ty.replace("List<", "global::System.Collections.Generic.List<")
            .replace("Dictionary<", "global::System.Collections.Generic.Dictionary<")
    } else {
        ty
    }
}

pub(crate) fn variant_field_name(enum_def: &EnumDef, variant: &EnumVariant, field: &FieldDef) -> String {
    let public = to_csharp_name(field.name.trim_start_matches('_'));
    let clashes = public == csharp_variant_name(&variant.name)
        || public == variant_field_type(enum_def, field)
        || enum_def
            .variants
            .iter()
            .any(|other| csharp_variant_name(&other.name) == public);
    if super::super::is_tuple_field(field) || clashes {
        "Value".to_string()
    } else {
        public
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::core::ir::TypeRef;

    #[test]
    fn collision_policy_matches_released_properties_without_using_wire_names() {
        let mut enum_def = EnumDef {
            variants: vec![
                EnumVariant {
                    name: "Text".into(),
                    ..Default::default()
                },
                EnumVariant {
                    name: "Other".into(),
                    ..Default::default()
                },
            ],
            ..Default::default()
        };
        for (name, ty, expected) in [
            ("text", TypeRef::String, "Value"),
            ("other", TypeRef::String, "Value"),
            ("details", TypeRef::Named("Details".into()), "Value"),
            ("caption", TypeRef::String, "Caption"),
            ("_0", TypeRef::String, "Value"),
        ] {
            let field = FieldDef {
                name: name.into(),
                ty,
                serde_rename: Some("wire_only".into()),
                ..Default::default()
            };
            enum_def.variants[0].fields = vec![field.clone()];
            assert_eq!(variant_field_name(&enum_def, &enum_def.variants[0], &field), expected);
        }
    }
}