pub mod component_impl;
pub mod factory;
pub mod inner_init;
pub mod intercept;
pub mod lifecycle;
pub mod meta_entry;
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{parse_macro_input, Ident, ItemStruct, Result as SynResult, Type, Visibility};
use crate::attr::comp_attr::{parse_component_attr_from_attributes, CompAttr};
use crate::classify::fields::{classify_fields, FieldKind};
use crate::type_utils::{
extract_trait_from_arc, extract_trait_from_option_arc, extract_trait_from_vec_arc, strip_arc_type,
};
pub fn derive_component(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemStruct);
match derive_component_impl(input) {
Ok(ts) => ts.into(),
Err(e) => e.to_compile_error().into(),
}
}
pub struct CodeGenContext {
pub struct_name: Ident,
pub vis: Visibility,
pub comp_attr: CompAttr,
pub fields_info: Vec<(Ident, FieldKind)>,
pub inject_fields: Vec<(Ident, Type)>,
pub trait_inject_fields: Vec<(Ident, Type)>,
pub required_trait_fields: Vec<(Ident, Type)>,
pub list_trait_fields: Vec<(Ident, Type)>,
}
fn derive_component_impl(input: ItemStruct) -> SynResult<TokenStream2> {
let struct_name = input.ident.clone();
let vis = input.vis.clone();
let generics = &input.generics;
let comp_attr = parse_component_attr_from_attributes(&input.attrs)?.unwrap_or_default();
if !generics.params.is_empty() {
return Err(syn::Error::new_spanned(
&input.ident,
"泛型结构体请使用 #[component(for(Type1, Type2))] 指定具体类型参数",
));
}
let fields_info = classify_fields(&input)?;
let inject_fields: Vec<(Ident, Type)> = fields_info
.iter()
.filter_map(|(name, kind)| match kind {
FieldKind::Inject { ty } => {
let inner_ty = strip_arc_type(ty);
Some((name.clone(), inner_ty))
}
_ => None,
})
.collect();
let trait_inject_fields: Vec<(Ident, Type)> = fields_info
.iter()
.filter_map(|(name, kind)| match kind {
FieldKind::TraitInject { ty } => {
let trait_ty = extract_trait_from_option_arc(ty)
.expect("is_arc_dyn_trait 已验证,提取 trait 类型不应失败");
Some((name.clone(), trait_ty))
}
_ => None,
})
.collect();
let required_trait_fields: Vec<(Ident, Type)> = fields_info
.iter()
.filter_map(|(name, kind)| match kind {
FieldKind::TraitInjectRequired { ty } => {
let trait_ty = extract_trait_from_arc(ty)
.expect("is_plain_arc_dyn_trait 已验证,提取 trait 类型不应失败");
Some((name.clone(), trait_ty))
}
_ => None,
})
.collect();
let list_trait_fields: Vec<(Ident, Type)> = fields_info
.iter()
.filter_map(|(name, kind)| match kind {
FieldKind::TraitInjectList { ty } => {
let trait_ty = extract_trait_from_vec_arc(ty)
.expect("is_vec_arc_dyn_trait 已验证,提取 trait 类型不应失败");
Some((name.clone(), trait_ty))
}
_ => None,
})
.collect();
let ctx = CodeGenContext {
struct_name,
vis,
comp_attr,
fields_info,
inject_fields,
trait_inject_fields,
required_trait_fields,
list_trait_fields,
};
let component_impl = component_impl::gen_component_impl(&ctx);
let factory_fn = factory::gen_factory_fn(&ctx);
let meta_entry = meta_entry::gen_meta_entry(&ctx, factory_fn);
Ok(quote! {
#component_impl
#meta_entry
})
}