cynic_codegen/use_schema/
mod.rs1mod argument;
2mod directive;
3mod fields;
4mod input_object;
5mod interface;
6mod named_type;
7mod object;
8mod params;
9mod schema_roots;
10mod subtype_markers;
11
12pub use params::UseSchemaParams;
13
14use {
15 proc_macro2::TokenStream,
16 quote::{quote, ToTokens},
17};
18
19use crate::{
20 error::Errors,
21 schema::{
22 types::{DirectiveLocation, Type},
23 Schema, SchemaInput, Validated,
24 },
25};
26
27use self::{
28 directive::FieldDirectiveOutput, input_object::InputObjectOutput, interface::InterfaceOutput,
29 named_type::NamedType, object::ObjectOutput, subtype_markers::SubtypeMarkers,
30};
31
32pub fn use_schema(input: UseSchemaParams) -> Result<TokenStream, Errors> {
33 let input = SchemaInput::from_schema_path(input.schema_filename)
34 .map_err(|e| e.into_syn_error(proc_macro2::Span::call_site()))?;
35
36 let schema = Schema::new(input).validate()?;
37 use_schema_impl(&schema)
38}
39
40pub(crate) fn use_schema_impl(schema: &Schema<'_, Validated>) -> Result<TokenStream, Errors> {
41 use quote::TokenStreamExt;
42
43 let mut output = TokenStream::new();
44 let mut field_module = TokenStream::new();
45
46 let root_types = schema.root_types()?;
47 output.append_all(quote! {
48 #root_types
49 });
50
51 let mut subtype_markers = Vec::new();
52 let mut named_types = Vec::new();
53
54 for definition in schema.iter() {
55 named_types.extend(NamedType::from_def(&definition));
56
57 match definition {
58 Type::Scalar(def) if !def.builtin => {
59 let name = proc_macro2::Literal::string(def.name.as_ref());
60 let ident = def.marker_ident().to_rust_ident();
61 output.append_all(quote! {
62 pub struct #ident {}
63 impl cynic::schema::NamedType for #ident {
64 const NAME: &'static ::core::primitive::str = #name;
65 }
66 });
67 }
68 Type::Scalar(_) => {}
69 Type::Object(def) => {
70 subtype_markers.extend(SubtypeMarkers::from_object(&def));
71
72 let object = ObjectOutput::new(def);
73 object.to_tokens(&mut output);
74 object.append_fields(&mut field_module);
75 }
76 Type::Interface(def) => {
77 subtype_markers.push(SubtypeMarkers::from_interface(&def));
78
79 let iface = InterfaceOutput::new(def);
80 iface.to_tokens(&mut output);
81 iface.append_fields(&mut field_module);
82 }
83 Type::Union(def) => {
84 subtype_markers.extend(SubtypeMarkers::from_union(&def));
85
86 let ident = def.marker_ident().to_rust_ident();
87 output.append_all(quote! {
88 pub struct #ident {}
89 });
90 }
91 Type::Enum(def) => {
92 let ident = def.marker_ident().to_rust_ident();
93 output.append_all(quote! {
94 pub struct #ident {}
95 });
96 }
97 Type::InputObject(def) => {
98 let object = InputObjectOutput::new(def);
99 object.to_tokens(&mut output);
100 object.append_fields(&mut field_module);
101 }
102 }
103 }
104
105 for directive in schema.directives() {
106 if !directive.locations.contains(&DirectiveLocation::Field) {
107 continue;
109 }
110 FieldDirectiveOutput {
111 directive: &directive,
112 }
113 .to_tokens(&mut output);
114 }
115
116 output.append_all(quote! {
117 #(#subtype_markers)*
118 #(#named_types)*
119
120 #[allow(non_snake_case, non_camel_case_types)]
121 pub mod __fields {
122 #field_module
123 }
124
125 pub type Boolean = bool;
126 pub type String = std::string::String;
127 pub type Float = f64;
128 pub type Int = i32;
129 pub type ID = cynic::Id;
130
131 pub mod variable {
132 use cynic::variables::VariableType;
133
134 pub trait Variable {
137 const TYPE: VariableType;
138 }
139
140 impl<T> Variable for &T
141 where
142 T: ?::core::marker::Sized + Variable,
143 {
144 const TYPE: VariableType = T::TYPE;
145 }
146
147 impl<T> Variable for Option<T>
148 where
149 T: Variable
150 {
151 const TYPE: VariableType = VariableType::Nullable(&T::TYPE);
152 }
153
154 impl<T> Variable for [T]
155 where
156 T: Variable,
157 {
158 const TYPE: VariableType = VariableType::List(&T::TYPE);
159 }
160
161 impl<T> Variable for Vec<T>
162 where
163 T: Variable,
164 {
165 const TYPE: VariableType = VariableType::List(&T::TYPE);
166 }
167
168 impl<T> Variable for Box<T>
169 where
170 T: Variable,
171 {
172 const TYPE: VariableType = T::TYPE;
173 }
174
175 impl<T> Variable for std::rc::Rc<T>
176 where
177 T: Variable,
178 {
179 const TYPE: VariableType = T::TYPE;
180 }
181
182 impl<T> Variable for std::sync::Arc<T>
183 where
184 T: Variable,
185 {
186 const TYPE: VariableType = T::TYPE;
187 }
188
189 impl<T> Variable for std::borrow::Cow<'_, T>
190 where
191 T: ?::core::marker::Sized + Variable + ToOwned,
192 {
193 const TYPE: VariableType = T::TYPE;
194 }
195
196 impl Variable for bool {
197 const TYPE: VariableType = VariableType::Named("Boolean");
198 }
199
200 impl Variable for str {
201 const TYPE: VariableType = VariableType::Named("String");
202 }
203
204 impl Variable for String {
205 const TYPE: VariableType = <str as Variable>::TYPE;
206 }
207
208 impl Variable for f64 {
209 const TYPE: VariableType = VariableType::Named("Float");
210 }
211
212 impl Variable for i32 {
213 const TYPE: VariableType = VariableType::Named("Int");
214 }
215
216 impl Variable for cynic::Id {
217 const TYPE: VariableType = VariableType::Named("ID");
218 }
219 }
220 });
221
222 Ok(output)
223}