diff --git a/yaserde/tests/deserializer.rs b/yaserde/tests/deserializer.rs index 0f96078..fbc8612 100644 --- a/yaserde/tests/deserializer.rs +++ b/yaserde/tests/deserializer.rs @@ -345,6 +345,45 @@ fn de_attributes_complex() { ); } +#[test] +fn de_attributes_with_same_name_field() { + init(); + + #[derive(Default, YaDeserialize, PartialEq, Debug)] + pub struct Struct { + #[yaserde(attribute, rename = "content")] + attribute: Option, + content: Option, + } + + convert_and_validate!( + r#""#, + Struct, + Struct { + attribute: None, + content: None + } + ); + + convert_and_validate!( + r#""#, + Struct, + Struct { + attribute: Some("attribute".to_string()), + content: None + } + ); + + convert_and_validate!( + r#"Field"#, + Struct, + Struct { + attribute: Some("attribute".to_string()), + content: Some("Field".to_string()) + } + ); +} + #[test] fn de_rename() { init(); diff --git a/yaserde/tests/flatten.rs b/yaserde/tests/flatten.rs index a37e267..34f9c51 100644 --- a/yaserde/tests/flatten.rs +++ b/yaserde/tests/flatten.rs @@ -196,7 +196,6 @@ fn flatten_attribute_and_child() { struct Node { #[yaserde(flatten)] base: Base, - #[yaserde(child)] value: StringValue, } @@ -235,7 +234,6 @@ fn flatten_name_in_unknown_child() { pub struct Node { #[yaserde(flatten)] base: Base, - #[yaserde(child)] value: Value, } diff --git a/yaserde_derive/src/common/field.rs b/yaserde_derive/src/common/field.rs index b8daff0..ec5e5ba 100644 --- a/yaserde_derive/src/common/field.rs +++ b/yaserde_derive/src/common/field.rs @@ -90,9 +90,15 @@ impl YaSerdeField { }, ); + let attribute = self + .attributes + .attribute + .then_some("Attribute_".to_string()) + .unwrap_or_default(); + Ident::new( &format!( - "__Visitor_{}_{}", + "__Visitor_{attribute}{}_{}", label.replace('.', "_").to_upper_camel_case(), struct_id ), diff --git a/yaserde_derive/src/de/expand_struct.rs b/yaserde_derive/src/de/expand_struct.rs index 2c9d7a1..a33aeab 100644 --- a/yaserde_derive/src/de/expand_struct.rs +++ b/yaserde_derive/src/de/expand_struct.rs @@ -1,6 +1,7 @@ -use crate::common::{Field, YaSerdeAttribute, YaSerdeField}; -use crate::de::build_default_value::build_default_value; -use heck::ToUpperCamelCase; +use crate::{ + common::{Field, YaSerdeAttribute, YaSerdeField}, + de::build_default_value::build_default_value, +}; use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{DataStruct, Ident}; @@ -142,7 +143,7 @@ pub fn parse( .fields .iter() .map(|field| YaSerdeField::new(field.clone())) - .filter(|field| !field.is_attribute() || !field.is_flatten()) + .filter(|field| !field.is_attribute() && !field.is_flatten()) .filter_map(|field| { let value_label = field.get_value_label(); let label_name = field.renamed_label_without_namespace(); @@ -225,7 +226,7 @@ pub fn parse( .filter_map(|field| { let label = field.get_value_label(); let label_name = field.renamed_label_without_namespace(); - let visitor_label = build_visitor_ident(&label_name, field.get_span(), None); + let visitor_label = field.get_visitor_ident(None); let visit = |action: &TokenStream, visitor: &Ident, visitor_label: &Ident| { Some(quote! { @@ -267,7 +268,7 @@ pub fn parse( visit( &action, &Ident::new("visit_str", Span::call_site()), - &build_visitor_ident(&label_name, field.get_span(), Some(&struct_name)), + &field.get_visitor_ident(Some(&struct_name)), ) }; @@ -294,7 +295,7 @@ pub fn parse( Field::FieldStruct { struct_name } => visit_vec( "e! { .push(value) }, &Ident::new("visit_str", field.get_span()), - &build_visitor_ident(&label_name, field.get_span(), Some(struct_name)), + &field.get_visitor_ident(Some(struct_name)), ), Field::FieldOption { .. } | Field::FieldVec { .. } => unimplemented!("Not supported"), simple_type => visit_vec( @@ -463,7 +464,7 @@ fn build_call_visitor( ) -> Option { let value_label = field.get_value_label(); let label_name = field.renamed_label_without_namespace(); - let visitor_label = build_visitor_ident(&label_name, field.get_span(), None); + let visitor_label = field.get_visitor_ident(None); let namespaces_matching = field.get_namespace_matching( root_attributes, @@ -494,28 +495,6 @@ fn build_call_visitor( }) } -fn build_visitor_ident(label: &str, span: Span, struct_name: Option<&syn::Path>) -> Ident { - let struct_id = struct_name.map_or_else( - || "".to_string(), - |struct_name| { - struct_name - .segments - .iter() - .map(|s| s.ident.to_string()) - .collect() - }, - ); - - Ident::new( - &format!( - "__Visitor_{}_{}", - label.replace('.', "_").to_upper_camel_case(), - struct_id - ), - span, - ) -} - fn build_code_for_unused_xml_events( call_flatten_visitors: &TokenStream, ) -> (