aspect_macros/lib.rs
1//! # aspect-macros
2//!
3//! Procedural macros for aspect-oriented programming in Rust.
4//!
5//! This crate provides the `#[aspect]` attribute macro that enables aspect weaving
6//! at compile time.
7
8use proc_macro::TokenStream;
9use syn::{parse_macro_input, Expr, ItemFn};
10
11mod advice_macro;
12mod aspect_attr;
13mod codegen;
14mod parsing;
15
16/// Applies an aspect to a function.
17///
18/// # Example
19///
20/// ```ignore
21/// use aspect_macros::aspect;
22/// use aspect_core::prelude::*;
23///
24/// #[derive(Default)]
25/// struct Logger;
26///
27/// impl Aspect for Logger {
28/// fn before(&self, ctx: &JoinPoint) {
29/// println!("[ENTRY] {}", ctx.function_name);
30/// }
31/// }
32///
33/// #[aspect(Logger)]
34/// fn my_function(x: i32) -> i32 {
35/// x * 2
36/// }
37/// ```
38#[proc_macro_attribute]
39pub fn aspect(attr: TokenStream, item: TokenStream) -> TokenStream {
40 let aspect_expr = parse_macro_input!(attr as Expr);
41 let func = parse_macro_input!(item as ItemFn);
42
43 aspect_attr::transform(aspect_expr, func)
44 .unwrap_or_else(|e| e.to_compile_error())
45 .into()
46}
47
48/// Registers an aspect with a pointcut pattern for declarative aspect application.
49///
50/// # Example
51///
52/// ```ignore
53/// use aspect_macros::advice;
54/// use aspect_core::prelude::*;
55///
56/// #[advice(
57/// pointcut = "execution(pub fn *(..)) && within(crate::api)",
58/// advice = "around",
59/// order = 10
60/// )]
61/// fn api_logger(pjp: ProceedingJoinPoint) -> Result<Box<dyn Any>, AspectError> {
62/// println!("API call: {}", pjp.context().function_name);
63/// pjp.proceed()
64/// }
65/// ```
66#[proc_macro_attribute]
67pub fn advice(attr: TokenStream, item: TokenStream) -> TokenStream {
68 let args = parse_macro_input!(attr as advice_macro::AdviceArgs);
69 let func = parse_macro_input!(item as ItemFn);
70
71 advice_macro::transform(args, func)
72 .unwrap_or_else(|e| e.to_compile_error())
73 .into()
74}