meta_merge_core 0.1.0

Core logic for meta_merge
Documentation
use quote::{ToTokens, quote};
use syn::spanned::Spanned;

pub enum ItemFnStructEnum<'a> {
    Fn(&'a mut syn::ItemFn),
    Struct(&'a mut syn::ItemStruct),
    Enum(&'a mut syn::ItemEnum),
}

impl ItemFnStructEnum<'_> {
    pub fn ident(&self) -> &syn::Ident {
        match self {
            Self::Fn(i) => &i.sig.ident,
            Self::Struct(i) => &i.ident,
            Self::Enum(i) => &i.ident,
        }
    }
    pub fn attrs(&self) -> &Vec<syn::Attribute> {
        match self {
            Self::Fn(i) => &i.attrs,
            Self::Struct(i) => &i.attrs,
            Self::Enum(i) => &i.attrs,
        }
    }
    pub fn attrs_mut(&mut self) -> &mut Vec<syn::Attribute> {
        match self {
            Self::Fn(i) => &mut i.attrs,
            Self::Struct(i) => &mut i.attrs,
            Self::Enum(i) => &mut i.attrs,
        }
    }
    pub fn clone_attrs(&self) -> Vec<syn::Attribute> {
        self.attrs().clone()
    }
    pub fn take_attrs(&mut self) -> Vec<syn::Attribute> {
        std::mem::take(self.attrs_mut())
    }
    pub fn put_attrs(&mut self, attrs: Vec<syn::Attribute>) -> Vec<syn::Attribute> {
        std::mem::replace(self.attrs_mut(), attrs)
    }
}

impl<'a> TryFrom<&'a mut syn::Item> for ItemFnStructEnum<'a> {
    type Error = syn::Error;

    fn try_from(value: &'a mut syn::Item) -> Result<Self, Self::Error> {
        match value {
            syn::Item::Fn(i) => Ok(Self::Fn(i)),
            syn::Item::Struct(i) => Ok(Self::Struct(i)),
            syn::Item::Enum(i) => Ok(Self::Enum(i)),
            other => Err(syn::Error::new(
                other.span(),
                "expected a function, struct, or enum",
            )),
        }
    }
}

impl ToTokens for ItemFnStructEnum<'_> {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        tokens.extend(match self {
            Self::Fn(i) => quote! { #i },
            Self::Struct(i) => quote! { #i },
            Self::Enum(i) => quote! { #i },
        });
    }
}

#[allow(dead_code)]
pub trait ItemExt {
    fn ident(&self) -> Option<&syn::Ident>;
}

impl ItemExt for syn::Item {
    fn ident(&self) -> Option<&syn::Ident> {
        Some(match self {
            syn::Item::Const(i) => &i.ident,
            syn::Item::Enum(i) => &i.ident,
            syn::Item::ExternCrate(i) => &i.ident,
            syn::Item::Fn(i) => &i.sig.ident,
            syn::Item::Macro(i) => return i.ident.as_ref(),
            syn::Item::Mod(i) => &i.ident,
            syn::Item::Static(i) => &i.ident,
            syn::Item::Struct(i) => &i.ident,
            syn::Item::Trait(i) => &i.ident,
            syn::Item::TraitAlias(i) => &i.ident,
            syn::Item::Type(i) => &i.ident,
            syn::Item::Union(i) => &i.ident,
            _ => return None,
        })
    }
}

#[allow(dead_code)]
pub trait ItemAttrsExt {
    fn attrs_mut(&mut self) -> Option<&mut Vec<syn::Attribute>>;
    fn take_attrs(&mut self) -> Option<Vec<syn::Attribute>>;
    fn put_attrs(&mut self, attrs: Vec<syn::Attribute>) -> Option<Vec<syn::Attribute>>;
}

impl ItemAttrsExt for syn::Item {
    fn attrs_mut(&mut self) -> Option<&mut Vec<syn::Attribute>> {
        Some(match self {
            syn::Item::Const(i) => &mut i.attrs,
            syn::Item::Enum(i) => &mut i.attrs,
            syn::Item::ExternCrate(i) => &mut i.attrs,
            syn::Item::Fn(i) => &mut i.attrs,
            syn::Item::ForeignMod(i) => &mut i.attrs,
            syn::Item::Impl(i) => &mut i.attrs,
            syn::Item::Macro(i) => &mut i.attrs,
            syn::Item::Mod(i) => &mut i.attrs,
            syn::Item::Static(i) => &mut i.attrs,
            syn::Item::Struct(i) => &mut i.attrs,
            syn::Item::Trait(i) => &mut i.attrs,
            syn::Item::TraitAlias(i) => &mut i.attrs,
            syn::Item::Type(i) => &mut i.attrs,
            syn::Item::Union(i) => &mut i.attrs,
            syn::Item::Use(i) => &mut i.attrs,
            syn::Item::Verbatim(_) => return None,
            _ => return None,
        })
    }
    fn take_attrs(&mut self) -> Option<Vec<syn::Attribute>> {
        Some(std::mem::take(self.attrs_mut()?))
    }
    fn put_attrs(&mut self, attrs: Vec<syn::Attribute>) -> Option<Vec<syn::Attribute>> {
        Some(std::mem::replace(self.attrs_mut()?, attrs))
    }
}