diff options
Diffstat (limited to 'mingling_macros/src/func/dispatcher.rs')
| -rw-r--r-- | mingling_macros/src/func/dispatcher.rs | 108 |
1 files changed, 14 insertions, 94 deletions
diff --git a/mingling_macros/src/func/dispatcher.rs b/mingling_macros/src/func/dispatcher.rs index a61dd26..a9e2464 100644 --- a/mingling_macros/src/func/dispatcher.rs +++ b/mingling_macros/src/func/dispatcher.rs @@ -1,13 +1,8 @@ -#[cfg(feature = "dispatch_tree")] -use just_fmt::snake_case; use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; use quote::quote; use syn::parse::{Parse, ParseStream}; -use syn::{Attribute, Ident, LitStr, Result as SynResult, Token}; - -#[cfg(feature = "dispatch_tree")] -use crate::COMPILE_TIME_DISPATCHERS; +use syn::{Attribute, Ident, LitStr, Token}; enum DispatcherChainInput { Default { @@ -17,7 +12,7 @@ enum DispatcherChainInput { command_struct: Ident, pack: Ident, }, - #[cfg(feature = "extra_macros")] + #[cfg(feature = "extras")] Auto { cmd_attrs: Vec<Attribute>, command_name: syn::LitStr, @@ -25,7 +20,7 @@ enum DispatcherChainInput { } impl Parse for DispatcherChainInput { - fn parse(input: ParseStream) -> SynResult<Self> { + fn parse(input: ParseStream) -> syn::Result<Self> { // Collect outer attributes for the CMD struct let cmd_attrs = input.call(Attribute::parse_outer)?; @@ -35,14 +30,14 @@ impl Parse for DispatcherChainInput { // Check if this is the abbreviated form: just "command_name" without ", CMD => Entry" if input.is_empty() { - #[cfg(feature = "extra_macros")] + #[cfg(feature = "extras")] { return Ok(DispatcherChainInput::Auto { cmd_attrs, command_name, }); } - #[cfg(not(feature = "extra_macros"))] + #[cfg(not(feature = "extras"))] { return Err(syn::Error::new( command_name.span(), @@ -79,7 +74,7 @@ pub(crate) fn dispatcher(input: TokenStream) -> TokenStream { // Parse the input let dispatcher_input = syn::parse_macro_input!(input as DispatcherChainInput); - #[cfg(not(feature = "extra_macros"))] + #[cfg(not(feature = "extras"))] let (command_name, command_struct, pack, cmd_attrs, entry_attrs) = match dispatcher_input { DispatcherChainInput::Default { cmd_attrs, @@ -90,7 +85,7 @@ pub(crate) fn dispatcher(input: TokenStream) -> TokenStream { } => (command_name, command_struct, pack, cmd_attrs, entry_attrs), }; - #[cfg(feature = "extra_macros")] + #[cfg(feature = "extras")] let (command_name, command_struct, pack, cmd_attrs, entry_attrs) = match dispatcher_input { DispatcherChainInput::Default { cmd_attrs, @@ -104,7 +99,7 @@ pub(crate) fn dispatcher(input: TokenStream) -> TokenStream { command_name, } => { let command_name_str = command_name.value(); - let pascal = dotted_to_pascal_case(&command_name_str); + let pascal = just_fmt::pascal_case!(&command_name_str); let command_struct = Ident::new(&format!("CMD{pascal}"), command_name.span()); let pack = Ident::new(&format!("Entry{pascal}"), command_name.span()); (command_name, command_struct, pack, cmd_attrs, Vec::new()) @@ -126,6 +121,12 @@ pub(crate) fn dispatcher(input: TokenStream) -> TokenStream { ::mingling::macros::pack!(#(#entry_attrs)* #pack = Vec<String>); + impl From<#pack> for crate::Entry { + fn from(value: #pack) -> Self { + crate::Entry::new(value.inner) + } + } + #comp_entry #dispatch_tree_entry @@ -183,84 +184,3 @@ fn get_dispatch_tree_entry( ) -> TokenStream2 { quote! {} } - -#[cfg(feature = "dispatch_tree")] -/// Input format: ("node.name", DispatcherType, EntryName) -struct RegisterDispatcherInput { - node_name: syn::LitStr, - dispatcher_type: Ident, - entry_name: Ident, -} - -#[cfg(feature = "dispatch_tree")] -impl Parse for RegisterDispatcherInput { - fn parse(input: ParseStream) -> SynResult<Self> { - let node_name = input.parse()?; - input.parse::<Token![,]>()?; - let dispatcher_type = input.parse()?; - input.parse::<Token![,]>()?; - let entry_name = input.parse()?; - Ok(RegisterDispatcherInput { - node_name, - dispatcher_type, - entry_name, - }) - } -} - -#[cfg(feature = "dispatch_tree")] -pub(crate) fn register_dispatcher(input: TokenStream) -> TokenStream { - let RegisterDispatcherInput { - node_name, - dispatcher_type, - entry_name, - } = syn::parse_macro_input!(input as RegisterDispatcherInput); - - let node_name_str = node_name.value(); - let static_name = format!( - "__internal_dispatcher_{}", - snake_case!(node_name_str.clone()) - ); - let static_ident = Ident::new(&static_name, proc_macro2::Span::call_site()); - - // Register node info in the global collection at compile time - // Format: "node.name:DispatcherType:EntryName" - crate::get_global_set(&COMPILE_TIME_DISPATCHERS) - .lock() - .unwrap() - .insert(format!( - "{}:{}:{}", - node_name_str, dispatcher_type, entry_name - )); - - let expanded = quote! { - #[doc(hidden)] - #[allow(nonstandard_style)] - pub static #static_ident: #dispatcher_type = #dispatcher_type; - }; - - expanded.into() -} - -#[cfg(not(feature = "dispatch_tree"))] -pub(crate) fn register_dispatcher(_input: TokenStream) -> TokenStream { - quote! {}.into() -} - -/// Converts a dotted command name (e.g. "remote.add") to `PascalCase` (e.g. "`RemoteAdd`"). -/// -/// Each segment is split by `.`, the first character of each segment is uppercased, -/// and the segments are joined. This is used by the abbreviated `dispatcher!` syntax -/// (when `Command => Entry` is omitted) to auto-derive struct names. -#[cfg(feature = "extra_macros")] -fn dotted_to_pascal_case(s: &str) -> String { - s.split('.') - .map(|segment| { - let mut chars = segment.chars(); - match chars.next() { - None => String::new(), - Some(c) => c.to_uppercase().to_string() + chars.as_str(), - } - }) - .collect() -} |
