mplusfonts-macros 0.3.4

Procedural macros re-exported in the mplusfonts crate
Documentation
use std::panic;

use proc_macro2::Span;
use quote::format_ident;

pub trait ItemExt {
    fn variant_ident(&self) -> syn::Ident;
}

impl ItemExt for syn::Item {
    fn variant_ident(&self) -> syn::Ident {
        use syn::Item::*;

        match self {
            Const(syn::ItemConst { ident, .. }) => {
                format_ident!("const_{ident}")
            }
            Enum(syn::ItemEnum { ident, .. }) => {
                format_ident!("enum_{ident}")
            }
            ExternCrate(syn::ItemExternCrate { ident, .. }) => {
                format_ident!("extern_crate_{ident}")
            }
            Fn(syn::ItemFn {
                sig: syn::Signature { ident, .. },
                ..
            }) => {
                format_ident!("fn_{ident}")
            }
            ForeignMod(syn::ItemForeignMod {
                abi: syn::Abi { name, .. },
                ..
            }) => {
                let ident = name.as_ref().map(|n| {
                    panic::catch_unwind(|| syn::Ident::new_raw(&n.value(), Span::call_site())).ok()
                });
                if let Some(ident) = ident.flatten() {
                    format_ident!("extern_{ident}")
                } else {
                    format_ident!("extern")
                }
            }
            Impl(syn::ItemImpl {
                trait_, self_ty, ..
            }) => {
                let trait_ident = if let Some((_, path, _)) = trait_.as_ref() {
                    Some(path.segments.last().map(|s| &s.ident))
                } else {
                    None
                };
                let ident = if let syn::Type::Path(syn::TypePath { path, .. }) = self_ty.as_ref() {
                    Some(path.segments.last().map(|s| &s.ident))
                } else {
                    None
                };
                match (trait_ident.flatten(), ident.flatten()) {
                    (Some(trait_ident), Some(ident)) => {
                        format_ident!("impl_{trait_ident}_for_{ident}")
                    }
                    (Some(trait_ident), None) => {
                        format_ident!("impl_{trait_ident}")
                    }
                    (None, Some(ident)) => {
                        format_ident!("impl_{ident}")
                    }
                    (None, None) => {
                        format_ident!("impl")
                    }
                }
            }
            Macro(syn::ItemMacro {
                ident,
                mac: syn::Macro { path, .. },
                ..
            }) => {
                let macro_ident = path.segments.last().map(|s| &s.ident);
                match (macro_ident, ident) {
                    (Some(_), Some(ident)) if path.is_ident("macro_rules") => {
                        format_ident!("macro_rules_{ident}")
                    }
                    (Some(macro_ident), Some(ident)) => {
                        format_ident!("{macro_ident}_{ident}")
                    }
                    (Some(macro_ident), None) => {
                        format_ident!("{macro_ident}")
                    }
                    (None, Some(ident)) => {
                        format_ident!("macro_{ident}")
                    }
                    (None, None) => {
                        format_ident!("macro")
                    }
                }
            }
            Mod(syn::ItemMod { ident, .. }) => {
                format_ident!("mod_{ident}")
            }
            Static(syn::ItemStatic { ident, .. }) => {
                format_ident!("static_{ident}")
            }
            Struct(syn::ItemStruct { ident, .. }) => {
                format_ident!("struct_{ident}")
            }
            Trait(syn::ItemTrait { ident, .. }) => {
                format_ident!("trait_{ident}")
            }
            TraitAlias(syn::ItemTraitAlias { ident, .. }) => {
                format_ident!("trait_{ident}")
            }
            Type(syn::ItemType { ident, .. }) => {
                format_ident!("type_{ident}")
            }
            Union(syn::ItemUnion { ident, .. }) => {
                format_ident!("union_{ident}")
            }
            Use(syn::ItemUse { .. }) => {
                format_ident!("use")
            }
            Verbatim(_) | _ => {
                format_ident!("item")
            }
        }
    }
}