bon_macros/builder/builder_gen/member/config/
blanket.rs

1use super::MemberConfig;
2use crate::builder::builder_gen::member::MemberOrigin;
3use crate::builder::builder_gen::top_level_config::OnConfig;
4use crate::util::prelude::*;
5use std::fmt;
6
7pub(crate) enum BlanketParamName {
8    Into,
9    Overwritable,
10}
11
12impl fmt::Display for BlanketParamName {
13    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14        match self {
15            Self::Into => fmt::Display::fmt(&super::ParamName::Into, f),
16            Self::Overwritable => fmt::Display::fmt(&super::ParamName::Overwritable, f),
17        }
18    }
19}
20
21impl BlanketParamName {
22    fn value_in_on_config(&self, cfg: &OnConfig) -> darling::util::Flag {
23        match self {
24            Self::Into => cfg.into,
25            Self::Overwritable => cfg.overwritable,
26        }
27    }
28
29    fn value_in_member_config(&self, cfg: &MemberConfig) -> darling::util::Flag {
30        match self {
31            Self::Into => cfg.into,
32            Self::Overwritable => cfg.overwritable,
33        }
34    }
35}
36
37pub(crate) struct EvalBlanketFlagParam<'a> {
38    pub(crate) on: &'a [OnConfig],
39    pub(crate) param_name: BlanketParamName,
40    pub(crate) member_config: &'a MemberConfig,
41    pub(crate) scrutinee: &'a syn::Type,
42    pub(crate) origin: MemberOrigin,
43}
44
45impl EvalBlanketFlagParam<'_> {
46    pub(crate) fn eval(self) -> Result<darling::util::Flag> {
47        let Self {
48            on,
49            param_name,
50            member_config,
51            scrutinee,
52            origin,
53        } = self;
54
55        let verdict_from_on = on
56            .iter()
57            .map(|params| Ok((params, scrutinee.matches(&params.type_pattern)?)))
58            .collect::<Result<Vec<_>>>()?
59            .into_iter()
60            .filter(|(_, matched)| *matched)
61            .map(|(params, _)| param_name.value_in_on_config(params))
62            .find(darling::util::Flag::is_present);
63
64        let value_in_member = param_name.value_in_member_config(member_config);
65        let flag = match (verdict_from_on, value_in_member.is_present()) {
66            (Some(_), true) => {
67                bail!(
68                    &value_in_member.span(),
69                    "this `#[builder({param_name})]` attribute is redundant, because \
70                    `{param_name}` is already implied for this member via the \
71                    `#[builder(on(...))]` at the top of the {}",
72                    origin.parent_construct(),
73                );
74            }
75            (Some(flag), false) => flag,
76            (None, _) => value_in_member,
77        };
78
79        Ok(flag)
80    }
81}