mod config;
mod config_builder;
mod error;
mod generics_item_fn;
mod log_template;
mod output;
use config_builder::ConfigBuilder;
use generics_item_fn::GenericsFn;
use proc_macro::TokenStream;
use syn::punctuated::Punctuated;
use syn::token::Comma;
use syn::Meta;
use syn::{parse_macro_input, ItemFn};
#[proc_macro_attribute]
pub fn funlog(args: TokenStream, item: TokenStream) -> TokenStream {
let is_debug = cfg!(debug_assertions);
if !is_debug {
return item;
}
let func = parse_macro_input!(item as ItemFn);
let func = GenericsFn::from(func);
let attr_meta: Punctuated<Meta, Comma> =
parse_macro_input!(args with Punctuated::<Meta, Comma>::parse_terminated);
match ConfigBuilder::from(attr_meta, func) {
Ok(config_builder) => match config_builder.build() {
Ok(config) => {
let output = config.to_output();
output.into()
}
Err(e) => {
let syn_error: syn::Error = e.into();
syn_error.into_compile_error().into()
}
},
Err(e) => {
let syn_error: syn::Error = e.into();
syn_error.into_compile_error().into()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use syn::{parse_quote, ItemFn};
#[test]
fn test_funlog_macro_exists() {
let func: ItemFn = parse_quote! {
fn test_func(x: i32) -> i32 { x + 1 }
};
let generics_fn = GenericsFn::from(func);
assert_eq!(generics_fn.sig.ident.to_string(), "test_func");
}
#[test]
fn test_debug_build_behavior() {
let is_debug = cfg!(debug_assertions);
if is_debug {
} else {
}
}
#[test]
fn test_integration_with_config_builder() {
let func: ItemFn = parse_quote! {
pub fn integration_test(x: i32, y: String) -> i32 {
x + 1
}
};
let generics_fn = GenericsFn::from(func);
let meta_list: Punctuated<Meta, Comma> = parse_quote! { debug, all, retVal };
let config_builder = ConfigBuilder::from(meta_list, generics_fn);
assert!(config_builder.is_ok());
let config = config_builder.unwrap().build();
assert!(config.is_ok());
let output = config.unwrap().to_output();
assert!(!output.inner_func.is_empty());
}
#[test]
fn test_error_handling_integration() {
let func: ItemFn = parse_quote! {
fn error_test() {}
};
let generics_fn = GenericsFn::from(func);
let meta_list: Punctuated<Meta, Comma> = parse_quote! { debug, info };
let result = ConfigBuilder::from(meta_list, generics_fn);
assert!(result.is_err());
match result.unwrap_err() {
error::ConfigError::ConflictingOptions { .. } => {
}
_ => panic!("Expected ConflictingOptions error"),
}
}
}