1use proc_macro::TokenStream;
5use quote::quote;
6use syn::{Fields, ItemStruct, LitStr, parse_macro_input};
7
8#[proc_macro_attribute]
20pub fn plugin_factory(attr: TokenStream, item: TokenStream) -> TokenStream {
21 let plugin_type = parse_macro_input!(attr as LitStr);
22 let item_struct = parse_macro_input!(item as ItemStruct);
23 let ident = &item_struct.ident;
24
25 let factory_ctor = match &item_struct.fields {
26 Fields::Unit => quote! { #ident },
27 Fields::Named(fields) if fields.named.is_empty() => quote! { #ident {} },
28 _ => {
29 return syn::Error::new_spanned(
30 &item_struct,
31 "#[plugin_factory] only supports unit structs or empty braced structs; use register_plugin_factory! for factories with state or custom constructors",
32 )
33 .to_compile_error()
34 .into();
35 }
36 };
37
38 quote! {
39 #item_struct
40
41 inventory::submit! {
42 crate::plugin::FactoryRegistration {
43 plugin_type: #plugin_type,
44 module_path: module_path!(),
45 constructor: || -> Box<dyn crate::plugin::PluginFactory> {
46 Box::new(#factory_ctor)
47 },
48 }
49 }
50 }
51 .into()
52}