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}