lombok_macros/
lib.rs

1//! lombok-macros
2//!
3//! A Rust procedural macro collection providing Lombok-like functionality.
4//! Automatically generates getters/setters with field-level visibility control,
5//! custom Debug implementations with field skipping, and Display trait implementations.
6//! Supports structs, enums, generics and lifetimes.
7
8pub(crate) mod config;
9pub(crate) mod func;
10pub(crate) mod generate;
11pub(crate) mod parse;
12pub(crate) mod visibility;
13
14pub(crate) use config::*;
15pub(crate) use func::*;
16pub(crate) use generate::*;
17pub(crate) use parse::*;
18pub(crate) use visibility::*;
19
20pub(crate) use proc_macro::TokenStream;
21pub(crate) use proc_macro2::{
22    TokenStream as TokenStream2, TokenTree as TokenTree2, token_stream::IntoIter,
23};
24pub(crate) use quote::{ToTokens, format_ident, quote};
25pub(crate) use std::{collections::HashMap, str::FromStr};
26pub(crate) use syn::{
27    Data, DeriveInput, Field,
28    GenericParam::{self},
29    Ident, Lifetime,
30    Type::{self},
31    TypeParam, WhereClause, parse_macro_input,
32};
33
34/// This is an example of how to use the `Lombok` procedural macro with `get` attributes.
35///
36/// The `Lombok` procedural macro is used to automatically generate getter methods for struct fields.
37/// The `get` attribute controls the visibility of the generated getter method.
38///
39/// Example:
40///
41/// ```rust
42/// use lombok_macros::*;
43///
44/// #[derive(Getter, Clone)]
45/// struct LombokTest2<'a, 'b, T: Clone> {
46///     #[get(pub(crate))]
47///     list: Vec<String>,
48///     #[get(pub(crate))]
49///     opt_str_lifetime_a: Option<&'a T>,
50///     opt_str_lifetime_b: Option<&'b str>,
51/// }
52/// let list: Vec<String> = vec!["hello".to_string(), "world".to_string()];
53/// let data2: LombokTest2<usize> = LombokTest2 {
54///     list: list.clone(),
55///     opt_str_lifetime_a: None,
56///     opt_str_lifetime_b: None,
57/// };
58/// let get_list: Vec<String> = data2.get_list().clone();
59/// assert_eq!(get_list, list);
60/// ```
61#[proc_macro_derive(Getter, attributes(get))]
62pub fn getter(input: TokenStream) -> TokenStream {
63    inner_lombok_data(input, true, false, false)
64}
65
66/// This is an example of how to use the `Lombok` procedural macro with `get_mut` attributes.
67///
68/// The `Lombok` procedural macro is used to automatically generate mutable getters for struct fields.
69/// The `get_mut` attribute controls the visibility of the mutable getter function.
70///
71/// Example:
72///
73/// ```rust
74/// use lombok_macros::*;
75///
76/// #[derive(GetterMut, Clone)]
77/// struct LombokTest2<'a, 'b, T: Clone> {
78///     #[get_mut(pub(crate))]
79///     list: Vec<String>,
80///     #[get_mut(pub(crate))]
81///     opt_str_lifetime_a: Option<&'a T>,
82///     opt_str_lifetime_b: Option<&'b str>,
83/// }
84/// let list: Vec<String> = vec!["hello".to_string(), "world".to_string()];
85/// let mut data2: LombokTest2<usize> = LombokTest2 {
86///     list: list.clone(),
87///     opt_str_lifetime_a: None,
88///     opt_str_lifetime_b: None,
89/// };
90/// let get_list: Vec<String> = data2.get_mut_list().clone();
91/// assert_eq!(get_list, list);
92/// ```
93#[proc_macro_derive(GetterMut, attributes(get_mut))]
94pub fn getter_mut(input: TokenStream) -> TokenStream {
95    inner_lombok_data(input, false, true, false)
96}
97
98/// This is an example of how to use the `Lombok` procedural macro with `set` attributes.
99///
100/// The `Lombok` procedural macro is used to automatically generate setters for struct fields.
101/// The `set` attribute controls the visibility of the setter function.
102///
103/// Example:
104///
105/// ```rust
106/// use lombok_macros::*;
107///
108/// #[derive(Setter, Debug, Clone)]
109/// struct LombokTest<'a, 'b, T: Clone> {
110///     #[set(pub(crate))]
111///     list: Vec<String>,
112///     opt_str_lifetime_a: Option<&'a T>,
113///     #[set(private)]
114///     opt_str_lifetime_b: Option<&'b str>,
115/// }
116/// let mut data: LombokTest<usize> = LombokTest {
117///     list: Vec::new(),
118///     opt_str_lifetime_a: None,
119///     opt_str_lifetime_b: None,
120/// };
121/// let list: Vec<String> = vec!["hello".to_string(), "world".to_string()];
122/// data.set_list(list.clone());
123/// match data.list {
124///     left_val => {
125///         assert_eq!(*left_val, list);
126///     }
127/// }
128/// ```
129#[proc_macro_derive(Setter, attributes(set))]
130pub fn setter(input: TokenStream) -> TokenStream {
131    inner_lombok_data(input, false, false, true)
132}
133
134/// This is an example of how to use the `Lombok` procedural macro with `get`, `get_mut`, and `set` attributes.
135///
136/// The `Lombok` procedural macro is used to automatically generate getters, mutable getters, and setters for struct fields.
137/// The `get` and `get_mut` attributes control the visibility of the getter functions, while the `set` attribute controls
138/// the visibility of the setter function.
139///
140/// Example:
141///
142/// ```rust
143/// use lombok_macros::*;
144///
145/// #[derive(Data, Debug, Clone)]
146/// struct LombokTest<'a, 'b, T: Clone> {
147///     #[get(pub(crate))]
148///     #[set(pub(crate))]
149///     list: Vec<String>,
150///     #[get(pub(crate))]
151///     opt_str_lifetime_a: Option<&'a T>,
152///     #[set(private)]
153///     opt_str_lifetime_b: Option<&'b str>,
154/// }
155/// let mut data: LombokTest<usize> = LombokTest {
156///     list: Vec::new(),
157///     opt_str_lifetime_a: None,
158///     opt_str_lifetime_b: None,
159/// };
160/// let list: Vec<String> = vec!["hello".to_string(), "world".to_string()];
161/// data.set_list(list.clone());
162/// match data.get_list() {
163///     left_val => {
164///         assert_eq!(*left_val, list);
165///     }
166/// }
167/// ```
168#[proc_macro_derive(Data, attributes(get, get_mut, set))]
169pub fn data(input: TokenStream) -> TokenStream {
170    let mut result: TokenStream2 = TokenStream2::new();
171    let lombok_data: TokenStream = inner_lombok_data(input.clone(), true, true, true);
172    result.extend(
173        lombok_data
174            .to_string()
175            .parse::<TokenStream2>()
176            .unwrap_or_default(),
177    );
178    result.into()
179}
180
181/// A procedural macro that implements the `std::fmt::Display` trait for a type,
182/// using the standard debug format (`{:?}`) for formatting.
183///
184/// This macro derives the `Display` implementation for a type, allowing it to be formatted
185/// using `{:?}` in formatting macros. It uses the `inner_display_debug` function to generate
186/// the implementation with the standard debug format.
187///
188/// # Parameters
189/// - `input`: The input token stream representing the Rust item (struct, enum, etc.)
190///   for which the `Display` implementation will be generated.
191///
192/// # Returns
193/// - `TokenStream`: The generated `std::fmt::Display` implementation for the type
194///   using the standard debug format.
195#[proc_macro_derive(DisplayDebug)]
196pub fn display_debug(input: TokenStream) -> TokenStream {
197    inner_display_debug(input)
198}
199
200/// A procedural macro that implements the `std::fmt::Display` trait for a type,
201/// using the detailed debug format (`{:#?}`) for formatting.
202///
203/// This macro derives the `Display` implementation for a type, allowing it to be formatted
204/// using `{:#?}` in formatting macros. It uses the `inner_display_debug_format` function
205/// to generate the implementation with the detailed debug format.
206///
207/// # Parameters
208/// - `input`: The input token stream representing the Rust item (struct, enum, etc.)
209///   for which the `Display` implementation will be generated.
210///
211/// # Returns
212/// - `TokenStream`: The generated `std::fmt::Display` implementation for the type
213///   using the detailed debug format.
214#[proc_macro_derive(DisplayDebugFormat)]
215pub fn display_debug_format(input: TokenStream) -> TokenStream {
216    inner_display_debug_format(input)
217}
218
219/// A procedural macro that implements the `std::fmt::Debug` trait for a type,
220/// with support for the `#[debug(skip)]` attribute to skip specific fields.
221///
222/// This macro derives a custom Debug implementation that behaves like the standard
223/// library's Debug derive, but allows individual fields to be excluded from the
224/// debug output by annotating them with `#[debug(skip)]`.
225///
226/// # Supported Attributes
227/// - `#[debug(skip)]`: Excludes the field from the debug output
228///
229/// # Examples
230///
231/// ## Struct Example
232/// ```rust
233/// use lombok_macros::*;
234///
235/// #[derive(CustomDebug)]
236/// struct User {
237///     name: String,
238///     #[debug(skip)]
239///     password: String,
240///     email: String,
241/// }
242///
243/// let user = User {
244///     name: "Alice".to_string(),
245///     password: "secret123".to_string(),
246///     email: "alice@example.com".to_string(),
247/// };
248/// let expected_debug = "User { name: \"Alice\", email: \"alice@example.com\" }";
249/// assert_eq!(format!("{:?}", user), expected_debug);
250/// ```
251///
252/// ## Enum Example
253/// ```rust
254/// use lombok_macros::*;
255///
256/// #[derive(CustomDebug)]
257/// enum Response {
258///     Success { data: String },
259///     Error {
260///         message: String,
261///         #[debug(skip)]
262///         internal_code: u32,
263///     },
264/// }
265///
266/// let success = Response::Success { data: "Hello".to_string() };
267/// let error = Response::Error { message: "Failed".to_string(), internal_code: 500 };
268/// let expected_success = "Success { data: \"Hello\" }";
269/// let expected_error = "Error { message: \"Failed\" }";
270/// assert_eq!(format!("{:?}", success), expected_success);
271/// assert_eq!(format!("{:?}", error), expected_error);
272/// ```
273///
274/// # Parameters
275/// - `input`: The input token stream representing the Rust item (struct, enum, etc.)
276///   for which the Debug implementation will be generated.
277///
278/// # Returns
279/// - `TokenStream`: The generated `std::fmt::Debug` implementation for the type
280///   that respects the `#[debug(skip)]` attribute.
281#[proc_macro_derive(CustomDebug, attributes(debug))]
282pub fn custom_debug(input: TokenStream) -> TokenStream {
283    inner_custom_debug(input)
284}
285
286/// A procedural macro that generates a constructor function for structs.
287///
288/// This macro automatically generates a `new` function that takes all non-skipped fields
289/// as parameters and returns a new instance of the struct. Fields marked with `#[new(skip)]`
290/// will be initialized with their default values.
291///
292/// # Supported Attributes
293/// - `#[new(skip)]`: Excludes the field from constructor parameters and uses default initialization
294/// - `#[new(pub)]`: Generates a public constructor  
295/// - `#[new(pub(crate))]`: Generates a crate-visible constructor  
296/// - `#[new(pub(super))]`: Generates a constructor visible to parent module  
297/// - `#[new(private)]`: Generates a private constructor
298///
299/// # Default Behavior
300/// - The generated constructor is `pub` by default
301/// - All fields are included in the constructor unless marked with `#[new(skip)]`
302/// - Skipped fields are initialized using `Default::default()`
303///
304/// # Examples
305///
306/// ## Basic Usage
307/// ```rust
308/// use lombok_macros::*;
309///
310/// #[derive(New)]
311/// struct Person {
312///     name: String,
313///     age: u32,
314/// }
315///
316/// let person = Person::new("Alice".to_string(), 30);
317/// assert_eq!(person.name, "Alice");
318/// assert_eq!(person.age, 30);
319/// ```
320///
321/// ## With Skip Attribute
322/// ```rust
323/// use lombok_macros::*;
324///
325/// #[derive(New)]
326/// struct User {
327///     username: String,
328///     email: String,
329///     #[new(skip)]
330///     created_at: String,
331/// }
332///
333/// let user = User::new("alice".to_string(), "alice@example.com".to_string());
334/// assert_eq!(user.username, "alice");
335/// assert_eq!(user.email, "alice@example.com");
336/// assert_eq!(user.created_at, ""); // skipped field defaults to empty string
337/// ```
338///
339/// ## With Visibility Control
340/// ```rust
341/// use lombok_macros::*;
342///
343/// #[derive(New)]
344/// #[new(pub(crate))]
345/// struct InternalStruct {
346///     value: i32,
347/// }
348/// ```
349///
350/// # Parameters
351/// - `input`: The input token stream representing the struct for which to generate the constructor.
352///
353/// # Returns
354/// - `TokenStream`: The generated constructor implementation.
355#[proc_macro_derive(New, attributes(new))]
356pub fn new(input: TokenStream) -> TokenStream {
357    let derive_input: DeriveInput = parse_macro_input!(input as DeriveInput);
358    let visibility: Visibility = parse_new_visibility(&derive_input);
359    inner_new_constructor(&derive_input, visibility)
360}