| 1 | use syn::{parse_macro_input, DeriveInput}; |
| 2 | |
| 3 | mod body_impl; |
| 4 | mod default_attr; |
| 5 | mod util; |
| 6 | |
| 7 | /// # Smart Default |
| 8 | /// |
| 9 | /// This crate provides a custom derive for `SmartDefault`. `SmartDefault` is not a real trait - |
| 10 | /// deriving it will actually `impl Default`. The difference from regular `#[derive(Default)]` is |
| 11 | /// that `#[derive(SmartDefault)]` allows you to use `#[default = "..."]` attributes to customize |
| 12 | /// the `::default()` method and to support `struct`s that don't have `Default` for all their |
| 13 | /// fields - and even `enum`s! |
| 14 | /// |
| 15 | /// # Examples |
| 16 | /// |
| 17 | /// ``` |
| 18 | /// use smart_default::SmartDefault; |
| 19 | /// |
| 20 | /// # fn main() { |
| 21 | /// #[derive(SmartDefault)] |
| 22 | /// # #[derive(PartialEq)] |
| 23 | /// # #[allow (dead_code)] |
| 24 | /// enum Foo { |
| 25 | /// Bar, |
| 26 | /// #[default] |
| 27 | /// Baz { |
| 28 | /// #[default = 12] |
| 29 | /// a: i32, |
| 30 | /// b: i32, |
| 31 | /// #[default(Some(Default::default()))] |
| 32 | /// c: Option<i32>, |
| 33 | /// #[default(_code = "vec![1, 2, 3]" )] |
| 34 | /// d: Vec<u32>, |
| 35 | /// #[default = "four" ] |
| 36 | /// e: String, |
| 37 | /// }, |
| 38 | /// Qux(i32), |
| 39 | /// } |
| 40 | /// |
| 41 | /// assert!(Foo::default() == Foo::Baz { |
| 42 | /// a: 12, |
| 43 | /// b: 0, |
| 44 | /// c: Some(0), |
| 45 | /// d: vec![1, 2, 3], |
| 46 | /// e: "four" .to_owned(), |
| 47 | /// }); |
| 48 | /// # } |
| 49 | /// ``` |
| 50 | /// |
| 51 | /// * `Baz` has the `#[default]` attribute. This means that the default `Foo` is a `Foo::Baz`. Only |
| 52 | /// one variant may have a `#[default]` attribute, and that attribute must have no value. |
| 53 | /// * `a` has a `#[default = 12]` attribute. This means that it's default value is `12`. |
| 54 | /// * `b` has no `#[default = ...]` attribute. It's default value will `i32`'s default value |
| 55 | /// instead - `0`. |
| 56 | /// * `c` is an `Option<i32>`, and it's default is `Some(Default::default())`. Rust cannot (currently) |
| 57 | /// parse `#[default = Some(Default::default())]` and therefore we have to use a special syntax: |
| 58 | /// `#[default(Some(Default::default))]` |
| 59 | /// * `d` has the `!` token in it, which cannot (currently) be parsed even with `#[default(...)]`, |
| 60 | /// so we have to encode it as a string and mark it as `_code = `. |
| 61 | /// * `e` is a `String`, so the string literal "four" is automatically converted to it. This |
| 62 | /// automatic conversion **only** happens to string (or byte string) literals - and only if |
| 63 | /// `_code` is not used. |
| 64 | /// * Documentation for the `impl Default` section is generated automatically, specifying the |
| 65 | /// default value returned from `::default()`. |
| 66 | #[proc_macro_derive (SmartDefault, attributes(default))] |
| 67 | pub fn derive_smart_default(input: proc_macro::TokenStream) -> proc_macro::TokenStream { |
| 68 | let input: DeriveInput = parse_macro_input!(input as DeriveInput); |
| 69 | match body_impl::impl_my_derive(&input) { |
| 70 | Ok(output: TokenStream) => output.into(), |
| 71 | Err(error: Error) => error.to_compile_error().into(), |
| 72 | } |
| 73 | } |
| 74 | |