Skip to main content

cynic_codegen/schema_for_derives/
utils.rs

1use darling::ast::NestedMeta;
2use syn::{Attribute, Item, Meta};
3
4#[derive(Debug, PartialEq, Eq)]
5pub enum Derive {
6    QueryFragment,
7    QueryVariables,
8    InlineFragments,
9    Enum,
10    Scalar,
11    InputObject,
12}
13
14pub fn find_derives(item: &Item) -> Vec<Derive> {
15    match item {
16        Item::Struct(s) => derive_from_attributes(&s.attrs),
17        Item::Enum(e) => derive_from_attributes(&e.attrs),
18        _ => vec![],
19    }
20}
21
22fn derive_from_attributes(attrs: &[Attribute]) -> Vec<Derive> {
23    let attr = attrs.iter().find(|attr| attr.path().is_ident("derive"));
24
25    if attr.is_none() {
26        return vec![];
27    }
28    let attr = attr.unwrap();
29
30    let meta_list = match &attr.meta {
31        Meta::List(list) => list,
32        _ => {
33            return vec![];
34        }
35    };
36
37    NestedMeta::parse_meta_list(meta_list.tokens.clone())
38        .unwrap_or_default()
39        .iter()
40        .filter_map(derive_for_nested_meta)
41        .collect()
42}
43
44fn derive_for_nested_meta(nested: &NestedMeta) -> Option<Derive> {
45    if let NestedMeta::Meta(Meta::Path(path)) = nested {
46        if let Some(last) = path.segments.last() {
47            match last.ident.to_string().as_ref() {
48                "QueryFragment" => return Some(Derive::QueryFragment),
49                "QueryVariables" => return Some(Derive::QueryVariables),
50                "InlineFragments" => return Some(Derive::InlineFragments),
51                "Enum" => return Some(Derive::Enum),
52                "Scalar" => return Some(Derive::Scalar),
53                "InputObject" => return Some(Derive::InputObject),
54                _ => (),
55            }
56        }
57    }
58
59    None
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65    use quote::quote;
66
67    #[test]
68    fn test_find_derives_with_fragment() {
69        let item: syn::Item = syn::parse2(quote! {
70            #[derive(Debug, cynic::QueryFragment)]
71            struct Something {}
72        })
73        .unwrap();
74
75        assert_eq!(find_derives(&item), vec![Derive::QueryFragment]);
76    }
77
78    #[test]
79    fn test_find_derives_when_no_cynic_derive() {
80        let item: syn::Item = syn::parse2(quote! {
81            #[derive(Debug)]
82            struct Something {}
83        })
84        .unwrap();
85
86        assert_eq!(find_derives(&item), vec![]);
87    }
88
89    #[test]
90    fn test_find_derives_when_no_derive() {
91        let item: syn::Item = syn::parse2(quote! {
92            struct Something {}
93        })
94        .unwrap();
95
96        assert_eq!(find_derives(&item), vec![]);
97    }
98
99    #[test]
100    fn test_find_derives_on_enum() {
101        let item: syn::Item = syn::parse2(quote! {
102            #[derive(cynic::InlineFragments)]
103            enum Something {}
104        })
105        .unwrap();
106
107        assert_eq!(find_derives(&item), vec![Derive::InlineFragments]);
108    }
109}