use proc_macro::TokenStream;
use syn::{ItemFn, parse_macro_input};
mod analysis;
mod codegen;
mod error;
mod types;
mod validation;
use analysis::ComponentAnalyzer;
use codegen::ComponentCodeGenerator;
use error::ComponentResult;
use types::{CodeGenConfig, ValidationConfig};
use validation::ComponentValidator;
pub fn component_impl(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as ItemFn);
match process_component(input) {
Ok(tokens) => tokens,
Err(error) => error.to_compile_error().into(),
}
}
fn process_component(mut input: ItemFn) -> ComponentResult<TokenStream> {
let validation_config = ValidationConfig::default();
let validator = ComponentValidator::with_config(validation_config);
validator.validate(&input)?;
let hook_validator = crate::hook_validator::HookValidator::new();
if let Err(errors) = hook_validator.validate(&mut input.block) {
let first_error = errors.into_iter().next().unwrap();
return Err(error::ComponentError::InvalidSyntax(
first_error.to_string(),
));
}
let analyzer = ComponentAnalyzer::new();
let component_info = analyzer.analyze(&input)?;
let mut config = CodeGenConfig::default();
if component_info.has_generics() || component_info.has_parameters() {
config.debug_info = true;
}
config.children_support = true;
let code_generator = ComponentCodeGenerator::with_config(config);
let generated_code = code_generator.generate(&input, &component_info)?;
Ok(generated_code.into())
}