1use crate::ast;
5use crate::compat::graphql_parser_v0_4::helpers::directives_to_gp;
6use crate::compat::graphql_parser_v0_4::helpers::end_pos_from_span;
7use crate::compat::graphql_parser_v0_4::helpers::pos_from_span;
8use crate::compat::graphql_parser_v0_4::helpers::type_annotation_to_gp;
9use crate::compat::graphql_parser_v0_4::helpers::value_to_gp;
10use crate::GraphQLParseError;
11use crate::GraphQLParseErrorKind;
12use crate::ParseResult;
13use crate::SourceSpan;
14
15fn selection_set_to_gp(
16 sel_set: &ast::SelectionSet<'_>,
17 errors: &mut Vec<GraphQLParseError>,
18 source_map: &crate::SourceMap<'_>,
19) -> graphql_parser::query::SelectionSet<'static, String>
20{
21 graphql_parser::query::SelectionSet {
22 span: (
23 pos_from_span(sel_set.span, source_map),
24 end_pos_from_span(
25 sel_set.span, source_map,
26 ),
27 ),
28 items: sel_set
29 .selections
30 .iter()
31 .map(|s| {
32 selection_to_gp(s, errors, source_map)
33 })
34 .collect(),
35 }
36}
37
38fn selection_to_gp(
39 sel: &ast::Selection<'_>,
40 errors: &mut Vec<GraphQLParseError>,
41 source_map: &crate::SourceMap<'_>,
42) -> graphql_parser::query::Selection<'static, String> {
43 use graphql_parser::query::Selection as GpSel;
44 match sel {
45 ast::Selection::Field(field) => {
46 GpSel::Field(
47 query_field_to_gp(
48 field, errors, source_map,
49 ),
50 )
51 },
52 ast::Selection::FragmentSpread(frag_spread) => {
53 GpSel::FragmentSpread(
54 fragment_spread_to_gp(
55 frag_spread, source_map,
56 ),
57 )
58 },
59 ast::Selection::InlineFragment(inline_frag) => {
60 GpSel::InlineFragment(
61 inline_fragment_to_gp(
62 inline_frag,
63 errors,
64 source_map,
65 ),
66 )
67 },
68 }
69}
70
71fn query_field_to_gp(
72 field: &ast::FieldSelection<'_>,
73 errors: &mut Vec<GraphQLParseError>,
74 source_map: &crate::SourceMap<'_>,
75) -> graphql_parser::query::Field<'static, String> {
76 graphql_parser::query::Field {
77 position: pos_from_span(
78 field.span, source_map,
79 ),
80 alias: field
81 .alias
82 .as_ref()
83 .map(|a| a.value.to_string()),
84 name: field.name.value.to_string(),
85 arguments: field
86 .arguments
87 .iter()
88 .map(|arg| {
89 (
90 arg.name.value.to_string(),
91 value_to_gp(&arg.value),
92 )
93 })
94 .collect(),
95 directives: directives_to_gp(
96 &field.directives, source_map,
97 ),
98 selection_set: match &field.selection_set {
99 Some(sel_set) => {
100 selection_set_to_gp(
101 sel_set, errors, source_map,
102 )
103 },
104 None => graphql_parser::query::SelectionSet {
105 span: (
106 pos_from_span(
107 field.span, source_map,
108 ),
109 pos_from_span(
110 field.span, source_map,
111 ),
112 ),
113 items: vec![],
114 },
115 },
116 }
117}
118
119fn fragment_spread_to_gp(
120 frag_spread: &ast::FragmentSpread<'_>,
121 source_map: &crate::SourceMap<'_>,
122) -> graphql_parser::query::FragmentSpread<
123 'static,
124 String,
125> {
126 graphql_parser::query::FragmentSpread {
127 position: pos_from_span(
131 frag_spread.name.span, source_map,
132 ),
133 fragment_name: frag_spread
134 .name
135 .value
136 .to_string(),
137 directives: directives_to_gp(
138 &frag_spread.directives, source_map,
139 ),
140 }
141}
142
143fn inline_fragment_to_gp(
144 inline_frag: &ast::InlineFragment<'_>,
145 errors: &mut Vec<GraphQLParseError>,
146 source_map: &crate::SourceMap<'_>,
147) -> graphql_parser::query::InlineFragment<
148 'static,
149 String,
150> {
151 graphql_parser::query::InlineFragment {
152 position: if let Some(tc) =
157 &inline_frag.type_condition
158 {
159 pos_from_span(tc.span, source_map)
160 } else if let Some(dir) =
161 inline_frag.directives.first()
162 {
163 pos_from_span(dir.span, source_map)
164 } else {
165 pos_from_span(
166 inline_frag.selection_set.span,
167 source_map,
168 )
169 },
170 type_condition: inline_frag
171 .type_condition
172 .as_ref()
173 .map(type_condition_to_gp),
174 directives: directives_to_gp(
175 &inline_frag.directives, source_map,
176 ),
177 selection_set: selection_set_to_gp(
178 &inline_frag.selection_set,
179 errors,
180 source_map,
181 ),
182 }
183}
184
185fn type_condition_to_gp(
186 type_cond: &ast::TypeCondition<'_>,
187) -> graphql_parser::query::TypeCondition<
188 'static,
189 String,
190> {
191 graphql_parser::query::TypeCondition::On(
192 type_cond.named_type.value.to_string(),
193 )
194}
195
196fn variable_def_to_gp(
197 var_def: &ast::VariableDefinition<'_>,
198 errors: &mut Vec<GraphQLParseError>,
199 source_map: &crate::SourceMap<'_>,
200) -> graphql_parser::query::VariableDefinition<
201 'static,
202 String,
203> {
204 if !var_def.directives.is_empty() {
205 errors.push(GraphQLParseError::new(
206 "Variable directives cannot be \
207 represented in graphql_parser v0.4 AST",
208 GraphQLParseErrorKind::UnsupportedFeature {
209 feature: "variable directives"
210 .to_string(),
211 },
212 source_map.resolve_span(var_def.span)
213 .unwrap_or_else(SourceSpan::zero),
214 ));
215 }
216 graphql_parser::query::VariableDefinition {
217 position: pos_from_span(
218 var_def.span, source_map,
219 ),
220 name: var_def.variable.value.to_string(),
221 var_type: type_annotation_to_gp(
222 &var_def.var_type,
223 ),
224 default_value: var_def
225 .default_value
226 .as_ref()
227 .map(value_to_gp),
228 }
229}
230
231fn fragment_def_to_gp(
232 frag_def: &ast::FragmentDefinition<'_>,
233 errors: &mut Vec<GraphQLParseError>,
234 source_map: &crate::SourceMap<'_>,
235) -> graphql_parser::query::FragmentDefinition<
236 'static,
237 String,
238> {
239 graphql_parser::query::FragmentDefinition {
240 position: pos_from_span(
241 frag_def.span, source_map,
242 ),
243 name: frag_def.name.value.to_string(),
244 type_condition: type_condition_to_gp(
245 &frag_def.type_condition,
246 ),
247 directives: directives_to_gp(
248 &frag_def.directives, source_map,
249 ),
250 selection_set: selection_set_to_gp(
251 &frag_def.selection_set,
252 errors,
253 source_map,
254 ),
255 }
256}
257
258fn operation_def_to_gp(
259 op_def: &ast::OperationDefinition<'_>,
260 errors: &mut Vec<GraphQLParseError>,
261 source_map: &crate::SourceMap<'_>,
262) -> graphql_parser::query::OperationDefinition<
263 'static,
264 String,
265> {
266 use graphql_parser::query::OperationDefinition
267 as GpOp;
268
269 let var_defs: Vec<_> = op_def
270 .variable_definitions
271 .iter()
272 .map(|var_def| {
273 variable_def_to_gp(
274 var_def, errors, source_map,
275 )
276 })
277 .collect();
278 let sel_set = selection_set_to_gp(
279 &op_def.selection_set,
280 errors,
281 source_map,
282 );
283 let dirs = directives_to_gp(
284 &op_def.directives, source_map,
285 );
286 let pos = pos_from_span(
287 op_def.span, source_map,
288 );
289 let name = op_def
290 .name
291 .as_ref()
292 .map(|n| n.value.to_string());
293
294 if op_def.shorthand {
295 return GpOp::SelectionSet(sel_set);
296 }
297
298 match op_def.operation_kind {
299 ast::OperationKind::Query => {
300 GpOp::Query(graphql_parser::query::Query {
301 position: pos,
302 name,
303 variable_definitions: var_defs,
304 directives: dirs,
305 selection_set: sel_set,
306 })
307 },
308 ast::OperationKind::Mutation => {
309 GpOp::Mutation(
310 graphql_parser::query::Mutation {
311 position: pos,
312 name,
313 variable_definitions: var_defs,
314 directives: dirs,
315 selection_set: sel_set,
316 },
317 )
318 },
319 ast::OperationKind::Subscription => {
320 GpOp::Subscription(
321 graphql_parser::query::Subscription {
322 position: pos,
323 name,
324 variable_definitions: var_defs,
325 directives: dirs,
326 selection_set: sel_set,
327 },
328 )
329 },
330 }
331}
332
333pub fn to_graphql_parser_query_ast<'a>(
345 doc: &ast::Document<'_>,
346 source_map: &crate::SourceMap<'a>,
347) -> ParseResult<
348 'a,
349 graphql_parser::query::Document<'static, String>,
350> {
351 let mut errors: Vec<GraphQLParseError> = Vec::new();
352 let mut definitions = Vec::new();
353
354 for def in &doc.definitions {
355 match def {
356 ast::Definition::FragmentDefinition(
357 frag_def,
358 ) => {
359 definitions.push(
360 graphql_parser::query::Definition
361 ::Fragment(
362 fragment_def_to_gp(
363 frag_def,
364 &mut errors,
365 source_map,
366 ),
367 ),
368 );
369 },
370 ast::Definition::OperationDefinition(
371 op_def,
372 ) => {
373 definitions.push(
374 graphql_parser::query::Definition
375 ::Operation(
376 operation_def_to_gp(
377 op_def,
378 &mut errors,
379 source_map,
380 ),
381 ),
382 );
383 },
384 ast::Definition::DirectiveDefinition(_)
387 | ast::Definition::SchemaDefinition(_)
388 | ast::Definition::SchemaExtension(_)
389 | ast::Definition::TypeDefinition(_)
390 | ast::Definition::TypeExtension(_) => {},
391 }
392 }
393
394 let gp_doc =
395 graphql_parser::query::Document { definitions };
396
397 if errors.is_empty() {
398 ParseResult::new_ok(gp_doc, source_map.clone())
399 } else {
400 ParseResult::new_recovered(gp_doc, errors, source_map.clone())
401 }
402}