derive_getters/lib.rs
1//! This library provides two derive macros. One, `Getters` for autogenerating getters and
2//! `Dissolve` for consuming a struct returning a tuple of all fields. They can only be
3//! used on named structs.
4//!
5//! # Derives
6//!
7//! Only named structs can derive `Getters` or `Dissolve`.
8//!
9//! # `Getter` methods generated
10//!
11//! The getter methods generated shall bear the same name as the struct fields and be
12//! publicly visible. The methods return an immutable reference to the struct field of the
13//! same name. If there is already a method defined with that name there'll be a collision.
14//! In these cases one of two attributes can be set to either `skip` or `rename` the getter.
15//!
16//!
17//! # `Getters` Usage
18//!
19//! In lib.rs or main.rs;
20//!
21//!```edition2021
22//! use derive_getters::Getters;
23//!
24//! #[derive(Getters)]
25//! struct User {
26//! name: String,
27//! }
28//!
29//! let user = User { name: "John Doe".to_string() };
30//! assert!(user.name() == "John Doe");
31//! ```
32//!
33//! Here, a method called `num()` has been created for the `Number` struct which gives a
34//! reference to the `num` field.
35//!
36//! This macro can also derive on structs that have simple generic types. For example;
37//!
38//! ```edition2021
39//! # use derive_getters::Getters;
40//! #[derive(Getters)]
41//! struct Generic<T, U> {
42//! gen_t: T,
43//! gen_u: U,
44//! }
45//! #
46//! # fn main() { }
47//! ```
48//!
49//! The macro can also handle generic types with trait bounds. For example;
50//! ```edition2021
51//! # use derive_getters::Getters;
52//! #[derive(Getters)]
53//! struct Generic<T: Clone, U: Copy> {
54//! gen_t: T,
55//! gen_u: U,
56//! }
57//! #
58//! # fn main() { }
59//! ```
60//! The trait bounds can also be declared in a `where` clause.
61//!
62//! Additionaly, simple lifetimes are OK too;
63//! ```edition2021
64//! # use derive_getters::Getters;
65//! #[derive(Getters)]
66//! struct Annotated<'a, 'b, T> {
67//! stuff: &'a T,
68//! comp: &'b str,
69//! num: u64,
70//! }
71//! #
72//! # fn main() { }
73//! ```
74//!
75//! # `Getter` Attributes
76//! Getters can be further configured to either skip or rename a getter.
77//!
78//! * #[getter(skip)]
79//! Will skip generating a getter for the field being decorated.
80//!
81//! * #[getter(rename = "name")]
82//! Changes the name of the getter (default is the field name) to "name".
83//!
84//!```edition2021
85//! # use derive_getters::Getters;
86//! #[derive(Getters)]
87//! struct Attributed {
88//! keep_me: u64,
89//!
90//! #[getter(skip)]
91//! skip_me: u64,
92//!
93//! #[getter(rename = "number")]
94//! rename_me: u64,
95//! }
96//! #
97//! # fn main() { }
98//! ```
99//!
100//! # `Dissolve` method generated
101//!
102//! Deriving `Dissolve` on a named or unit struct will generate a method `dissolve(self)`
103//! which shall return a tuple of all struct fields in the order they were defined. Calling
104//! this method consumes the struct. The name of this method can be changed with an
105//! attribute.
106//!
107//! # `Dissolve` usage
108//!
109//! ```edition2021
110//! # use derive_getters::Dissolve;
111//! #[derive(Dissolve)]
112//! struct Stuff {
113//! name: String,
114//! price: f64,
115//! count: usize,
116//! }
117//!
118//! fn main() {
119//! let stuff = Stuff {
120//! name: "Hogie".to_owned(),
121//! price: 123.4f64,
122//! count: 100,
123//! };
124//!
125//! let (n, p, c) = stuff.dissolve();
126//! assert!(n == "Hogie");
127//! assert!(p == 123.4f64);
128//! assert!(c == 100);
129//! }
130//! ```
131//!
132//! # `Dissolve` can be derived on tuple structs.
133//!
134//! ```edition2021
135//! # use derive_getters::Dissolve;
136//! #[derive(Dissolve)]
137//! struct Stuff(String, f64, usize);
138//!
139//! fn main() {
140//! let stuff = Stuff("Hogie".to_owned(), 123.4f64, 100);
141//!
142//! let (n, p, c) = stuff.dissolve();
143//! assert!(n == "Hogie");
144//! assert!(p == 123.4f64);
145//! assert!(c == 100);
146//! }
147//! ```
148//!
149//! # `Dissolve` Attributes
150//! You can rename the `dissolve` function by using a struct attribute.
151//!
152//! * #[dissolve(rename = "name")]
153//!
154//! ```edition2021
155//! # use derive_getters::Dissolve;
156//! #[derive(Dissolve)]
157//! #[dissolve(rename = "shatter")]
158//! struct Numbers {
159//! a: u64,
160//! b: i64,
161//! c: f64,
162//! }
163//! #
164//! # fn main() { }
165//! ```
166//!
167//! # Comment Replication/Generation
168//!
169//! Comments are produced for the auto-generated getters or dissolver. A comment is also
170//! generated for the impl block.
171//!
172//! ## Replication of comments
173//!
174//! Any field comments are replicated for the getter. If the field on the target struct
175//! has a comment; the getter for it shall have the exact same comment.
176//!
177//! ```edition2021
178//! # use derive_getters::Getters;
179//! #[derive(Getters)]
180//! struct Number {
181//! /// My special number.
182//! num: u64,
183//! }
184//! #
185//! # fn main() { }
186//!```
187//!
188//! ## Generation of comments
189//!
190//! If no comment is present for the field, one shall be generated like so;
191//! " Get field `{}` from instance of `{}`."
192//!
193//! A comment for the dissolve function shall be similarily generated;
194//! "Dissolve `{}` into a tuple consisting of its fields in order of declaration."
195//!
196//! The impl block for the getters or dissolve function also has a comment generated;
197//! "Auto-generated by `derive_getters::Getters`." and or
198//! "Auto-generated by `derive_getters::Dissolve`".
199//!
200//! # Panics
201//!
202//! If `Getters` is derived on unit, unnamed structs, enums or unions.
203//! If `Dissolve` is dervied on unnamed structs, enums or unions.
204//!
205//! # Cannot Do
206//! Const generics aren't handled by this macro nor are they tested.
207use std::convert::TryFrom;
208
209extern crate proc_macro;
210use syn::{parse_macro_input, DeriveInput};
211
212mod dissolve;
213mod extract;
214mod faultmsg;
215mod getters;
216
217/// Generate getter methods for all named struct fields in a seperate struct `impl` block.
218/// Getter methods share the name of the field they're 'getting'. Methods return an
219/// immutable reference to the field.
220#[proc_macro_derive(Getters, attributes(getter))]
221pub fn getters(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
222 let ast = parse_macro_input!(input as DeriveInput);
223
224 getters::NamedStruct::try_from(&ast)
225 .map(|ns| ns.emit())
226 .unwrap_or_else(|err| err.to_compile_error())
227 .into()
228}
229
230/// Produce a `dissolve` method that consumes the named struct returning a tuple of all the
231/// the struct fields.
232#[proc_macro_derive(Dissolve, attributes(dissolve))]
233pub fn dissolve(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
234 let ast = parse_macro_input!(input as DeriveInput);
235
236 dissolve::NamedStruct::try_from(&ast)
237 .map(|ns| ns.emit())
238 .unwrap_or_else(|err| err.to_compile_error())
239 .into()
240}