codama_attributes/
codama_attribute.rs

1use crate::{utils::SetOnce, AccountDirective, AttributeContext, CodamaDirective};
2use codama_syn_helpers::extensions::*;
3
4#[derive(Debug, PartialEq)]
5pub struct CodamaAttribute<'a> {
6    pub ast: &'a syn::Attribute,
7    pub directive: CodamaDirective,
8}
9
10impl<'a> CodamaAttribute<'a> {
11    pub fn parse(ast: &'a syn::Attribute, ctx: &AttributeContext) -> syn::Result<Self> {
12        // Check if the attribute is feature-gated.
13        let unfeatured = ast.unfeatured();
14        let attr = unfeatured.as_ref().unwrap_or(ast);
15
16        // Check if the attribute is a #[codama(...)] attribute.
17        let list = attr.meta.require_list()?;
18        if !list.path.is_strict("codama") {
19            return Err(list.path.error("expected #[codama(...)]"));
20        };
21
22        let mut directive = SetOnce::<CodamaDirective>::new("codama");
23        list.each(|ref meta| directive.set(CodamaDirective::parse(meta, ctx)?, meta))?;
24        Ok(Self {
25            ast,
26            directive: directive.take(attr)?,
27        })
28    }
29
30    pub fn account(&self) -> Option<&AccountDirective> {
31        match &self.directive {
32            CodamaDirective::Account(a) => Some(a),
33            _ => None,
34        }
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41    use syn::parse_quote;
42
43    #[test]
44    fn test_codama_attribute() {
45        let ast = parse_quote! { #[codama(type = boolean)] };
46        let file = syn::File::empty();
47        let ctx = AttributeContext::File(&file);
48        let attribute = CodamaAttribute::parse(&ast, &ctx).unwrap();
49
50        assert_eq!(attribute.ast, &ast);
51        assert!(matches!(attribute.directive, CodamaDirective::Type(_)));
52    }
53
54    #[test]
55    fn test_feature_gated_codama_attribute() {
56        let ast = parse_quote! { #[cfg_attr(feature = "some_feature", codama(type = boolean))] };
57        let file = syn::File::empty();
58        let ctx = AttributeContext::File(&file);
59        let attribute = CodamaAttribute::parse(&ast, &ctx).unwrap();
60
61        assert_eq!(attribute.ast, &ast);
62        assert!(matches!(attribute.directive, CodamaDirective::Type(_)));
63    }
64}