bon_macros/builder/builder_gen/member/config/
setters.rs1use crate::parsing::{ItemSigConfig, ItemSigConfigParsing, SpannedKey};
2use crate::util::prelude::*;
3use darling::ast::NestedMeta;
4use darling::FromMeta;
5use syn::punctuated::Punctuated;
6
7const DOCS_CONTEXT: &str = "builder struct's impl block";
8
9fn parse_setter_fn(meta: &syn::Meta) -> Result<SpannedKey<ItemSigConfig>> {
10 let params = ItemSigConfigParsing::new(meta, Some(DOCS_CONTEXT)).parse()?;
11 SpannedKey::new(meta.path(), params)
12}
13
14fn parse_docs(meta: &syn::Meta) -> Result<SpannedKey<Vec<syn::Attribute>>> {
15 crate::parsing::parse_docs_without_self_mentions(DOCS_CONTEXT, meta)
16}
17
18#[derive(Debug, Default)]
19pub(crate) struct SettersConfig {
20 pub(crate) name: Option<SpannedKey<syn::Ident>>,
21 pub(crate) vis: Option<SpannedKey<syn::Visibility>>,
22 pub(crate) doc: SettersDocConfig,
23 pub(crate) fns: SettersFnsConfig,
24}
25
26impl FromMeta for SettersConfig {
27 fn from_meta(meta: &syn::Meta) -> Result<Self> {
28 let meta: Punctuated<syn::Meta, syn::Token![,]> =
29 crate::parsing::parse_paren_meta_list_with_terminated(meta)?;
30
31 let (docs, remaining_meta): (Vec<_>, Vec<_>) = meta
32 .into_iter()
33 .partition(|meta| meta.path().is_ident("doc"));
34
35 let doc = SettersDocConfig::from_docs_entries(docs)?;
36
37 #[derive(FromMeta)]
38 struct Parsed {
39 name: Option<SpannedKey<syn::Ident>>,
40 vis: Option<SpannedKey<syn::Visibility>>,
41
42 #[darling(flatten)]
43 fns: SettersFnsConfig,
44 }
45
46 let remaining_meta = remaining_meta
47 .into_iter()
48 .map(NestedMeta::Meta)
49 .collect::<Vec<_>>();
50
51 let parsed: Parsed = Parsed::from_list(&remaining_meta)?;
52
53 Ok(Self {
54 name: parsed.name,
55 vis: parsed.vis,
56 fns: parsed.fns,
57 doc,
58 })
59 }
60}
61
62#[derive(Debug, Default, FromMeta)]
63pub(crate) struct SettersFnsConfig {
64 #[darling(default, with = parse_setter_fn, map = Some)]
69 pub(crate) some_fn: Option<SpannedKey<ItemSigConfig>>,
70
71 #[darling(default, with = parse_setter_fn, map = Some)]
76 pub(crate) option_fn: Option<SpannedKey<ItemSigConfig>>,
77}
78
79#[derive(Debug, Default)]
80pub(crate) struct SettersDocConfig {
81 pub(crate) content: Option<SpannedKey<Vec<syn::Attribute>>>,
83
84 pub(crate) default: Option<SpannedKey<SettersDocDefaultConfig>>,
86}
87
88impl SettersDocConfig {
89 fn from_docs_entries(docs: Vec<syn::Meta>) -> Result<Self> {
90 let mut doc_config = None;
91 let mut doc_content = None;
92
93 for doc in docs {
94 match doc.require_list()?.delimiter {
95 syn::MacroDelimiter::Paren(_) => {
96 if doc_config.is_some() {
97 bail!(&doc, "repeated `doc(...)` attribute is not allowed");
98 }
99 doc_config = Some(doc);
100 }
101 syn::MacroDelimiter::Brace(_) => {
102 if doc_content.is_some() {
103 bail!(&doc, "repeated `doc {{...}}` attribute is not allowed");
104 }
105 doc_content = Some(doc);
106 }
107 syn::MacroDelimiter::Bracket(_) => {
108 bail!(&doc, "wrong delimiter, expected doc(...) or doc {{...}}",);
109 }
110 }
111 }
112
113 #[derive(FromMeta)]
114 struct Parsed {
115 #[darling(with = crate::parsing::parse_non_empty_paren_meta_list)]
116 default: Option<SpannedKey<SettersDocDefaultConfig>>,
117 }
118
119 let config = doc_config
120 .as_ref()
121 .map(crate::parsing::parse_non_empty_paren_meta_list::<Parsed>)
122 .transpose()?;
123
124 let content = doc_content.as_ref().map(parse_docs).transpose()?;
125
126 let mut me = Self {
127 content,
128 default: None,
129 };
130
131 if let Some(Parsed { default }) = config {
132 me.default = default;
133 }
135
136 Ok(me)
137 }
138}
139
140#[derive(Debug, Default, FromMeta)]
141pub(crate) struct SettersDocDefaultConfig {
142 pub(crate) skip: darling::util::Flag,
144}