Coverage Report

Created: 2025-02-07 03:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/runner/work/bare_err_tree/bare_err_tree/bare_err_tree_proc/src/boiler.rs
Line
Count
Source
1
/*
2
 * This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
 */
6
7
use std::iter;
8
9
use proc_macro::TokenStream;
10
use quote::quote;
11
use syn::{Attribute, Generics, Ident, Meta};
12
13
/// Derives intended to minimize friction introduced by the wrapper.
14
///
15
/// Derives transparent Error, Debug, From (both ways), and Deref(Mut).
16
/// If known derivable traits are in scope, re-derives those as well.
17
1
pub fn wrapper_boilerplate(
18
1
    ident: &Ident,
19
1
    generics: &Generics,
20
1
    attrs: &[Attribute],
21
1
    name_attribute: &Ident,
22
1
) -> TokenStream {
23
1
    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
24
1
25
1
    // Core set
26
1
    let universal: TokenStream = quote! {
27
1
        #[automatically_derived]
28
1
        impl #impl_generics ::core::error::Error for #name_attribute #ty_generics #where_clause {
29
1
            fn source(&self) -> Option<&(dyn ::core::error::Error + 'static)> {
30
1
                ::core::error::Error::source(&self.inner)
31
1
            }
32
1
        }
33
1
34
1
        #[automatically_derived]
35
1
        impl #impl_generics ::core::fmt::Debug for #name_attribute #ty_generics #where_clause {
36
1
            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), ::core::fmt::Error> {
37
1
                ::core::fmt::Debug::fmt(&self.inner, f)
38
1
            }
39
1
        }
40
1
41
1
        #[automatically_derived]
42
1
        impl #impl_generics ::core::fmt::Display for #name_attribute #ty_generics #where_clause {
43
1
            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> Result<(), ::core::fmt::Error> {
44
1
                ::core::fmt::Display::fmt(&self.inner, f)
45
1
            }
46
1
        }
47
1
48
1
        #[automatically_derived]
49
1
        impl #impl_generics ::core::convert::From<#ident #ty_generics> for #name_attribute #ty_generics #where_clause {
50
1
            #[track_caller]
51
1
            fn from(inner: #ident #ty_generics) -> Self {
52
1
                Self::_tree(inner)
53
1
            }
54
1
        }
55
1
56
1
        #[automatically_derived]
57
1
        impl #impl_generics ::core::convert::From<#name_attribute #ty_generics> for #ident #ty_generics #where_clause {
58
1
            fn from(value: #name_attribute #ty_generics) -> Self {
59
1
                value.inner
60
1
            }
61
1
        }
62
1
63
1
        #[automatically_derived]
64
1
        impl #impl_generics ::core::ops::Deref for #name_attribute #ty_generics #where_clause {
65
1
            type Target = #ident #ty_generics;
66
1
            fn deref(&self) -> &Self::Target {
67
1
                &self.inner
68
1
            }
69
1
        }
70
1
71
1
        #[automatically_derived]
72
1
        impl #impl_generics ::core::ops::DerefMut for #name_attribute #ty_generics #where_clause {
73
1
            fn deref_mut(&mut self) -> &mut Self::Target {
74
1
                &mut self.inner
75
1
            }
76
1
        }
77
1
    }
78
1
    .into();
79
1
80
1
    // Look for viable extra derives
81
1
    let mut extra_derive = Vec::new();
82
1
    attrs.iter().for_each(|x| {
83
1
        if let Meta::List(list) = &x.meta {
84
1
            if list.path.get_ident().map(|x| x.to_string()) == Some("derive".to_string()) {
85
1
                let _ = list.parse_nested_meta(|meta| {
86
1
                    if let Some(ident) = meta.path.get_ident() {
87
1
                        extra_derive.push(ident.clone());
88
1
                    
}0
89
1
                    Ok(())
90
1
                });
91
1
            
}0
92
0
        }
93
1
    });
94
1
95
1
    // Optimistically added extra derives
96
1
    let extra_derive_tokens =
97
1
        extra_derive
98
1
            .into_iter()
99
1
            .map(|extra| match extra.to_string().to_lowercase().as_str() {
100
1
                "eq" => quote! {
101
0
                    #[automatically_derived]
102
0
                    impl #impl_generics ::core::cmp::Eq for #name_attribute #ty_generics #where_clause {}
103
0
                }
104
0
                .into(),
105
1
                "partialeq" => quote! {
106
0
                    #[automatically_derived]
107
0
                    impl #impl_generics ::core::cmp::PartialEq<#name_attribute #ty_generics> for #name_attribute #ty_generics #where_clause {
108
0
                        fn eq(&self, other: &#name_attribute #ty_generics) -> bool {
109
0
                            self.inner == other.inner
110
0
                        }
111
0
                    }
112
0
                }
113
0
                .into(),
114
1
                "ord" => quote! {
115
0
                    #[automatically_derived]
116
0
                    impl #impl_generics ::core::cmp::Ord for #name_attribute #ty_generics #where_clause {
117
0
                        fn ord(&self, other: &Self) -> bool {
118
0
                            <#ident #ty_generics #where_clause as ::core::cmp::Ord>::ord(self.inner, other.inner)
119
0
                        }
120
0
                    }
121
0
                }
122
0
                .into(),
123
1
                "partialord" => quote! {
124
0
                    #[automatically_derived]
125
0
                    impl #impl_generics ::core::cmp::PartialOrd for #name_attribute #ty_generics #where_clause {
126
0
                        fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
127
0
                            <#ident #ty_generics #where_clause as ::core::cmp::ParitalOrd>::partial_cmp(self.inner, other.inner)
128
0
                        }
129
0
                    }
130
0
                }
131
0
                .into(),
132
1
                "clone" => quote! {
133
0
                    #[automatically_derived]
134
0
                    impl #impl_generics ::core::clone::Clone for #name_attribute #ty_generics #where_clause {
135
0
                        fn clone(&self) -> Self {
136
0
                            Self {
137
0
                                inner: self.inner.clone(),
138
0
                                _err_tree_pkg: self._err_tree_pkg.clone()
139
0
                            }
140
0
                        }
141
0
                    }
142
0
                }
143
0
                .into(),
144
1
                "hash" => quote! {
145
0
                    #[automatically_derived]
146
0
                    impl #impl_generics ::core::hash::Hash for #name_attribute #ty_generics #where_clause {
147
0
                        fn hash<H>(&self, state: &mut H)
148
0
                            where H: ::core::hash::Hasher
149
0
                        {
150
0
                            self.inner.hash(state)
151
0
                        }
152
0
                    }
153
0
                }
154
0
                .into(),
155
1
                "default" => quote! {
156
0
                    #[automatically_derived]
157
0
                    impl #impl_generics ::core::default::Default for #name_attribute #ty_generics #where_clause {
158
0
                        #[track_caller]
159
0
                        fn default() -> Self {
160
0
                            Self {
161
0
                                inner: #ident ::default(),
162
0
                                _err_tree_pkg: ::bare_err_tree::ErrTreePkg::default(),
163
0
                            }
164
0
                        }
165
0
                    }
166
0
                }
167
0
                .into(),
168
1
                _ => quote! {}.into(),
169
1
            });
170
1
171
1
    TokenStream::from_iter(iter::once(universal).chain(extra_derive_tokens))
172
1
}