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