derivative/
lib.rs

1// We need to support Rust 1.34 to stable
2#![allow(deprecated)]
3
4#![allow(renamed_and_removed_lints)] // support for multiple Clippy versions
5#![allow(clippy::unknown_clippy_lints)] // because of other #![allow]s
6#![allow(clippy::mem_replace_with_default)] // needs rustc 1.40
7#![allow(clippy::option_as_ref_deref)] // needs rustc 1.40
8#![allow(clippy::cyclomatic_complexity)] // old name of cognitive_complexity
9#![allow(clippy::cognitive_complexity)] // in code generated by macros
10#![allow(clippy::redundant_closure)]
11
12extern crate proc_macro;
13extern crate proc_macro2;
14#[macro_use]
15extern crate syn;
16
17#[macro_use]
18extern crate quote;
19
20mod ast;
21mod attr;
22mod bound;
23mod clone;
24mod cmp;
25mod debug;
26mod default;
27mod hash;
28mod matcher;
29mod paths;
30mod utils;
31
32use proc_macro::TokenStream;
33
34fn derive_impls(
35    input: &mut ast::Input,
36    errors: &mut proc_macro2::TokenStream,
37) -> proc_macro2::TokenStream {
38    let mut tokens = proc_macro2::TokenStream::new();
39
40    if input.attrs.clone.is_some() {
41        tokens.extend(clone::derive_clone(input));
42    }
43    if input.attrs.copy.is_some() {
44        tokens.extend(clone::derive_copy(input));
45    }
46    if input.attrs.debug.is_some() {
47        tokens.extend(debug::derive(input));
48    }
49    if let Some(ref default) = input.attrs.default {
50        tokens.extend(default::derive(input, default));
51    }
52    if input.attrs.eq.is_some() {
53        tokens.extend(cmp::derive_eq(input));
54    }
55    if input.attrs.hash.is_some() {
56        tokens.extend(hash::derive(input));
57    }
58    if input.attrs.partial_eq.is_some() {
59        tokens.extend(cmp::derive_partial_eq(input));
60    }
61    if input.attrs.partial_ord.is_some() {
62        tokens.extend(cmp::derive_partial_ord(input, errors));
63    }
64    if input.attrs.ord.is_some() {
65        tokens.extend(cmp::derive_ord(input, errors));
66    }
67
68    tokens.extend(std::mem::replace(
69        errors,
70        Default::default(),
71    ));
72
73    tokens
74}
75
76#[cfg_attr(not(test), proc_macro_derive(Derivative, attributes(derivative)))]
77pub fn derivative(input: TokenStream) -> TokenStream {
78    let mut errors = proc_macro2::TokenStream::new();
79
80    let mut output = match syn::parse::<syn::DeriveInput>(input) {
81        Ok(parsed) => {
82            ast::Input::from_ast(&parsed, &mut errors)
83                .map(|mut input| derive_impls(&mut input, &mut errors))
84                .unwrap_or_default()
85        },
86        Err(error) => {
87            errors.extend(error.to_compile_error());
88            Default::default()
89        }
90    };
91
92    output.extend(errors);
93    output.into()
94}