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(¶ms.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}