Coverage Report

Created: 2025-06-04 02:13

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
25
    // Core set
26
1
    let universal: TokenStream = quote! {
27
        #[automatically_derived]
28
        impl #impl_generics ::core::error::Error for #name_attribute #ty_generics #where_clause {
29
            fn source(&self) -> Option<&(dyn ::core::error::Error + 'static)> {
30
                ::core::error::Error::source(&self.inner)
31
            }
32
        }
33
34
        #[automatically_derived]
35
        impl #impl_generics ::core::fmt::Debug for #name_attribute #ty_generics #where_clause {
36
            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), ::core::fmt::Error> {
37
                ::core::fmt::Debug::fmt(&self.inner, f)
38
            }
39
        }
40
41
        #[automatically_derived]
42
        impl #impl_generics ::core::fmt::Display for #name_attribute #ty_generics #where_clause {
43
            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> Result<(), ::core::fmt::Error> {
44
                ::core::fmt::Display::fmt(&self.inner, f)
45
            }
46
        }
47
48
        #[automatically_derived]
49
        impl #impl_generics ::core::convert::From<#ident #ty_generics> for #name_attribute #ty_generics #where_clause {
50
            #[track_caller]
51
            fn from(inner: #ident #ty_generics) -> Self {
52
                Self::_tree(inner)
53
            }
54
        }
55
56
        #[automatically_derived]
57
        impl #impl_generics ::core::convert::From<#name_attribute #ty_generics> for #ident #ty_generics #where_clause {
58
            fn from(value: #name_attribute #ty_generics) -> Self {
59
                value.inner
60
            }
61
        }
62
63
        #[automatically_derived]
64
        impl #impl_generics ::core::ops::Deref for #name_attribute #ty_generics #where_clause {
65
            type Target = #ident #ty_generics;
66
            fn deref(&self) -> &Self::Target {
67
                &self.inner
68
            }
69
        }
70
71
        #[automatically_derived]
72
        impl #impl_generics ::core::ops::DerefMut for #name_attribute #ty_generics #where_clause {
73
            fn deref_mut(&mut self) -> &mut Self::Target {
74
                &mut self.inner
75
            }
76
        }
77
    }
78
1
    .into();
79
80
    // 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
0
            }
92
0
        }
93
1
    });
94
95
    // 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!0
{
101
                    #[automatically_derived]
102
                    impl #impl_generics ::core::cmp::Eq for #name_attribute #ty_generics #where_clause {}
103
                }
104
0
                .into(),
105
1
                "partialeq" => 
quote!0
{
106
                    #[automatically_derived]
107
                    impl #impl_generics ::core::cmp::PartialEq<#name_attribute #ty_generics> for #name_attribute #ty_generics #where_clause {
108
                        fn eq(&self, other: &#name_attribute #ty_generics) -> bool {
109
                            self.inner == other.inner
110
                        }
111
                    }
112
                }
113
0
                .into(),
114
1
                "ord" => 
quote!0
{
115
                    #[automatically_derived]
116
                    impl #impl_generics ::core::cmp::Ord for #name_attribute #ty_generics #where_clause {
117
                        fn ord(&self, other: &Self) -> bool {
118
                            <#ident #ty_generics #where_clause as ::core::cmp::Ord>::ord(self.inner, other.inner)
119
                        }
120
                    }
121
                }
122
0
                .into(),
123
1
                "partialord" => 
quote!0
{
124
                    #[automatically_derived]
125
                    impl #impl_generics ::core::cmp::PartialOrd for #name_attribute #ty_generics #where_clause {
126
                        fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
127
                            <#ident #ty_generics #where_clause as ::core::cmp::ParitalOrd>::partial_cmp(self.inner, other.inner)
128
                        }
129
                    }
130
                }
131
0
                .into(),
132
1
                "clone" => 
quote!0
{
133
                    #[automatically_derived]
134
                    impl #impl_generics ::core::clone::Clone for #name_attribute #ty_generics #where_clause {
135
                        fn clone(&self) -> Self {
136
                            Self {
137
                                inner: self.inner.clone(),
138
                                _err_tree_pkg: self._err_tree_pkg.clone()
139
                            }
140
                        }
141
                    }
142
                }
143
0
                .into(),
144
1
                "hash" => 
quote!0
{
145
                    #[automatically_derived]
146
                    impl #impl_generics ::core::hash::Hash for #name_attribute #ty_generics #where_clause {
147
                        fn hash<H>(&self, state: &mut H)
148
                            where H: ::core::hash::Hasher
149
                        {
150
                            self.inner.hash(state)
151
                        }
152
                    }
153
                }
154
0
                .into(),
155
1
                "default" => 
quote!0
{
156
                    #[automatically_derived]
157
                    impl #impl_generics ::core::default::Default for #name_attribute #ty_generics #where_clause {
158
                        #[track_caller]
159
                        fn default() -> Self {
160
                            Self {
161
                                inner: #ident ::default(),
162
                                _err_tree_pkg: ::bare_err_tree::ErrTreePkg::default(),
163
                            }
164
                        }
165
                    }
166
                }
167
0
                .into(),
168
1
                _ => quote! {}.into(),
169
1
            });
170
171
1
    TokenStream::from_iter(iter::once(universal).chain(extra_derive_tokens))
172
1
}