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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use super::MemberConfig;
use crate::builder::builder_gen::member::MemberOrigin;
use crate::builder::builder_gen::top_level_config::OnConfig;
use crate::util::prelude::*;
use std::fmt;

pub(crate) enum BlanketParamName {
    Into,
    Overwritable,
}

impl fmt::Display for BlanketParamName {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Into => fmt::Display::fmt(&super::ParamName::Into, f),
            Self::Overwritable => fmt::Display::fmt(&super::ParamName::Overwritable, f),
        }
    }
}

impl BlanketParamName {
    fn value_in_on_config(&self, cfg: &OnConfig) -> darling::util::Flag {
        match self {
            Self::Into => cfg.into,
            Self::Overwritable => cfg.overwritable,
        }
    }

    fn value_in_member_config(&self, cfg: &MemberConfig) -> darling::util::Flag {
        match self {
            Self::Into => cfg.into,
            Self::Overwritable => cfg.overwritable,
        }
    }
}

pub(crate) struct EvalBlanketFlagParam<'a> {
    pub(crate) on: &'a [OnConfig],
    pub(crate) param_name: BlanketParamName,
    pub(crate) member_config: &'a MemberConfig,
    pub(crate) scrutinee: &'a syn::Type,
    pub(crate) origin: MemberOrigin,
}

impl EvalBlanketFlagParam<'_> {
    pub(crate) fn eval(self) -> Result<darling::util::Flag> {
        let Self {
            on,
            param_name,
            member_config,
            scrutinee,
            origin,
        } = self;

        let verdict_from_on = on
            .iter()
            .map(|params| Ok((params, scrutinee.matches(&params.type_pattern)?)))
            .collect::<Result<Vec<_>>>()?
            .into_iter()
            .filter(|(_, matched)| *matched)
            .map(|(params, _)| param_name.value_in_on_config(params))
            .find(darling::util::Flag::is_present);

        let value_in_member = param_name.value_in_member_config(member_config);
        let flag = match (verdict_from_on, value_in_member.is_present()) {
            (Some(_), true) => {
                bail!(
                    &value_in_member.span(),
                    "this `#[builder({param_name})]` attribute is redundant, because \
                    `{param_name}` is already implied for this member via the \
                    `#[builder(on(...))]` at the top of the {}",
                    origin.parent_construct(),
                );
            }
            (Some(flag), false) => flag,
            (None, _) => value_in_member,
        };

        Ok(flag)
    }
}