Pass attrs properly in element tags
This commit is contained in:
@@ -21,6 +21,7 @@ struct Element {
|
|||||||
ty: syn::Path,
|
ty: syn::Path,
|
||||||
kind: ElementKind,
|
kind: ElementKind,
|
||||||
name: String,
|
name: String,
|
||||||
|
attrs: Vec<syn::Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_type(input: syn::Type) -> (syn::Path, ElementKind) {
|
fn parse_type(input: syn::Type) -> (syn::Path, ElementKind) {
|
||||||
@@ -66,22 +67,31 @@ fn parse_type(input: syn::Type) -> (syn::Path, ElementKind) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_field_attrs(attrs: &[syn::Attribute]) -> Option<String> {
|
fn parse_field_attrs(attrs: &mut Vec<syn::Attribute>) -> Option<String> {
|
||||||
match (attrs.first(), attrs.len()) {
|
let index_of_tag_attribute = attrs
|
||||||
(Some(attr), 1) => {
|
.iter()
|
||||||
assert!(
|
.enumerate()
|
||||||
attr.style == syn::AttrStyle::Outer,
|
.filter(|&(_i, attr)| attr.style == syn::AttrStyle::Outer)
|
||||||
"field attribute style needs to be an outer attribute"
|
.find_map(|(i, attr)| match attr.meta {
|
||||||
);
|
|
||||||
match attr.meta {
|
|
||||||
syn::Meta::List(ref meta_list) => {
|
syn::Meta::List(ref meta_list) => {
|
||||||
let tag = &meta_list.path;
|
let tag = &meta_list.path;
|
||||||
let tag_name = match (tag.segments.first(), tag.segments.len()) {
|
if let (Some(segment), 1) = (tag.segments.first(), tag.segments.len()) {
|
||||||
(Some(segment), 1) => segment.ident.to_string(),
|
if segment.ident == "tag" {
|
||||||
(_, 0) => return None,
|
Some((i, meta_list.clone()))
|
||||||
_ => panic!("invalid field attribute path"),
|
} else {
|
||||||
};
|
None
|
||||||
assert!(tag_name == "tag", "invalid field attribute path {tag_name}");
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
match index_of_tag_attribute {
|
||||||
|
Some((i, meta_list)) => {
|
||||||
|
let removed_attribute = attrs.remove(i);
|
||||||
|
drop(removed_attribute);
|
||||||
|
|
||||||
let expr: syn::Expr = match meta_list.parse_args() {
|
let expr: syn::Expr = match meta_list.parse_args() {
|
||||||
Ok(expr) => expr,
|
Ok(expr) => expr,
|
||||||
@@ -112,22 +122,18 @@ fn parse_field_attrs(attrs: &[syn::Attribute]) -> Option<String> {
|
|||||||
_ => panic!("right side of tag field attribute not a literal"),
|
_ => panic!("right side of tag field attribute not a literal"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => panic!("invalid field attribute"),
|
None => None,
|
||||||
}
|
|
||||||
}
|
|
||||||
(_, 0) => None,
|
|
||||||
_ => panic!("invalid field attributes"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_fields(input: impl IntoIterator<Item = syn::Field>) -> Vec<Element> {
|
fn parse_fields(input: impl IntoIterator<Item = syn::Field>) -> Vec<Element> {
|
||||||
let mut elements = Vec::new();
|
let mut elements = Vec::new();
|
||||||
for field in input {
|
for mut field in input {
|
||||||
let ident = field.ident.expect("tuple structs not supported");
|
let ident = field.ident.expect("tuple structs not supported");
|
||||||
let vis = field.vis;
|
let vis = field.vis;
|
||||||
let (ty, kind) = parse_type(field.ty);
|
let (ty, kind) = parse_type(field.ty);
|
||||||
|
|
||||||
let name = parse_field_attrs(&field.attrs);
|
let name = parse_field_attrs(&mut field.attrs);
|
||||||
|
|
||||||
elements.push(Element {
|
elements.push(Element {
|
||||||
ident: ident.clone(),
|
ident: ident.clone(),
|
||||||
@@ -135,6 +141,7 @@ fn parse_fields(input: impl IntoIterator<Item = syn::Field>) -> Vec<Element> {
|
|||||||
ty,
|
ty,
|
||||||
kind,
|
kind,
|
||||||
name: name.unwrap_or_else(|| ident.to_string()),
|
name: name.unwrap_or_else(|| ident.to_string()),
|
||||||
|
attrs: field.attrs,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
elements
|
elements
|
||||||
@@ -165,14 +172,19 @@ fn build_output(input: Input) -> TokenStream {
|
|||||||
let ident = &element.ident;
|
let ident = &element.ident;
|
||||||
let vis = &element.vis;
|
let vis = &element.vis;
|
||||||
let ty = &element.ty;
|
let ty = &element.ty;
|
||||||
|
let attrs = &element.attrs;
|
||||||
match element.kind {
|
match element.kind {
|
||||||
ElementKind::Required => {
|
ElementKind::Required => {
|
||||||
quote!(
|
quote!(
|
||||||
|
#(#attrs)
|
||||||
|
*
|
||||||
#vis #ident: #ty
|
#vis #ident: #ty
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ElementKind::Optional => {
|
ElementKind::Optional => {
|
||||||
quote!(
|
quote!(
|
||||||
|
#(#attrs)
|
||||||
|
*
|
||||||
#vis #ident: ::std::option::Option<#ty>
|
#vis #ident: ::std::option::Option<#ty>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -191,9 +203,18 @@ fn build_output(input: Input) -> TokenStream {
|
|||||||
let params = input.elements.iter().map(|element| {
|
let params = input.elements.iter().map(|element| {
|
||||||
let ident = &element.ident;
|
let ident = &element.ident;
|
||||||
let ty = &element.ty;
|
let ty = &element.ty;
|
||||||
|
let attrs = &element.attrs;
|
||||||
match element.kind {
|
match element.kind {
|
||||||
ElementKind::Required => quote!(#ident: #ty),
|
ElementKind::Required => quote! {
|
||||||
ElementKind::Optional => quote!(#ident: ::std::option::Option<#ty>),
|
#(#attrs)
|
||||||
|
*
|
||||||
|
#ident: #ty
|
||||||
|
},
|
||||||
|
ElementKind::Optional => quote! {
|
||||||
|
#(#attrs)
|
||||||
|
*
|
||||||
|
#ident: ::std::option::Option<#ty>
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -202,7 +223,12 @@ fn build_output(input: Input) -> TokenStream {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|element| {
|
.map(|element| {
|
||||||
let ident = &element.ident;
|
let ident = &element.ident;
|
||||||
quote! {#ident: #ident}
|
let attrs = &element.attrs;
|
||||||
|
quote! {
|
||||||
|
#(#attrs)
|
||||||
|
*
|
||||||
|
#ident: #ident
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@@ -210,8 +236,9 @@ fn build_output(input: Input) -> TokenStream {
|
|||||||
let ident = &element.ident;
|
let ident = &element.ident;
|
||||||
let ty = &element.ty;
|
let ty = &element.ty;
|
||||||
let tag_name = &element.name;
|
let tag_name = &element.name;
|
||||||
|
let attrs = &element.attrs;
|
||||||
|
|
||||||
let try_convert = quote!{
|
let try_convert = quote! {
|
||||||
let value: ::std::result::Result<#ty, #root::tags::ParseTagsError> = <#ty as #root::tags::TagValue<#ty>>::from_raw_tag(value)
|
let value: ::std::result::Result<#ty, #root::tags::ParseTagsError> = <#ty as #root::tags::TagValue<#ty>>::from_raw_tag(value)
|
||||||
.map_err(
|
.map_err(
|
||||||
|e| #root::tags::ParseTagsError::ParseTag(#root::tags::ParseTagError::InvalidTagValue {
|
|e| #root::tags::ParseTagsError::ParseTag(#root::tags::ParseTagError::InvalidTagValue {
|
||||||
@@ -261,6 +288,8 @@ fn build_output(input: Input) -> TokenStream {
|
|||||||
};
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
|
#(#attrs)
|
||||||
|
*
|
||||||
#ident: {
|
#ident: {
|
||||||
let key: #root::tags::TagKey = #root::tags::TagKey::new(#tag_name.to_owned());
|
let key: #root::tags::TagKey = #root::tags::TagKey::new(#tag_name.to_owned());
|
||||||
|
|
||||||
@@ -286,9 +315,12 @@ fn build_output(input: Input) -> TokenStream {
|
|||||||
let ident = &element.ident;
|
let ident = &element.ident;
|
||||||
let ty= &element.ty;
|
let ty= &element.ty;
|
||||||
let tag_name = &element.name;
|
let tag_name = &element.name;
|
||||||
|
let attrs= &element.attrs;
|
||||||
match element.kind {
|
match element.kind {
|
||||||
ElementKind::Required => {
|
ElementKind::Required => {
|
||||||
quote! {
|
quote! {
|
||||||
|
#(#attrs)
|
||||||
|
*
|
||||||
{
|
{
|
||||||
let key = #root::tags::TagKey::new(#tag_name.to_owned());
|
let key = #root::tags::TagKey::new(#tag_name.to_owned());
|
||||||
let value: #root::tags::RawTagValue = <#ty as #root::tags::TagValue<#ty>>::into_raw_tag(self.#ident);
|
let value: #root::tags::RawTagValue = <#ty as #root::tags::TagValue<#ty>>::into_raw_tag(self.#ident);
|
||||||
@@ -298,6 +330,8 @@ fn build_output(input: Input) -> TokenStream {
|
|||||||
}
|
}
|
||||||
ElementKind::Optional => {
|
ElementKind::Optional => {
|
||||||
quote! {
|
quote! {
|
||||||
|
#(#attrs)
|
||||||
|
*
|
||||||
{
|
{
|
||||||
match self.#ident {
|
match self.#ident {
|
||||||
::std::option::Option::Some(value) => {
|
::std::option::Option::Some(value) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user