codama_attributes/
derive_attribute.rs

1use codama_syn_helpers::extensions::*;
2
3#[derive(Debug, PartialEq)]
4pub struct DeriveAttribute<'a> {
5    pub ast: &'a syn::Attribute,
6    pub derives: Vec<syn::Path>,
7}
8
9impl<'a> DeriveAttribute<'a> {
10    pub fn parse(ast: &'a syn::Attribute) -> syn::Result<Self> {
11        // Check if the attribute is feature-gated.
12        let unfeatured = ast.unfeatured();
13        let attr = unfeatured.as_ref().unwrap_or(ast);
14
15        // Check if the attribute is a #[derive(...)] attribute.
16        let list = attr.meta.require_list()?;
17        if !list.path.is_strict("derive") {
18            return Err(list.path.error("expected #[derive(...)]"));
19        };
20
21        // Parse the list of derives.
22        let derives = list.parse_comma_args::<syn::Path>()?;
23        Ok(Self { ast, derives })
24    }
25}
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30    use syn::parse_quote;
31
32    #[test]
33    fn test_derive_attribute() {
34        let ast = parse_quote! { #[derive(Debug, PartialEq)] };
35        let attribute = DeriveAttribute::parse(&ast).unwrap();
36
37        assert_eq!(attribute.ast, &ast);
38        assert_eq!(
39            attribute.derives,
40            [(parse_quote! { Debug }), (parse_quote! { PartialEq }),]
41        );
42    }
43
44    #[test]
45    fn test_feature_gated_derive_attribute() {
46        let ast = parse_quote! { #[cfg_attr(feature = "some_feature", derive(Debug, PartialEq))] };
47        let attribute = DeriveAttribute::parse(&ast).unwrap();
48
49        assert_eq!(attribute.ast, &ast);
50        assert_eq!(
51            attribute.derives,
52            [(parse_quote! { Debug }), (parse_quote! { PartialEq })]
53        );
54    }
55}