1 // We support Rust 1.15 and struct initialization shorthand syntax is a Rust 1.17 feature
2 //
3 // NOTE: Rust 1.17 and older cannot parse `::` in attributes so we can't use
4 // `allow(clippy::redundant_field_names)`.
5 // Instead, we resort to using `allow(redundant_field_names)`, but this triggers
6 // `renamed_and_removed_lints` which we also want to allow.
7 #![cfg_attr(feature = "cargo-clippy", allow(
8     renamed_and_removed_lints,
9     redundant_field_names,
10 ))]
11 
12 extern crate proc_macro;
13 extern crate proc_macro2;
14 #[macro_use]
15 extern crate syn;
16 
17 #[macro_use]
18 extern crate quote;
19 
20 mod ast;
21 mod attr;
22 mod bound;
23 mod clone;
24 mod cmp;
25 mod debug;
26 mod default;
27 mod hash;
28 mod matcher;
29 mod utils;
30 
31 use proc_macro::TokenStream;
32 
derive_impls(input: &ast::Input) -> Result<proc_macro2::TokenStream, String>33 fn derive_impls(input: &ast::Input) -> Result<proc_macro2::TokenStream, String> {
34     let mut tokens = proc_macro2::TokenStream::new();
35 
36     if input.attrs.clone.is_some() {
37         tokens.extend(clone::derive_clone(input));
38     }
39     if input.attrs.copy.is_some() {
40         tokens.extend(clone::derive_copy(input));
41     }
42     if input.attrs.debug.is_some() {
43         tokens.extend(debug::derive(input));
44     }
45     if let Some(ref default) = input.attrs.default {
46         tokens.extend(default::derive(input, default));
47     }
48     if input.attrs.eq.is_some() {
49         tokens.extend(cmp::derive_eq(input));
50     }
51     if input.attrs.hash.is_some() {
52         tokens.extend(hash::derive(input));
53     }
54     if input.attrs.partial_eq.is_some() {
55         tokens.extend(cmp::derive_partial_eq(input)?);
56     }
57 
58     Ok(tokens)
59 }
60 
detail(input: TokenStream) -> Result<TokenStream, String>61 fn detail(input: TokenStream) -> Result<TokenStream, String> {
62     let parsed = syn::parse::<syn::DeriveInput>(input).map_err(|e| e.to_string())?;
63     let output = derive_impls(&ast::Input::from_ast(&parsed)?)?;
64     Ok(output.into())
65 }
66 
67 #[cfg_attr(
68     not(test),
69     proc_macro_derive(Derivative, attributes(derivative))
70 )]
derivative(input: TokenStream) -> TokenStream71 pub fn derivative(input: TokenStream) -> TokenStream {
72     match detail(input) {
73         Ok(output) => output,
74         Err(e) => panic!(e),
75     }
76 }
77