|
1 | | -use crate::parsing::{ItemSigConfig, ItemSigConfigParsing, SpannedKey}; |
| 1 | +use crate::parsing::SpannedKey; |
2 | 2 | use crate::util::prelude::*; |
3 | 3 | use darling::FromMeta; |
4 | 4 |
|
5 | 5 | const DOCS_CONTEXT: &str = "builder struct's impl block"; |
6 | 6 |
|
7 | | -fn parse_setter_fn(meta: &syn::Meta) -> Result<SpannedKey<ItemSigConfig>> { |
8 | | - let params = ItemSigConfigParsing { |
9 | | - meta, |
10 | | - reject_self_mentions: Some(DOCS_CONTEXT), |
11 | | - } |
12 | | - .parse()?; |
| 7 | +fn parse_docs(meta: &syn::Meta) -> Result<SpannedKey<Vec<syn::Attribute>>> { |
| 8 | + crate::parsing::parse_docs_without_self_mentions(DOCS_CONTEXT, meta) |
| 9 | +} |
13 | 10 |
|
14 | | - SpannedKey::new(meta.path(), params) |
| 11 | +#[derive(Debug)] |
| 12 | +pub(crate) enum SetterFnName { |
| 13 | + Name(syn::Ident), |
| 14 | + Prefix(syn::Ident), |
15 | 15 | } |
16 | 16 |
|
17 | | -fn parse_docs(meta: &syn::Meta) -> Result<SpannedKey<Vec<syn::Attribute>>> { |
18 | | - crate::parsing::parse_docs_without_self_mentions(DOCS_CONTEXT, meta) |
| 17 | +impl SetterFnName { |
| 18 | + fn new( |
| 19 | + name: Option<SpannedKey<syn::Ident>>, |
| 20 | + prefix: Option<SpannedKey<syn::Ident>>, |
| 21 | + ) -> Result<Option<SpannedKey<Self>>> { |
| 22 | + match (name, prefix) { |
| 23 | + (Some(name), None) => Ok(Some(name.map_value(SetterFnName::Name))), |
| 24 | + (None, Some(prefix)) => Ok(Some(prefix.map_value(SetterFnName::Prefix))), |
| 25 | + (None, None) => Ok(None), |
| 26 | + (Some(name), Some(prefix)) => { |
| 27 | + bail!( |
| 28 | + &name.key, |
| 29 | + "`{}` is mutually exclusive with `{}`", |
| 30 | + name.key, |
| 31 | + prefix.key, |
| 32 | + ); |
| 33 | + } |
| 34 | + } |
| 35 | + } |
19 | 36 | } |
20 | 37 |
|
21 | | -#[derive(Debug, FromMeta)] |
| 38 | +#[derive(Debug)] |
22 | 39 | pub(crate) struct SettersConfig { |
23 | | - pub(crate) name: Option<SpannedKey<syn::Ident>>, |
| 40 | + pub(crate) name: Option<SpannedKey<SetterFnName>>, |
24 | 41 | pub(crate) vis: Option<SpannedKey<syn::Visibility>>, |
25 | | - |
26 | | - #[darling(rename = "doc", default, with = parse_docs, map = Some)] |
27 | 42 | pub(crate) docs: Option<SpannedKey<Vec<syn::Attribute>>>, |
28 | | - |
29 | | - #[darling(flatten)] |
30 | 43 | pub(crate) fns: SettersFnsConfig, |
31 | 44 | } |
32 | 45 |
|
| 46 | +impl FromMeta for SettersConfig { |
| 47 | + fn from_meta(meta: &syn::Meta) -> Result<Self> { |
| 48 | + #[derive(FromMeta)] |
| 49 | + struct Parsed { |
| 50 | + name: Option<SpannedKey<syn::Ident>>, |
| 51 | + prefix: Option<SpannedKey<syn::Ident>>, |
| 52 | + |
| 53 | + vis: Option<SpannedKey<syn::Visibility>>, |
| 54 | + |
| 55 | + #[darling(rename = "doc", default, map = Some, with = parse_docs)] |
| 56 | + docs: Option<SpannedKey<Vec<syn::Attribute>>>, |
| 57 | + |
| 58 | + #[darling(flatten)] |
| 59 | + fns: SettersFnsConfig, |
| 60 | + } |
| 61 | + |
| 62 | + let Parsed { |
| 63 | + name, |
| 64 | + prefix, |
| 65 | + vis, |
| 66 | + docs, |
| 67 | + fns, |
| 68 | + } = Parsed::from_meta(meta)?; |
| 69 | + |
| 70 | + Ok(SettersConfig { |
| 71 | + name: SetterFnName::new(name, prefix)?, |
| 72 | + vis, |
| 73 | + docs, |
| 74 | + fns, |
| 75 | + }) |
| 76 | + } |
| 77 | +} |
| 78 | + |
33 | 79 | #[derive(Debug, FromMeta)] |
34 | 80 | pub(crate) struct SettersFnsConfig { |
35 | 81 | /// Config for the setter that accepts the value of type T for a member of |
36 | 82 | /// type `Option<T>` or with `#[builder(default)]`. |
37 | 83 | /// |
38 | 84 | /// By default, it's named `{member}` without any prefix or suffix. |
39 | | - #[darling(default, with = parse_setter_fn, map = Some)] |
40 | | - pub(crate) some_fn: Option<SpannedKey<ItemSigConfig>>, |
| 85 | + pub(crate) some_fn: Option<SpannedKey<SetterFnSigConfig>>, |
41 | 86 |
|
42 | 87 | /// The setter that accepts the value of type `Option<T>` for a member of |
43 | 88 | /// type `Option<T>` or with `#[builder(default)]`. |
44 | 89 | /// |
45 | 90 | /// By default, it's named `maybe_{member}`. |
46 | | - #[darling(default, with = parse_setter_fn, map = Some)] |
47 | | - pub(crate) option_fn: Option<SpannedKey<ItemSigConfig>>, |
| 91 | + pub(crate) option_fn: Option<SpannedKey<SetterFnSigConfig>>, |
| 92 | +} |
| 93 | + |
| 94 | +#[derive(Debug, Default)] |
| 95 | +pub(crate) struct SetterFnSigConfig { |
| 96 | + pub(crate) name: Option<SpannedKey<SetterFnName>>, |
| 97 | + pub(crate) vis: Option<SpannedKey<syn::Visibility>>, |
| 98 | + pub(crate) docs: Option<SpannedKey<Vec<syn::Attribute>>>, |
| 99 | +} |
| 100 | + |
| 101 | +impl FromMeta for SetterFnSigConfig { |
| 102 | + fn from_meta(meta: &syn::Meta) -> Result<Self> { |
| 103 | + if let syn::Meta::NameValue(meta) = meta { |
| 104 | + let val = &meta.value; |
| 105 | + let name = syn::parse2(val.to_token_stream())?; |
| 106 | + |
| 107 | + return Ok(SetterFnSigConfig { |
| 108 | + name: Some(SpannedKey::new(&meta.path, SetterFnName::Name(name))?), |
| 109 | + vis: None, |
| 110 | + docs: None, |
| 111 | + }); |
| 112 | + } |
| 113 | + |
| 114 | + #[derive(Debug, FromMeta)] |
| 115 | + struct Full { |
| 116 | + name: Option<SpannedKey<syn::Ident>>, |
| 117 | + prefix: Option<SpannedKey<syn::Ident>>, |
| 118 | + |
| 119 | + vis: Option<SpannedKey<syn::Visibility>>, |
| 120 | + |
| 121 | + #[darling(rename = "doc", default, map = Some, with = parse_docs)] |
| 122 | + docs: Option<SpannedKey<Vec<syn::Attribute>>>, |
| 123 | + } |
| 124 | + |
| 125 | + let Full { |
| 126 | + name, |
| 127 | + prefix, |
| 128 | + vis, |
| 129 | + docs, |
| 130 | + } = crate::parsing::parse_non_empty_paren_meta_list_or_name_value(meta)?; |
| 131 | + |
| 132 | + let config = SetterFnSigConfig { |
| 133 | + name: SetterFnName::new(name, prefix)?, |
| 134 | + vis, |
| 135 | + docs, |
| 136 | + }; |
| 137 | + |
| 138 | + Ok(config) |
| 139 | + } |
48 | 140 | } |
0 commit comments