Skip to content

Factor attribute-stripping into a fold, similar to libsyntax #561

@dtolnay

Description

@dtolnay

This stuff:

fn strip_serde_derives(item: syn::MacroInput) -> (bool, bool, syn::MacroInput) {
let mut ser = false;
let mut de = false;
let item = syn::MacroInput {
attrs: item.attrs.into_iter().flat_map(|attr| {
if attr.is_sugared_doc {
return Some(attr);
}
let (name, nested) = match attr.value {
syn::MetaItem::List(name, nested) => (name, nested),
_ => return Some(attr)
};
if name != "derive" {
return Some(syn::Attribute {
value: syn::MetaItem::List(name, nested),
is_sugared_doc: false,
});
}
let rest: Vec<_> = nested.into_iter().filter(|nested| {
match *nested {
syn::MetaItem::Word(ref word) if word == "Serialize" => {
ser = true;
false
}
syn::MetaItem::Word(ref word) if word == "Deserialize" => {
de = true;
false
}
_ => true,
}
}).collect();
if rest.is_empty() {
None
} else {
Some(syn::Attribute {
value: syn::MetaItem::List(name, rest),
is_sugared_doc: false,
})
}
}).collect(),
..item
};
(ser, de, item)
}
fn strip_serde_attrs(item: syn::MacroInput) -> syn::MacroInput {
syn::MacroInput {
attrs: strip_serde_from_attrs(item.attrs),
body: match item.body {
syn::Body::Enum(variants) => syn::Body::Enum(
variants.into_iter().map(|variant| {
syn::Variant {
ident: variant.ident,
attrs: strip_serde_from_attrs(variant.attrs),
data: strip_serde_from_variant_data(variant.data),
discriminant: variant.discriminant,
}
}).collect()
),
syn::Body::Struct(variant_data) => syn::Body::Struct(
strip_serde_from_variant_data(variant_data)
),
},
..item
}
}
fn strip_serde_from_variant_data(data: syn::VariantData) -> syn::VariantData {
match data {
syn::VariantData::Struct(fields) => syn::VariantData::Struct(
fields.into_iter().map(strip_serde_from_field).collect()
),
syn::VariantData::Tuple(fields) => syn::VariantData::Tuple(
fields.into_iter().map(strip_serde_from_field).collect()
),
syn::VariantData::Unit => syn::VariantData::Unit,
}
}
fn strip_serde_from_field(field: syn::Field) -> syn::Field {
syn::Field {
attrs: strip_serde_from_attrs(field.attrs),
..field
}
}
fn strip_serde_from_attrs(attrs: Vec<syn::Attribute>) -> Vec<syn::Attribute> {
attrs.into_iter().filter(|attr| {
match attr.value {
syn::MetaItem::List(ref ident, _) => ident != "serde",
_ => true,
}
}).collect()
}

Here is how libsyntax does it: https://github.com/rust-lang/rust/blob/master/src/libsyntax/fold.rs

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions