use proc_macro2::TokenStream;
use quote::quote;
use syn::{Path, PathSegment};
pub(crate) enum ModulePrefix {
Cano,
Prefixed(TokenStream),
Bare,
}
impl ModulePrefix {
pub(crate) fn qualify(&self, type_name: &str) -> TokenStream {
let ident = syn::Ident::new(type_name, proc_macro2::Span::call_site());
match self {
ModulePrefix::Cano => quote! { ::cano::#ident },
ModulePrefix::Prefixed(prefix) => quote! { #prefix #ident },
ModulePrefix::Bare => quote! { #ident },
}
}
}
pub(crate) fn derive_module_prefix(trait_path: &Path) -> ModulePrefix {
let seg_count = trait_path.segments.len();
if seg_count <= 1 && trait_path.leading_colon.is_none() {
return ModulePrefix::Bare;
}
let prefix_segs: syn::punctuated::Punctuated<PathSegment, syn::token::PathSep> = trait_path
.segments
.iter()
.take(seg_count.saturating_sub(1))
.cloned()
.collect();
let has_leading_colon = trait_path.leading_colon.is_some();
let is_cano_prefix = prefix_segs.len() == 1
&& prefix_segs
.iter()
.next()
.map(|s| s.ident == "cano")
.unwrap_or(false);
if has_leading_colon && is_cano_prefix {
return ModulePrefix::Cano;
}
let leading = if has_leading_colon {
quote! { :: }
} else {
quote! {}
};
ModulePrefix::Prefixed(quote! { #leading #prefix_segs :: })
}