From 5fe400c006d9d143aa7b977cb13f95e7380754a5 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Sat, 16 May 2026 21:55:55 +0800 Subject: Validate single-segment types in attribute macros --- mingling_macros/src/lib.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'mingling_macros/src/lib.rs') diff --git a/mingling_macros/src/lib.rs b/mingling_macros/src/lib.rs index 213c397..175c7e5 100644 --- a/mingling_macros/src/lib.rs +++ b/mingling_macros/src/lib.rs @@ -68,6 +68,35 @@ pub(crate) static RENDERERS_EXIST: Lazy>> = pub(crate) static HELP_REQUESTS: Lazy>> = Lazy::new(|| Mutex::new(BTreeSet::new())); +/// 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`, +/// not a qualified path like `other::Empty`. +/// +/// Returns `None` if the type is valid, or a `compile_error!` token stream if it contains `::`. +pub(crate) fn check_single_segment_type( + type_path: &syn::TypePath, + attr_name: &str, +) -> Option { + if type_path.path.segments.len() > 1 { + let type_str = quote! { #type_path }; + Some(quote! { + compile_error!(concat!( + "The type `", + #type_str, + "` in ", + #attr_name, + " function must be a simple single-segment type, ", + "e.g. `Empty` instead of `other::Empty`. ", + "Qualified paths with `::` are not allowed here." + )); + }) + } else { + None + } +} + /// Creates a `Node` from a dot-separated path string. /// /// Each segment is converted to kebab-case (unless it starts with `_`). -- cgit