1#![allow(deprecated)]
3#![allow(renamed_and_removed_lints)] #![allow(clippy::unknown_clippy_lints)] #![allow(clippy::mem_replace_with_default)] #![allow(clippy::option_as_ref_deref)] #![allow(clippy::cyclomatic_complexity)] #![allow(clippy::cognitive_complexity)] #![allow(clippy::redundant_closure)]
10
11extern crate proc_macro;
12extern crate proc_macro2;
13#[macro_use]
14extern crate syn;
15
16#[macro_use]
17extern crate quote;
18
19mod ast;
20mod attr;
21mod bound;
22mod clone;
23mod cmp;
24mod debug;
25mod default;
26mod hash;
27mod matcher;
28mod paths;
29mod utils;
30
31use proc_macro::TokenStream;
32
33fn derive_impls(
34 input: &mut ast::Input,
35 errors: &mut proc_macro2::TokenStream,
36) -> proc_macro2::TokenStream {
37 let mut tokens = proc_macro2::TokenStream::new();
38
39 if input.attrs.clone.is_some() {
40 tokens.extend(clone::derive_clone(input));
41 }
42 if input.attrs.copy.is_some() {
43 tokens.extend(clone::derive_copy(input));
44 }
45 if input.attrs.debug.is_some() {
46 tokens.extend(debug::derive(input));
47 }
48 if let Some(ref default) = input.attrs.default {
49 tokens.extend(default::derive(input, default));
50 }
51 if input.attrs.eq.is_some() {
52 tokens.extend(cmp::derive_eq(input));
53 }
54 if input.attrs.hash.is_some() {
55 tokens.extend(hash::derive(input));
56 }
57 if input.attrs.partial_eq.is_some() {
58 tokens.extend(cmp::derive_partial_eq(input));
59 }
60 if input.attrs.partial_ord.is_some() {
61 tokens.extend(cmp::derive_partial_ord(input, errors));
62 }
63 if input.attrs.ord.is_some() {
64 tokens.extend(cmp::derive_ord(input, errors));
65 }
66
67 tokens.extend(std::mem::replace(errors, Default::default()));
68
69 tokens
70}
71
72#[cfg(not(tarpaulin_include))]
73#[cfg_attr(not(test), proc_macro_derive(Derivative, attributes(derivative)))]
74pub fn derivative(input: TokenStream) -> TokenStream {
75 derivative_internal(syn::parse_macro_input!(input as syn::DeriveInput)).into()
76}
77
78fn derivative_internal(input: syn::DeriveInput) -> proc_macro2::TokenStream {
79 let mut errors = proc_macro2::TokenStream::new();
80
81 let mut output = ast::Input::from_ast(&input, &mut errors)
82 .map(|mut input| derive_impls(&mut input, &mut errors))
83 .unwrap_or_default();
84
85 output.extend(errors);
86 output
87}
88
89#[test]
90fn macro_code_coverage() {
91 for entry in walkdir::WalkDir::new("tests")
92 .into_iter()
93 .map(|e| e.unwrap())
94 .filter(|e| e.file_type().is_file())
95 .filter(|e| e.path().extension().map(|e| e == "rs").unwrap_or(false))
96 {
97 let file = std::fs::File::open(entry.path()).unwrap();
98
99 runtime_macros_derive::emulate_derive_expansion_fallible(
100 file,
101 "Derivative",
102 derivative_internal,
103 )
104 .unwrap();
105 }
106}