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