aboutsummaryrefslogtreecommitdiff
path: root/mingling_macros/src
diff options
context:
space:
mode:
Diffstat (limited to 'mingling_macros/src')
-rw-r--r--mingling_macros/src/chain.rs8
-rw-r--r--mingling_macros/src/dispatch_tree_gen.rs14
-rw-r--r--mingling_macros/src/dispatcher.rs3
-rw-r--r--mingling_macros/src/entry.rs23
-rw-r--r--mingling_macros/src/enum_tag.rs15
-rw-r--r--mingling_macros/src/groupped.rs22
-rw-r--r--mingling_macros/src/lib.rs24
-rw-r--r--mingling_macros/src/pack.rs1
-rw-r--r--mingling_macros/src/renderer.rs41
-rw-r--r--mingling_macros/src/res_injection.rs3
10 files changed, 75 insertions, 79 deletions
diff --git a/mingling_macros/src/chain.rs b/mingling_macros/src/chain.rs
index ac05480..b0ea8ae 100644
--- a/mingling_macros/src/chain.rs
+++ b/mingling_macros/src/chain.rs
@@ -229,8 +229,8 @@ fn generate_struct_and_impl(
group_name: &proc_macro2::TokenStream,
program_type: &proc_macro2::TokenStream,
use_crate_prefix: bool,
- proc_fn: proc_macro2::TokenStream,
- origin_proc_fn: proc_macro2::TokenStream,
+ proc_fn: &proc_macro2::TokenStream,
+ origin_proc_fn: &proc_macro2::TokenStream,
) -> proc_macro2::TokenStream {
let chain_type = if use_crate_prefix {
program_type
@@ -389,8 +389,8 @@ pub fn chain_attr(attr: TokenStream, item: TokenStream) -> TokenStream {
&group_name,
&program_type,
use_crate_prefix,
- proc_fn,
- origin_proc_fn,
+ &proc_fn,
+ &origin_proc_fn,
);
expanded.into()
diff --git a/mingling_macros/src/dispatch_tree_gen.rs b/mingling_macros/src/dispatch_tree_gen.rs
index a2cd52c..66fb6e7 100644
--- a/mingling_macros/src/dispatch_tree_gen.rs
+++ b/mingling_macros/src/dispatch_tree_gen.rs
@@ -43,7 +43,7 @@ pub fn gen_dispatch_args_trie(entries: &[(String, String, String)]) -> TokenStre
quote! {
fn dispatch_args_trie(
- raw: &Vec<String>,
+ raw: &[String],
) -> Result<::mingling::AnyOutput<Self::Enum>, ::mingling::error::ProgramInternalExecuteError>
{
let raw_string = format!("{} ", raw.join(" "));
@@ -63,7 +63,7 @@ pub fn gen_dispatch_args_trie(entries: &[(String, String, String)]) -> TokenStre
fn build_dispatch_body(nodes: &[(String, String)], depth: usize) -> TokenStream {
if nodes.is_empty() {
return quote! {
- return Ok(Self::build_dispatcher_not_found(raw.clone()));
+ return Ok(Self::build_dispatcher_not_found(raw.to_vec()));
};
}
@@ -121,7 +121,7 @@ fn build_dispatch_body(nodes: &[(String, String)], depth: usize) -> TokenStream
arms.push(quote! {
Some(#ch_char) => {
#arm
- return Ok(Self::build_dispatcher_not_found(raw.clone()));
+ return Ok(Self::build_dispatcher_not_found(raw.to_vec()));
}
});
} else {
@@ -150,7 +150,7 @@ fn build_dispatch_body(nodes: &[(String, String)], depth: usize) -> TokenStream
let match_body = quote! {
match raw_chars.nth(0) {
#(#arms)*
- _ => return Ok(Self::build_dispatcher_not_found(raw.clone())),
+ _ => return Ok(Self::build_dispatcher_not_found(raw.to_vec())),
}
};
quote! {
@@ -161,19 +161,19 @@ fn build_dispatch_body(nodes: &[(String, String)], depth: usize) -> TokenStream
// Only exact nodes, no deeper groups
quote! {
#(#exact_checks)*
- return Ok(Self::build_dispatcher_not_found(raw.clone()));
+ return Ok(Self::build_dispatcher_not_found(raw.to_vec()));
}
} else if arms.is_empty() {
// Only fallback (shouldn't happen if nodes is non-empty)
quote! {
- return Ok(Self::build_dispatcher_not_found(raw.clone()));
+ return Ok(Self::build_dispatcher_not_found(raw.to_vec()));
}
} else {
// Only group arms
quote! {
match raw_chars.nth(0) {
#(#arms)*
- _ => return Ok(Self::build_dispatcher_not_found(raw.clone())),
+ _ => return Ok(Self::build_dispatcher_not_found(raw.to_vec())),
}
}
}
diff --git a/mingling_macros/src/dispatcher.rs b/mingling_macros/src/dispatcher.rs
index b7952a1..7e973eb 100644
--- a/mingling_macros/src/dispatcher.rs
+++ b/mingling_macros/src/dispatcher.rs
@@ -104,6 +104,7 @@ impl Parse for DispatcherChainInput {
// Additionally, the token stream generation patterns are nearly identical between
// the two main functions and could benefit from refactoring.
+#[allow(clippy::too_many_lines)]
pub fn dispatcher(input: TokenStream) -> TokenStream {
// Parse the input
let dispatcher_input = syn::parse_macro_input!(input as DispatcherChainInput);
@@ -332,7 +333,7 @@ pub fn register_dispatcher(_input: TokenStream) -> TokenStream {
quote! {}.into()
}
-/// Converts a dotted command name (e.g. "remote.add") to PascalCase (e.g. "RemoteAdd").
+/// 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
diff --git a/mingling_macros/src/entry.rs b/mingling_macros/src/entry.rs
index 6237e41..2ac5d6b 100644
--- a/mingling_macros/src/entry.rs
+++ b/mingling_macros/src/entry.rs
@@ -42,21 +42,16 @@ fn parse_strings(input: &syn::parse::ParseBuffer) -> syn::Result<Vec<String>> {
pub fn entry(input: TokenStream) -> TokenStream {
let parsed = parse_macro_input!(input as EntryInput);
- let string_exprs = match &parsed {
- EntryInput::Typed { .. } | EntryInput::Untyped { .. } => {
- let strings = match &parsed {
- EntryInput::Typed { strings, .. } => strings,
- EntryInput::Untyped { strings } => strings,
- };
- strings
- .iter()
- .map(|s| {
- let lit = syn::LitStr::new(s, proc_macro2::Span::call_site());
- quote! { #lit.to_string() }
- })
- .collect::<Vec<_>>()
- }
+ let strings = match &parsed {
+ EntryInput::Typed { strings, .. } | EntryInput::Untyped { strings } => strings,
};
+ let string_exprs = strings
+ .iter()
+ .map(|s| {
+ let lit = syn::LitStr::new(s, proc_macro2::Span::call_site());
+ quote! { #lit.to_string() }
+ })
+ .collect::<Vec<_>>();
let expanded = match parsed {
EntryInput::Typed { ident, .. } => {
diff --git a/mingling_macros/src/enum_tag.rs b/mingling_macros/src/enum_tag.rs
index 8f0576a..6277b69 100644
--- a/mingling_macros/src/enum_tag.rs
+++ b/mingling_macros/src/enum_tag.rs
@@ -13,7 +13,7 @@ pub fn derive_enum_tag(input: TokenStream) -> TokenStream {
}
}
-/// Implementation of the EnumTag derive macro
+/// Implementation of the `EnumTag` derive macro
fn derive_enum_tag_impl(input: DeriveInput) -> Result<proc_macro2::TokenStream> {
let enum_name = &input.ident;
let generics = &input.generics;
@@ -42,7 +42,7 @@ fn derive_enum_tag_impl(input: DeriveInput) -> Result<proc_macro2::TokenStream>
for variant in data.variants {
process_variant(
- variant,
+ &variant,
enum_name,
&mut variant_info,
&mut match_arms,
@@ -82,7 +82,7 @@ fn derive_enum_tag_impl(input: DeriveInput) -> Result<proc_macro2::TokenStream>
/// Process a single enum variant
fn process_variant(
- variant: Variant,
+ variant: &Variant,
enum_name: &Ident,
variant_info: &mut Vec<proc_macro2::TokenStream>,
match_arms: &mut Vec<proc_macro2::TokenStream>,
@@ -97,10 +97,9 @@ fn process_variant(
}
Fields::Named(_) | Fields::Unnamed(_) => {
return Err(Error::new_spanned(
- &variant,
+ variant,
format!(
- "EnumTag cannot be derived for enum variant `{}` with fields. Only unit variants are supported.",
- variant_name
+ "EnumTag cannot be derived for enum variant `{variant_name}` with fields. Only unit variants are supported."
),
));
}
@@ -132,7 +131,7 @@ fn process_variant(
Ok(())
}
-/// Extract description from #[enum_desc] attribute
+/// Extract description from #[`enum_desc`] attribute
fn extract_description(attrs: &[Attribute]) -> Result<Option<String>> {
for attr in attrs {
if attr.path().is_ident("enum_desc") {
@@ -150,7 +149,7 @@ fn extract_description(attrs: &[Attribute]) -> Result<Option<String>> {
Ok(None)
}
-/// Extract rename from #[enum_rename] attribute
+/// Extract rename from #[`enum_rename`] attribute
fn extract_rename(attrs: &[Attribute]) -> Result<Option<String>> {
for attr in attrs {
if attr.path().is_ident("enum_rename") {
diff --git a/mingling_macros/src/groupped.rs b/mingling_macros/src/groupped.rs
index e385812..534e2a6 100644
--- a/mingling_macros/src/groupped.rs
+++ b/mingling_macros/src/groupped.rs
@@ -23,13 +23,10 @@ pub fn derive_groupped(input: TokenStream) -> TokenStream {
// Parse attributes to find #[group(...)]
let group_ident: proc_macro2::TokenStream = parse_group_attribute(&input.attrs)
- .map(|ident| quote! { #ident })
- .unwrap_or_else(crate::default_program_path);
+ .map_or_else(crate::default_program_path, |ident| quote! { #ident });
- let any_output_convert_impls = proc_macro2::TokenStream::from(build_any_output_convert_impls(
- struct_name.clone(),
- group_ident.clone(),
- ));
+ let any_output_convert_impls =
+ proc_macro2::TokenStream::from(build_any_output_convert_impls(&struct_name, &group_ident));
// Generate the Groupped trait implementation
let expanded = quote! {
@@ -55,13 +52,10 @@ pub fn derive_groupped_serialize(input: TokenStream) -> TokenStream {
// Parse attributes to find #[group(...)]
let group_ident: proc_macro2::TokenStream = parse_group_attribute(&input_parsed.attrs)
- .map(|ident| quote! { #ident })
- .unwrap_or_else(crate::default_program_path);
+ .map_or_else(crate::default_program_path, |ident| quote! { #ident });
- let any_output_convert_impls = proc_macro2::TokenStream::from(build_any_output_convert_impls(
- struct_name.clone(),
- group_ident.clone(),
- ));
+ let any_output_convert_impls =
+ proc_macro2::TokenStream::from(build_any_output_convert_impls(&struct_name, &group_ident));
// Generate both Serialize and Groupped implementations
let expanded = quote! {
@@ -83,8 +77,8 @@ pub fn derive_groupped_serialize(input: TokenStream) -> TokenStream {
}
fn build_any_output_convert_impls(
- struct_name: Ident,
- group_ident: proc_macro2::TokenStream,
+ struct_name: &Ident,
+ group_ident: &proc_macro2::TokenStream,
) -> TokenStream {
quote! {
impl ::std::convert::Into<::mingling::AnyOutput<#group_ident>> for #struct_name {
diff --git a/mingling_macros/src/lib.rs b/mingling_macros/src/lib.rs
index 8cae29f..7a93895 100644
--- a/mingling_macros/src/lib.rs
+++ b/mingling_macros/src/lib.rs
@@ -82,7 +82,7 @@ pub(crate) static CHAINS_EXIST: Registry = OnceLock::new();
pub(crate) static RENDERERS_EXIST: Registry = OnceLock::new();
pub(crate) static HELP_REQUESTS: Registry = OnceLock::new();
-/// Checks that a TypePath is a simple single-segment identifier (no `::` in the path).
+/// Checks that a `TypePath` is a simple single-segment identifier (no `::` in the path).
///
/// This is used by `#[renderer]`, `#[help]`, `#[chain]`, and `#[completion]` attribute macros
/// to ensure that the type in the function signature is a bare identifier like `Empty`,
@@ -307,7 +307,7 @@ pub fn empty_result(_input: TokenStream) -> TokenStream {
///
/// When the `extra_macros` feature is enabled, the `CommandStruct => EntryStruct`
/// portion can be omitted. The struct names are auto-derived from the command path
-/// using PascalCase conversion:
+/// using `PascalCase` conversion:
///
/// ```rust,ignore
/// // Auto-derives: "remote.add" → CMDRemoteAdd ⇒ EntryRemoteAdd
@@ -1188,7 +1188,7 @@ pub fn program_comp_gen(input: TokenStream) -> TokenStream {
/// Registers a type into the global packed types registry for inclusion in
/// the program enum generated by `gen_program!`.
///
-/// This macro is called internally by `pack!` and `#[derive(Groupped)]`(macro.derive_groupped.html)
+/// This macro is called internally by `pack!` and `#[derive(Groupped)]`(`macro.derive_groupped.html`)
/// and is generally not needed in user code. However, it can be used for manual
/// registration if you are implementing custom type registration outside of
/// the standard macros.
@@ -1201,6 +1201,10 @@ pub fn program_comp_gen(input: TokenStream) -> TokenStream {
///
/// Each call inserts the type's name into the `PACKED_TYPES` global set, which
/// is later consumed by `program_final_gen!` to generate enum variants.
+///
+/// # Panics
+///
+/// Panics if the global `PACKED_TYPES` mutex is poisoned.
#[proc_macro]
pub fn register_type(input: TokenStream) -> TokenStream {
let type_ident = parse_macro_input!(input as syn::Ident);
@@ -1348,7 +1352,13 @@ pub fn program_fallback_gen(input: TokenStream) -> TokenStream {
/// pub fn new() -> Program<MyProgram> { Program::new() }
/// }
/// ```
+///
+/// # Panics
+///
+/// Panics if any of the global registries (`PACKED_TYPES`, `RENDERERS`, `CHAINS`, etc.)
+/// are poisoned.
#[proc_macro]
+#[allow(clippy::too_many_lines)]
pub fn program_final_gen(input: TokenStream) -> TokenStream {
let name = read_name(&input);
@@ -1479,11 +1489,11 @@ pub fn program_final_gen(input: TokenStream) -> TokenStream {
.collect();
let num_variants = packed_types.len();
- let repr_type = if num_variants <= u8::MAX as usize {
+ let repr_type = if u8::try_from(num_variants).is_ok() {
quote! { u8 }
- } else if num_variants <= u16::MAX as usize {
+ } else if u16::try_from(num_variants).is_ok() {
quote! { u16 }
- } else if num_variants <= u32::MAX as usize {
+ } else if u32::try_from(num_variants).is_ok() {
quote! { u32 }
} else {
quote! { u128 }
@@ -1612,7 +1622,7 @@ pub fn program_final_gen(input: TokenStream) -> TokenStream {
///
/// # Related
///
-/// - `suggest_enum!`(macro.suggest_enum.html) — Build suggestions from an `EnumTag` enum.
+/// - `suggest_enum!`(`macro.suggest_enum.html`) — Build suggestions from an `EnumTag` enum.
#[cfg(feature = "comp")]
#[proc_macro]
pub fn suggest(input: TokenStream) -> TokenStream {
diff --git a/mingling_macros/src/pack.rs b/mingling_macros/src/pack.rs
index 954a052..5a1c388 100644
--- a/mingling_macros/src/pack.rs
+++ b/mingling_macros/src/pack.rs
@@ -59,6 +59,7 @@ impl Parse for PackInput {
}
}
+#[allow(clippy::too_many_lines)]
pub fn pack(input: TokenStream) -> TokenStream {
// Parse the input
let pack_input = syn::parse_macro_input!(input as PackInput);
diff --git a/mingling_macros/src/renderer.rs b/mingling_macros/src/renderer.rs
index ae75895..4cf9fc1 100644
--- a/mingling_macros/src/renderer.rs
+++ b/mingling_macros/src/renderer.rs
@@ -7,20 +7,21 @@ use crate::get_global_set;
use crate::res_injection::{extract_args_info, generate_immut_resource_bindings};
/// Extracts and returns the return type from the function signature (or None for `()` / no return type).
-fn extract_return_type(sig: &Signature) -> syn::Result<Option<syn::Type>> {
+fn extract_return_type(sig: &Signature) -> Option<syn::Type> {
match &sig.output {
ReturnType::Type(_, ty) => {
match &**ty {
// `()` means no custom return type
- Type::Tuple(tuple) if tuple.elems.is_empty() => Ok(None),
+ Type::Tuple(tuple) if tuple.elems.is_empty() => None,
// Any other return type is allowed
- custom_ty => Ok(Some((*custom_ty).clone())),
+ custom_ty => Some((*custom_ty).clone()),
}
}
- ReturnType::Default => Ok(None),
+ ReturnType::Default => None,
}
}
+#[allow(clippy::too_many_lines)]
pub fn renderer_attr(attr: TokenStream, item: TokenStream) -> TokenStream {
// Parse attribute arguments for program path (e.g. #[renderer(my_crate::Program)])
let (program_path, _use_crate_prefix) = parse_renderer_attr_args(attr);
@@ -48,10 +49,7 @@ pub fn renderer_attr(attr: TokenStream, item: TokenStream) -> TokenStream {
}
// Validate return type – now returns Some(type) if custom type, None if ()
- let return_type = match extract_return_type(&input_fn.sig) {
- Ok(rt) => rt,
- Err(e) => return e.to_compile_error().into(),
- };
+ let return_type = extract_return_type(&input_fn.sig);
// Get function body statements
let fn_body_stmts: Vec<syn::Stmt> = input_fn.block.stmts.clone();
@@ -83,23 +81,20 @@ pub fn renderer_attr(attr: TokenStream, item: TokenStream) -> TokenStream {
let mut_resources: Vec<_> = resources.iter().filter(|r| r.is_mut).collect();
// Determine public return type and the expression to return dummy_r
- let (public_return_type, result_return) = match &return_type {
+ let (public_return_type, result_return) = if let Some(custom_ty) = &return_type {
// User specified a custom return type (e.g. -> String)
- Some(custom_ty) => {
- let ret_ty = quote! { #custom_ty };
- let expr = quote! { dummy_r.into() };
- (ret_ty, expr)
- }
+ let ret_ty = quote! { #custom_ty };
+ let expr = quote! { dummy_r.into() };
+ (ret_ty, expr)
+ } else {
// Return type is () — no custom return type specified
- None => {
- let ret_ty = quote! { () };
- let expr = quote! {
- if !dummy_r.is_empty() {
- ::std::println!("{}", &*dummy_r);
- }
- };
- (ret_ty, expr)
- }
+ let ret_ty = quote! { () };
+ let expr = quote! {
+ if !dummy_r.is_empty() {
+ ::std::println!("{}", &*dummy_r);
+ }
+ };
+ (ret_ty, expr)
};
let inner_body_with_resources = if has_mut_resources {
diff --git a/mingling_macros/src/res_injection.rs b/mingling_macros/src/res_injection.rs
index bdb3b73..f2280e3 100644
--- a/mingling_macros/src/res_injection.rs
+++ b/mingling_macros/src/res_injection.rs
@@ -13,6 +13,7 @@ pub(crate) struct ResourceInjection {
/// Extracts the previous type and parameter name from function arguments,
/// and collects resource injection parameters from the 2nd argument onward.
+#[allow(clippy::too_many_lines)]
pub(crate) fn extract_args_info(
sig: &Signature,
) -> syn::Result<(Pat, TypePath, Vec<ResourceInjection>)> {
@@ -183,7 +184,7 @@ pub(crate) fn wrap_body_with_mut_resources(
#(#fn_body_stmts)*
};
- for res in mut_resources.iter() {
+ for res in mut_resources {
let var_name = &res.var_name;
let inner_type = &res.inner_type;
wrapped = quote! {