Merge pull request #174 from media-io/fix_same_field_name
fix: support attribute and field with same name
This commit is contained in:
commit
82b5de86ed
@ -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<String>,
|
||||||
|
content: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
convert_and_validate!(
|
||||||
|
r#"<Struct />"#,
|
||||||
|
Struct,
|
||||||
|
Struct {
|
||||||
|
attribute: None,
|
||||||
|
content: None
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
convert_and_validate!(
|
||||||
|
r#"<Struct content="attribute" />"#,
|
||||||
|
Struct,
|
||||||
|
Struct {
|
||||||
|
attribute: Some("attribute".to_string()),
|
||||||
|
content: None
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
convert_and_validate!(
|
||||||
|
r#"<Struct content="attribute"><content>Field</content></Struct>"#,
|
||||||
|
Struct,
|
||||||
|
Struct {
|
||||||
|
attribute: Some("attribute".to_string()),
|
||||||
|
content: Some("Field".to_string())
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn de_rename() {
|
fn de_rename() {
|
||||||
init();
|
init();
|
||||||
|
|||||||
@ -196,7 +196,6 @@ fn flatten_attribute_and_child() {
|
|||||||
struct Node {
|
struct Node {
|
||||||
#[yaserde(flatten)]
|
#[yaserde(flatten)]
|
||||||
base: Base,
|
base: Base,
|
||||||
#[yaserde(child)]
|
|
||||||
value: StringValue,
|
value: StringValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,7 +234,6 @@ fn flatten_name_in_unknown_child() {
|
|||||||
pub struct Node {
|
pub struct Node {
|
||||||
#[yaserde(flatten)]
|
#[yaserde(flatten)]
|
||||||
base: Base,
|
base: Base,
|
||||||
#[yaserde(child)]
|
|
||||||
value: Value,
|
value: Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -90,9 +90,15 @@ impl YaSerdeField {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let attribute = self
|
||||||
|
.attributes
|
||||||
|
.attribute
|
||||||
|
.then_some("Attribute_".to_string())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
Ident::new(
|
Ident::new(
|
||||||
&format!(
|
&format!(
|
||||||
"__Visitor_{}_{}",
|
"__Visitor_{attribute}{}_{}",
|
||||||
label.replace('.', "_").to_upper_camel_case(),
|
label.replace('.', "_").to_upper_camel_case(),
|
||||||
struct_id
|
struct_id
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
|
use crate::{
|
||||||
use crate::de::build_default_value::build_default_value;
|
common::{Field, YaSerdeAttribute, YaSerdeField},
|
||||||
use heck::ToUpperCamelCase;
|
de::build_default_value::build_default_value,
|
||||||
|
};
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{DataStruct, Ident};
|
use syn::{DataStruct, Ident};
|
||||||
@ -142,7 +143,7 @@ pub fn parse(
|
|||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field| YaSerdeField::new(field.clone()))
|
.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| {
|
.filter_map(|field| {
|
||||||
let value_label = field.get_value_label();
|
let value_label = field.get_value_label();
|
||||||
let label_name = field.renamed_label_without_namespace();
|
let label_name = field.renamed_label_without_namespace();
|
||||||
@ -225,7 +226,7 @@ pub fn parse(
|
|||||||
.filter_map(|field| {
|
.filter_map(|field| {
|
||||||
let label = field.get_value_label();
|
let label = field.get_value_label();
|
||||||
let label_name = field.renamed_label_without_namespace();
|
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| {
|
let visit = |action: &TokenStream, visitor: &Ident, visitor_label: &Ident| {
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
@ -267,7 +268,7 @@ pub fn parse(
|
|||||||
visit(
|
visit(
|
||||||
&action,
|
&action,
|
||||||
&Ident::new("visit_str", Span::call_site()),
|
&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(
|
Field::FieldStruct { struct_name } => visit_vec(
|
||||||
"e! { .push(value) },
|
"e! { .push(value) },
|
||||||
&Ident::new("visit_str", field.get_span()),
|
&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"),
|
Field::FieldOption { .. } | Field::FieldVec { .. } => unimplemented!("Not supported"),
|
||||||
simple_type => visit_vec(
|
simple_type => visit_vec(
|
||||||
@ -463,7 +464,7 @@ fn build_call_visitor(
|
|||||||
) -> Option<TokenStream> {
|
) -> Option<TokenStream> {
|
||||||
let value_label = field.get_value_label();
|
let value_label = field.get_value_label();
|
||||||
let label_name = field.renamed_label_without_namespace();
|
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(
|
let namespaces_matching = field.get_namespace_matching(
|
||||||
root_attributes,
|
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(
|
fn build_code_for_unused_xml_events(
|
||||||
call_flatten_visitors: &TokenStream,
|
call_flatten_visitors: &TokenStream,
|
||||||
) -> (
|
) -> (
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user