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(set, get, get_mut, new))]
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    let derive_input: DeriveInput = parse_macro_input!(input as DeriveInput);
179    let new_constructor: TokenStream = inner_new_constructor(&derive_input, Visibility::Public);
180    result.extend(
181        new_constructor
182            .to_string()
183            .parse::<TokenStream2>()
184            .unwrap_or_default(),
185    );
186    result.into()
187}
188
189/// A procedural macro that implements the `std::fmt::Display` trait for a type,
190/// using the standard debug format (`{:?}`) for formatting.
191///
192/// This macro derives the `Display` implementation for a type, allowing it to be formatted
193/// using `{:?}` in formatting macros. It uses the `inner_display_debug` function to generate
194/// the implementation with the standard debug format.
195///
196/// # Parameters
197/// - `input`: The input token stream representing the Rust item (struct, enum, etc.)
198///   for which the `Display` implementation will be generated.
199///
200/// # Returns
201/// - `TokenStream`: The generated `std::fmt::Display` implementation for the type
202///   using the standard debug format.
203#[proc_macro_derive(DisplayDebug)]
204pub fn display_debug(input: TokenStream) -> TokenStream {
205    inner_display_debug(input)
206}
207
208/// A procedural macro that implements the `std::fmt::Display` trait for a type,
209/// using the detailed debug format (`{:#?}`) for formatting.
210///
211/// This macro derives the `Display` implementation for a type, allowing it to be formatted
212/// using `{:#?}` in formatting macros. It uses the `inner_display_debug_format` function
213/// to generate the implementation with the detailed debug format.
214///
215/// # Parameters
216/// - `input`: The input token stream representing the Rust item (struct, enum, etc.)
217///   for which the `Display` implementation will be generated.
218///
219/// # Returns
220/// - `TokenStream`: The generated `std::fmt::Display` implementation for the type
221///   using the detailed debug format.
222#[proc_macro_derive(DisplayDebugFormat)]
223pub fn display_debug_format(input: TokenStream) -> TokenStream {
224    inner_display_debug_format(input)
225}
226
227/// A procedural macro that implements the `std::fmt::Debug` trait for a type,
228/// with support for the `#[debug(skip)]` attribute to skip specific fields.
229///
230/// This macro derives a custom Debug implementation that behaves like the standard
231/// library's Debug derive, but allows individual fields to be excluded from the
232/// debug output by annotating them with `#[debug(skip)]`.
233///
234/// # Supported Attributes
235/// - `#[debug(skip)]`: Excludes the field from the debug output
236///
237/// # Examples
238///
239/// ## Struct Example
240/// ```rust
241/// use lombok_macros::*;
242///
243/// #[derive(CustomDebug)]
244/// struct User {
245///     name: String,
246///     #[debug(skip)]
247///     password: String,
248///     email: String,
249/// }
250///
251/// let user = User {
252///     name: "Alice".to_string(),
253///     password: "secret123".to_string(),
254///     email: "alice@example.com".to_string(),
255/// };
256/// let expected_debug = "User { name: \"Alice\", email: \"alice@example.com\" }";
257/// assert_eq!(format!("{:?}", user), expected_debug);
258/// ```
259///
260/// ## Enum Example
261/// ```rust
262/// use lombok_macros::*;
263///
264/// #[derive(CustomDebug)]
265/// enum Response {
266///     Success { data: String },
267///     Error {
268///         message: String,
269///         #[debug(skip)]
270///         internal_code: u32,
271///     },
272/// }
273///
274/// let success = Response::Success { data: "Hello".to_string() };
275/// let error = Response::Error { message: "Failed".to_string(), internal_code: 500 };
276/// let expected_success = "Success { data: \"Hello\" }";
277/// let expected_error = "Error { message: \"Failed\" }";
278/// assert_eq!(format!("{:?}", success), expected_success);
279/// assert_eq!(format!("{:?}", error), expected_error);
280/// ```
281///
282/// # Parameters
283/// - `input`: The input token stream representing the Rust item (struct, enum, etc.)
284///   for which the Debug implementation will be generated.
285///
286/// # Returns
287/// - `TokenStream`: The generated `std::fmt::Debug` implementation for the type
288///   that respects the `#[debug(skip)]` attribute.
289#[proc_macro_derive(CustomDebug, attributes(debug))]
290pub fn custom_debug(input: TokenStream) -> TokenStream {
291    inner_custom_debug(input)
292}
293
294/// A procedural macro that generates a constructor function for structs.
295///
296/// This macro automatically generates a `new` function that takes all non-skipped fields
297/// as parameters and returns a new instance of the struct. Fields marked with `#[new(skip)]`
298/// will be initialized with their default values.
299///
300/// # Supported Attributes
301/// - `#[new(skip)]`: Excludes the field from constructor parameters and uses default initialization
302/// - `#[new(pub)]`: Generates a public constructor  
303/// - `#[new(pub(crate))]`: Generates a crate-visible constructor  
304/// - `#[new(pub(super))]`: Generates a constructor visible to parent module  
305/// - `#[new(private)]`: Generates a private constructor
306///
307/// # Default Behavior
308/// - The generated constructor is `pub` by default
309/// - All fields are included in the constructor unless marked with `#[new(skip)]`
310/// - Skipped fields are initialized using `Default::default()`
311///
312/// # Examples
313///
314/// ## Basic Usage
315/// ```rust
316/// use lombok_macros::*;
317///
318/// #[derive(New)]
319/// struct Person {
320///     name: String,
321///     age: u32,
322/// }
323///
324/// let person = Person::new("Alice".to_string(), 30);
325/// assert_eq!(person.name, "Alice");
326/// assert_eq!(person.age, 30);
327/// ```
328///
329/// ## With Skip Attribute
330/// ```rust
331/// use lombok_macros::*;
332///
333/// #[derive(New)]
334/// struct User {
335///     username: String,
336///     email: String,
337///     #[new(skip)]
338///     created_at: String,
339/// }
340///
341/// let user = User::new("alice".to_string(), "alice@example.com".to_string());
342/// assert_eq!(user.username, "alice");
343/// assert_eq!(user.email, "alice@example.com");
344/// assert_eq!(user.created_at, ""); // skipped field defaults to empty string
345/// ```
346///
347/// ## With Visibility Control
348/// ```rust
349/// use lombok_macros::*;
350///
351/// #[derive(New)]
352/// #[new(pub(crate))]
353/// struct InternalStruct {
354///     value: i32,
355/// }
356/// ```
357///
358/// # Parameters
359/// - `input`: The input token stream representing the struct for which to generate the constructor.
360///
361/// # Returns
362/// - `TokenStream`: The generated constructor implementation.
363#[proc_macro_derive(New, attributes(new))]
364pub fn new(input: TokenStream) -> TokenStream {
365    let derive_input: DeriveInput = parse_macro_input!(input as DeriveInput);
366    let visibility: Visibility = parse_new_visibility(&derive_input);
367    inner_new_constructor(&derive_input, visibility)
368}