cynic_codegen/input_object_derive/
input.rs

1use crate::schema::SchemaInput;
2
3use {darling::util::SpannedValue, syn::spanned::Spanned};
4
5use {
6    crate::idents::{RenamableFieldIdent, RenameAll},
7    proc_macro2::Span,
8};
9
10#[derive(darling::FromDeriveInput)]
11#[darling(attributes(cynic), supports(struct_named))]
12pub struct InputObjectDeriveInput {
13    pub(super) ident: proc_macro2::Ident,
14    pub(super) generics: syn::Generics,
15    pub(super) data: darling::ast::Data<(), InputObjectDeriveField>,
16
17    #[darling(default)]
18    schema: Option<SpannedValue<String>>,
19    #[darling(default)]
20    schema_path: Option<SpannedValue<String>>,
21
22    #[darling(default, rename = "schema_module")]
23    schema_module_: Option<syn::Path>,
24
25    #[darling(default)]
26    pub graphql_type: Option<SpannedValue<String>>,
27
28    #[darling(default)]
29    pub require_all_fields: bool,
30
31    #[darling(default)]
32    pub(super) rename_all: Option<RenameAll>,
33}
34
35#[derive(Debug, darling::FromField)]
36#[darling(attributes(cynic))]
37pub struct InputObjectDeriveField {
38    pub(super) ident: Option<proc_macro2::Ident>,
39    pub(super) ty: syn::Type,
40
41    #[darling(default)]
42    pub(super) skip_serializing_if: Option<SpannedValue<syn::Path>>,
43
44    #[darling(default)]
45    pub(super) rename: Option<SpannedValue<String>>,
46}
47
48impl InputObjectDeriveInput {
49    pub fn schema_module(&self) -> syn::Path {
50        if let Some(schema_module) = &self.schema_module_ {
51            return schema_module.clone();
52        }
53        syn::parse2(quote::quote! { schema }).unwrap()
54    }
55
56    pub fn graphql_type_name(&self) -> String {
57        self.graphql_type
58            .as_ref()
59            .map(|sp| sp.to_string())
60            .unwrap_or_else(|| self.ident.to_string())
61    }
62
63    pub fn graphql_type_span(&self) -> Span {
64        self.graphql_type
65            .as_ref()
66            .map(|val| val.span())
67            .unwrap_or_else(|| self.ident.span())
68    }
69
70    pub fn schema_input(&self) -> Result<SchemaInput, syn::Error> {
71        match (&self.schema, &self.schema_path) {
72            (None, None) => SchemaInput::default().map_err(|e| e.into_syn_error(Span::call_site())),
73            (None, Some(path)) => SchemaInput::from_schema_path(path.as_ref())
74                .map_err(|e| e.into_syn_error(path.span())),
75            (Some(name), None) => SchemaInput::from_schema_name(name.as_ref())
76                .map_err(|e| e.into_syn_error(name.span())),
77            (Some(_), Some(path)) => Err(syn::Error::new(
78                path.span(),
79                "Only one of schema_path & schema can be provided",
80            )),
81        }
82    }
83}
84
85impl InputObjectDeriveField {
86    pub fn graphql_ident(&self, rename_rule: RenameAll) -> RenamableFieldIdent {
87        let mut ident = RenamableFieldIdent::from(
88            self.ident
89                .clone()
90                .expect("InputObject only supports named structs"),
91        );
92        match &self.rename {
93            Some(rename) => {
94                let span = rename.span();
95                let rename = (**rename).clone();
96                ident.set_rename(rename, span)
97            }
98            None => {
99                ident.rename_with(rename_rule, self.ident.span());
100            }
101        }
102        ident
103    }
104}