bon_macros/parsing/
item_sig.rs

1use super::SpannedKey;
2use crate::util::prelude::*;
3use darling::FromMeta;
4
5/// "Item signature" is a set of parameters that configures some aspects of
6/// an item like a function, struct, struct field, module, trait. All of them
7/// have configurable properties that are specified here.
8#[derive(Debug, Clone, Default)]
9pub(crate) struct ItemSigConfig {
10    pub(crate) name: Option<SpannedKey<syn::Ident>>,
11    pub(crate) vis: Option<SpannedKey<syn::Visibility>>,
12    pub(crate) docs: Option<SpannedKey<Vec<syn::Attribute>>>,
13}
14
15impl ItemSigConfig {
16    pub(crate) fn name(&self) -> Option<&syn::Ident> {
17        self.name.as_ref().map(|name| &name.value)
18    }
19
20    pub(crate) fn vis(&self) -> Option<&syn::Visibility> {
21        self.vis.as_ref().map(|vis| &vis.value)
22    }
23
24    pub(crate) fn docs(&self) -> Option<&[syn::Attribute]> {
25        self.docs.as_ref().map(|docs| docs.value.as_slice())
26    }
27}
28
29pub(crate) struct ItemSigConfigParsing<'a> {
30    pub(crate) meta: &'a syn::Meta,
31    pub(crate) reject_self_mentions: Option<&'static str>,
32}
33
34impl ItemSigConfigParsing<'_> {
35    pub(crate) fn parse(self) -> Result<ItemSigConfig> {
36        let meta = self.meta;
37
38        if let syn::Meta::NameValue(meta) = meta {
39            let val = &meta.value;
40            let name = syn::parse2(val.to_token_stream())?;
41
42            return Ok(ItemSigConfig {
43                name: Some(SpannedKey::new(&meta.path, name)?),
44                vis: None,
45                docs: None,
46            });
47        }
48
49        #[derive(Debug, FromMeta)]
50        struct Full {
51            name: Option<SpannedKey<syn::Ident>>,
52            vis: Option<SpannedKey<syn::Visibility>>,
53
54            #[darling(default, with = super::parse_docs, map = Some)]
55            doc: Option<SpannedKey<Vec<syn::Attribute>>>,
56        }
57
58        let full: Full = crate::parsing::parse_non_empty_paren_meta_list(meta)?;
59
60        if let Some(context) = self.reject_self_mentions {
61            if let Some(docs) = &full.doc {
62                crate::parsing::reject_self_mentions_in_docs(context, docs)?;
63            }
64        }
65
66        let config = ItemSigConfig {
67            name: full.name,
68            vis: full.vis,
69            docs: full.doc,
70        };
71
72        Ok(config)
73    }
74}