graphql_query/ast/
parser.rs

1use super::ast::*;
2use super::ast_kind::ASTKind;
3use super::lexer::{Extras, Token};
4use crate::error::{get_location, print_span, Error, ErrorType, Result};
5use bumpalo::collections::Vec;
6use logos::{Lexer, Logos, Span};
7
8type ParseResult<T> = std::result::Result<T, ASTKind>;
9
10pub(crate) mod private {
11    use super::{ASTContext, Extras, Lexer, Logos, ParseResult, Span, Token};
12
13    /// Private Parser context state that's kept to keep track of the current parser's progress and
14    /// state. This contains the AST context's arena and a [Lexer].
15    pub struct ParserContext<'a> {
16        pub(crate) arena: &'a bumpalo::Bump,
17        pub(crate) peek: Option<Token<'a>>,
18        pub(crate) iter: Lexer<'a, Token<'a>>,
19        pub(crate) in_var_def: bool,
20    }
21
22    impl<'a> ParserContext<'a> {
23        /// Create a new Parser context for a given AST context and initialize it with an input source
24        /// string to parse from.
25        pub(crate) fn new(ctx: &'a ASTContext, source: &'a str) -> Self {
26            let extras = Extras { arena: &ctx.arena };
27            ParserContext {
28                arena: &ctx.arena,
29                peek: None,
30                iter: Token::lexer_with_extras(source, extras),
31                in_var_def: false,
32            }
33        }
34
35        #[inline]
36        pub(crate) fn next(&mut self) -> Token<'a> {
37            match self.peek.take() {
38                Some(token) => token,
39                None => self.iter.next().unwrap_or(Token::End),
40            }
41        }
42
43        #[inline]
44        pub(crate) fn peek(&mut self) -> &Token<'a> {
45            let iter = &mut self.iter;
46            self.peek
47                .get_or_insert_with(|| iter.next().unwrap_or(Token::End))
48        }
49
50        #[inline]
51        pub(crate) fn source(&self) -> &str {
52            self.iter.source()
53        }
54
55        #[inline]
56        pub(crate) fn span(&self) -> Span {
57            self.iter.span()
58        }
59    }
60
61    /// (Private) Trait for parsing AST Nodes from a Parser Context.
62    /// The [`super::ParseNode`] trait implements the public `parse` method instead.
63    pub trait ParseNode<'a>: Sized {
64        fn new_with_ctx(ctx: &mut ParserContext<'a>) -> ParseResult<Self>;
65    }
66}
67
68/// Trait for parsing AST Nodes from source texts using recursive descent and a lexer.
69///
70/// This trait is implemented by all AST Nodes and can hence be used to granularly parse GraphQL language.
71/// However, mostly this will be used via `Document::parse`.
72pub trait ParseNode<'a>: private::ParseNode<'a> {
73    /// Parse an input source text into the implementor's AST Node structure and allocate the
74    /// resulting AST into the current AST Context's arena.
75    fn parse<T: ToString>(ctx: &'a ASTContext, source: T) -> Result<&'a Self> {
76        let source = ctx.alloc_string(source.to_string());
77        let mut parser_ctx = private::ParserContext::new(ctx, source);
78        match Self::new_with_ctx(&mut parser_ctx) {
79            Ok(value) => Ok(ctx.alloc(value)),
80            Err(error) => {
81                let span = print_span(parser_ctx.source(), parser_ctx.span());
82                let location = get_location(parser_ctx.source(), parser_ctx.span());
83                let message = format!("Invalid {}", error);
84                Err(Error::new_with_context(
85                    message,
86                    Some(location),
87                    span,
88                    Some(ErrorType::Syntax),
89                ))
90            }
91        }
92    }
93}
94
95impl<'a, T: private::ParseNode<'a>> ParseNode<'a> for T {}
96
97impl<'a> private::ParseNode<'a> for BooleanValue {
98    #[inline]
99    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<BooleanValue> {
100        match ctx.next() {
101            Token::Name("true") => Ok(BooleanValue { value: true }),
102            Token::Name("false") => Ok(BooleanValue { value: false }),
103            _ => Err(ASTKind::Boolean),
104        }
105    }
106}
107
108impl<'a> private::ParseNode<'a> for EnumValue<'a> {
109    #[inline]
110    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<EnumValue<'a>> {
111        match ctx.next() {
112            Token::Name("true" | "false" | "null") => Err(ASTKind::Enum),
113            Token::Name(value) => Ok(EnumValue { value }),
114            _ => Err(ASTKind::Enum),
115        }
116    }
117}
118
119impl<'a> private::ParseNode<'a> for FloatValue<'a> {
120    #[inline]
121    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<FloatValue<'a>> {
122        if let Token::Float(value) = ctx.next() {
123            Ok(FloatValue { value })
124        } else {
125            Err(ASTKind::Float)
126        }
127    }
128}
129
130impl<'a> private::ParseNode<'a> for IntValue<'a> {
131    #[inline]
132    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<IntValue<'a>> {
133        if let Token::Integer(value) = ctx.next() {
134            Ok(IntValue { value })
135        } else {
136            Err(ASTKind::Int)
137        }
138    }
139}
140
141impl<'a> private::ParseNode<'a> for StringValue<'a> {
142    #[inline]
143    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<StringValue<'a>> {
144        if let Token::String(value) = ctx.next() {
145            Ok(StringValue { value })
146        } else {
147            Err(ASTKind::String)
148        }
149    }
150}
151
152impl<'a> private::ParseNode<'a> for Variable<'a> {
153    #[inline]
154    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<Variable<'a>> {
155        if let Token::VariableName(name) = ctx.next() {
156            Ok(Variable { name })
157        } else {
158            Err(ASTKind::Variable)
159        }
160    }
161}
162
163impl<'a> private::ParseNode<'a> for Value<'a> {
164    #[inline]
165    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<Value<'a>> {
166        let in_var_def = ctx.in_var_def;
167        match ctx.peek() {
168            Token::Name("null") => {
169                ctx.next();
170                Ok(Value::Null)
171            }
172            Token::VariableName(_) if in_var_def => Err(ASTKind::VariableDefinition),
173            Token::VariableName(_) => Variable::new_with_ctx(ctx).map(Value::Variable),
174            Token::Name("true" | "false") => BooleanValue::new_with_ctx(ctx).map(Value::Boolean),
175            Token::Name(_) => EnumValue::new_with_ctx(ctx).map(Value::Enum),
176            Token::Float(_) => FloatValue::new_with_ctx(ctx).map(Value::Float),
177            Token::Integer(_) => IntValue::new_with_ctx(ctx).map(Value::Int),
178            Token::String(_) => StringValue::new_with_ctx(ctx).map(Value::String),
179            Token::BracketOpen => ListValue::new_with_ctx(ctx).map(Value::List),
180            Token::BraceOpen => ObjectValue::new_with_ctx(ctx).map(Value::Object),
181            _ => Err(ASTKind::Value),
182        }
183    }
184}
185
186impl<'a> private::ParseNode<'a> for ObjectField<'a> {
187    #[inline]
188    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<ObjectField<'a>> {
189        if let Token::Name(name) = ctx.next() {
190            if let Token::Colon = ctx.next() {
191                let value = Value::new_with_ctx(ctx)?;
192                return Ok(ObjectField { name, value });
193            }
194        }
195        Err(ASTKind::ObjectField)
196    }
197}
198
199impl<'a> private::ParseNode<'a> for ObjectValue<'a> {
200    #[inline]
201    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<ObjectValue<'a>> {
202        if let Token::BraceOpen = ctx.next() {
203            let children = if let Token::BraceClose = ctx.peek() {
204                ctx.next();
205                Vec::new_in(ctx.arena)
206            } else {
207                let mut builder = Vec::new_in(ctx.arena);
208                loop {
209                    builder.push(ObjectField::new_with_ctx(ctx)?);
210                    if let Token::BraceClose = ctx.peek() {
211                        ctx.next();
212                        break;
213                    }
214                }
215                builder
216            };
217            Ok(ObjectValue { children })
218        } else {
219            Err(ASTKind::Object)
220        }
221    }
222}
223
224impl<'a> private::ParseNode<'a> for ListValue<'a> {
225    #[inline]
226    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<ListValue<'a>> {
227        if let Token::BracketOpen = ctx.next() {
228            let children = if let Token::BracketClose = ctx.peek() {
229                ctx.next();
230                Vec::new_in(ctx.arena)
231            } else {
232                let mut builder = Vec::new_in(ctx.arena);
233                loop {
234                    builder.push(Value::new_with_ctx(ctx)?);
235                    if let Token::BracketClose = ctx.peek() {
236                        ctx.next();
237                        break;
238                    }
239                }
240                builder
241            };
242            Ok(ListValue { children })
243        } else {
244            Err(ASTKind::List)
245        }
246    }
247}
248
249impl<'a> private::ParseNode<'a> for Argument<'a> {
250    #[inline]
251    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<Argument<'a>> {
252        if let Token::Name(name) = ctx.next() {
253            if let Token::Colon = ctx.next() {
254                let value = Value::new_with_ctx(ctx)?;
255                return Ok(Argument { name, value });
256            }
257        }
258        Err(ASTKind::Argument)
259    }
260}
261
262impl<'a> private::ParseNode<'a> for Arguments<'a> {
263    #[inline]
264    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<Arguments<'a>> {
265        let children = if let Token::ParenOpen = ctx.peek() {
266            ctx.next();
267            if let Token::ParenClose = ctx.peek() {
268                ctx.next();
269                Vec::new_in(ctx.arena)
270            } else {
271                let mut builder = Vec::new_in(ctx.arena);
272                loop {
273                    builder.push(Argument::new_with_ctx(ctx)?);
274                    if let Token::ParenClose = ctx.peek() {
275                        ctx.next();
276                        break;
277                    }
278                }
279                builder
280            }
281        } else {
282            Vec::new_in(ctx.arena)
283        };
284        Ok(Arguments { children })
285    }
286}
287
288impl<'a> private::ParseNode<'a> for Directive<'a> {
289    #[inline]
290    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<Directive<'a>> {
291        if let Token::DirectiveName(name) = ctx.next() {
292            let arguments = Arguments::new_with_ctx(ctx)?;
293            Ok(Directive { name, arguments })
294        } else {
295            Err(ASTKind::Directive)
296        }
297    }
298}
299
300impl<'a> private::ParseNode<'a> for Directives<'a> {
301    #[inline]
302    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<Directives<'a>> {
303        let mut builder = Vec::new_in(ctx.arena);
304        while let Token::DirectiveName(_) = ctx.peek() {
305            builder.push(Directive::new_with_ctx(ctx)?);
306        }
307        Ok(Directives { children: builder })
308    }
309}
310
311impl<'a> private::ParseNode<'a> for Field<'a> {
312    #[inline]
313    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<Field<'a>> {
314        if let Token::Name(name_or_alias) = ctx.next() {
315            let (alias, name) = if let Token::Colon = ctx.peek() {
316                ctx.next();
317                if let Token::Name(name) = ctx.next() {
318                    (Some(name_or_alias), name)
319                } else {
320                    return Err(ASTKind::Field);
321                }
322            } else {
323                (None, name_or_alias)
324            };
325
326            let arguments = Arguments::new_with_ctx(ctx)?;
327            let directives = Directives::new_with_ctx(ctx)?;
328            let selection_set = SelectionSet::new_with_ctx(ctx)?;
329
330            Ok(Field {
331                alias,
332                name,
333                arguments,
334                directives,
335                selection_set,
336            })
337        } else {
338            Err(ASTKind::Field)
339        }
340    }
341}
342
343impl<'a> private::ParseNode<'a> for FragmentSpread<'a> {
344    #[inline]
345    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<FragmentSpread<'a>> {
346        if let Token::Ellipsis = ctx.peek() {
347            ctx.next();
348        };
349        match ctx.peek() {
350            Token::Name("on") => Err(ASTKind::FragmentSpread),
351            Token::Name(_) => {
352                let name = NamedType::new_with_ctx(ctx)?;
353                let directives = Directives::new_with_ctx(ctx)?;
354                Ok(FragmentSpread { name, directives })
355            }
356            _ => Err(ASTKind::FragmentSpread),
357        }
358    }
359}
360
361impl<'a> private::ParseNode<'a> for NamedType<'a> {
362    #[inline]
363    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<NamedType<'a>> {
364        if let Token::Name(name) = ctx.next() {
365            Ok(NamedType { name })
366        } else {
367            Err(ASTKind::NamedType)
368        }
369    }
370}
371
372impl<'a> private::ParseNode<'a> for InlineFragment<'a> {
373    #[inline]
374    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<InlineFragment<'a>> {
375        if let Token::Ellipsis = ctx.peek() {
376            ctx.next();
377        };
378        let type_condition = if let Token::Name("on") = ctx.peek() {
379            ctx.next();
380            Some(NamedType::new_with_ctx(ctx)?)
381        } else {
382            None
383        };
384        let directives = Directives::new_with_ctx(ctx)?;
385        if let Token::BraceOpen = ctx.peek() {
386            let selection_set = SelectionSet::new_with_ctx(ctx)?;
387            Ok(InlineFragment {
388                type_condition,
389                directives,
390                selection_set,
391            })
392        } else {
393            Err(ASTKind::InlineFragment)
394        }
395    }
396}
397
398impl<'a> private::ParseNode<'a> for Selection<'a> {
399    #[inline]
400    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<Selection<'a>> {
401        match ctx.peek() {
402            Token::Name(_) => Field::new_with_ctx(ctx).map(Selection::Field),
403            Token::Ellipsis => {
404                ctx.next();
405                match ctx.peek() {
406                    Token::DirectiveName(_) | Token::BraceOpen | Token::Name("on") => {
407                        InlineFragment::new_with_ctx(ctx).map(Selection::InlineFragment)
408                    }
409                    Token::Name(_) => {
410                        FragmentSpread::new_with_ctx(ctx).map(Selection::FragmentSpread)
411                    }
412                    _ => Err(ASTKind::Selection),
413                }
414            }
415            _ => Err(ASTKind::Selection),
416        }
417    }
418}
419
420impl<'a> private::ParseNode<'a> for SelectionSet<'a> {
421    #[inline]
422    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<SelectionSet<'a>> {
423        let selections = if let Token::BraceOpen = ctx.peek() {
424            ctx.next();
425            let mut builder = Vec::new_in(ctx.arena);
426            loop {
427                builder.push(Selection::new_with_ctx(ctx)?);
428                if let Token::BraceClose = ctx.peek() {
429                    ctx.next();
430                    break;
431                }
432            }
433            builder
434        } else {
435            Vec::new_in(ctx.arena)
436        };
437        Ok(SelectionSet { selections })
438    }
439}
440
441impl<'a> private::ParseNode<'a> for Type<'a> {
442    #[inline]
443    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<Type<'a>> {
444        let token = ctx.next();
445        let of_type = if let Token::BracketOpen = token {
446            let inner = Type::new_with_ctx(ctx)?;
447            if let Token::BracketClose = ctx.next() {
448                Type::ListType(ctx.arena.alloc(inner))
449            } else {
450                return Err(ASTKind::ListType);
451            }
452        } else if let Token::Name(name) = token {
453            Type::NamedType(NamedType { name })
454        } else {
455            return Err(ASTKind::Type);
456        };
457        if let Token::Exclam = ctx.peek() {
458            ctx.next();
459            Ok(Type::NonNullType(ctx.arena.alloc(of_type)))
460        } else {
461            Ok(of_type)
462        }
463    }
464}
465
466impl<'a> private::ParseNode<'a> for VariableDefinition<'a> {
467    #[inline]
468    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<VariableDefinition<'a>> {
469        let variable = Variable::new_with_ctx(ctx)?;
470        let of_type = if let Token::Colon = ctx.next() {
471            Type::new_with_ctx(ctx)?
472        } else {
473            return Err(ASTKind::VariableDefinition);
474        };
475        let default_value = if let Token::Equal = ctx.peek() {
476            ctx.next();
477            ctx.in_var_def = true;
478            let value = Value::new_with_ctx(ctx)?;
479            ctx.in_var_def = false;
480            value
481        } else {
482            Value::Null
483        };
484        let directives = Directives::new_with_ctx(ctx)?;
485        Ok(VariableDefinition {
486            variable,
487            of_type,
488            default_value,
489            directives,
490        })
491    }
492}
493
494impl<'a> private::ParseNode<'a> for VariableDefinitions<'a> {
495    #[inline]
496    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<VariableDefinitions<'a>> {
497        let children = if let Token::ParenOpen = ctx.peek() {
498            ctx.next();
499            let mut builder = Vec::new_in(ctx.arena);
500            loop {
501                builder.push(VariableDefinition::new_with_ctx(ctx)?);
502                if let Token::ParenClose = ctx.peek() {
503                    ctx.next();
504                    break;
505                }
506            }
507            builder
508        } else {
509            Vec::new_in(ctx.arena)
510        };
511        Ok(VariableDefinitions { children })
512    }
513}
514
515impl<'a> private::ParseNode<'a> for FragmentDefinition<'a> {
516    #[inline]
517    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<FragmentDefinition<'a>> {
518        if let Token::Name("fragment") = ctx.next() {
519            let name = NamedType::new_with_ctx(ctx)?;
520            let type_condition = if let Token::Name("on") = ctx.next() {
521                NamedType::new_with_ctx(ctx)?
522            } else {
523                return Err(ASTKind::FragmentDefinition);
524            };
525            let directives = Directives::new_with_ctx(ctx)?;
526            let selection_set = if let Token::BraceOpen = ctx.peek() {
527                SelectionSet::new_with_ctx(ctx)?
528            } else {
529                return Err(ASTKind::FragmentDefinition);
530            };
531            Ok(FragmentDefinition {
532                name,
533                type_condition,
534                directives,
535                selection_set,
536            })
537        } else {
538            Err(ASTKind::FragmentDefinition)
539        }
540    }
541}
542
543impl<'a> private::ParseNode<'a> for OperationKind {
544    #[inline]
545    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<OperationKind> {
546        match ctx.next() {
547            Token::Name("query") => Ok(OperationKind::Query),
548            Token::Name("mutation") => Ok(OperationKind::Mutation),
549            Token::Name("subscription") => Ok(OperationKind::Subscription),
550            _ => Err(ASTKind::OperationKind),
551        }
552    }
553}
554
555impl<'a> private::ParseNode<'a> for OperationDefinition<'a> {
556    #[inline]
557    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<OperationDefinition<'a>> {
558        let operation = match ctx.peek() {
559            Token::BraceOpen => {
560                let selection_set = SelectionSet::new_with_ctx(ctx)?;
561                return Ok(OperationDefinition {
562                    operation: OperationKind::Query,
563                    name: None,
564                    variable_definitions: VariableDefinitions::default_in(ctx.arena),
565                    directives: Directives::default_in(ctx.arena),
566                    selection_set,
567                });
568            }
569            Token::Name("query") => OperationKind::Query,
570            Token::Name("mutation") => OperationKind::Mutation,
571            Token::Name("subscription") => OperationKind::Subscription,
572            _ => return Err(ASTKind::OperationDefinition),
573        };
574        ctx.next();
575        let name = if let Token::Name(_) = ctx.peek() {
576            NamedType::new_with_ctx(ctx).ok()
577        } else {
578            None
579        };
580        let variable_definitions = VariableDefinitions::new_with_ctx(ctx)?;
581        let directives = Directives::new_with_ctx(ctx)?;
582        if let Token::BraceOpen = ctx.peek() {
583            let selection_set = SelectionSet::new_with_ctx(ctx)?;
584            Ok(OperationDefinition {
585                operation,
586                name,
587                variable_definitions,
588                directives,
589                selection_set,
590            })
591        } else {
592            Err(ASTKind::OperationDefinition)
593        }
594    }
595}
596
597impl<'a> private::ParseNode<'a> for Document<'a> {
598    #[inline]
599    fn new_with_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<Document<'a>> {
600        let mut definitions = Vec::new_in(ctx.arena);
601        loop {
602            let definition = match ctx.peek() {
603                Token::BraceOpen | Token::Name("query" | "mutation" | "subscription") => {
604                    OperationDefinition::new_with_ctx(ctx).map(Definition::Operation)
605                }
606                Token::Name("fragment") => {
607                    FragmentDefinition::new_with_ctx(ctx).map(Definition::Fragment)
608                }
609                Token::End => break,
610                _ => Err(ASTKind::Document),
611            }?;
612            definitions.push(definition);
613        }
614        Ok(Document {
615            definitions,
616            size_hint: ctx.iter.span().end,
617        })
618    }
619}
620
621#[cfg(test)]
622mod tests {
623    use bumpalo::collections::Vec;
624
625    use crate::error::Location;
626
627    use super::{super::ast::*, ParseNode};
628
629    fn assert_parse<'a, T: 'a>(ctx: &'a ASTContext, source: &'a str, expected: T)
630    where
631        T: ParseNode<'a> + std::fmt::Debug + PartialEq,
632    {
633        assert_eq!(*T::parse(ctx, source).unwrap(), expected);
634    }
635
636    #[test]
637    fn error() {
638        let ctx = ASTContext::new();
639        let result = Document::parse(&ctx, "query { document { $ }}");
640
641        assert_eq!(
642            result.err().unwrap().location,
643            Some(Location {
644                column: 19,
645                line: 1
646            })
647        );
648
649        let result = Document::parse(
650            &ctx,
651            "query {
652            document {
653                $
654            }
655        }",
656        );
657        assert_eq!(
658            result.err().unwrap().location,
659            Some(Location {
660                column: 16,
661                line: 3
662            })
663        );
664    }
665
666    #[test]
667    fn named_type() {
668        let ctx = ASTContext::new();
669        assert_parse(&ctx, "TypeName", NamedType { name: "TypeName" });
670    }
671
672    #[test]
673    fn variable() {
674        let ctx = ASTContext::new();
675        assert_parse(&ctx, "$test", Variable { name: "test" });
676    }
677
678    #[test]
679    fn lists() {
680        let ctx = ASTContext::new();
681        assert_parse(
682            &ctx,
683            "[]",
684            ListValue {
685                children: Vec::new_in(&ctx.arena),
686            },
687        );
688
689        let list_children = Vec::from_iter_in([Value::Null, Value::Null], &ctx.arena);
690        assert_parse(
691            &ctx,
692            "[null, null]",
693            ListValue {
694                children: list_children,
695            },
696        );
697    }
698
699    #[test]
700    fn objects() {
701        let ctx = ASTContext::new();
702        assert_parse(
703            &ctx,
704            "{}",
705            ObjectValue {
706                children: Vec::new_in(&ctx.arena),
707            },
708        );
709        let list_children = Vec::from_iter_in(
710            [ObjectField {
711                name: "test",
712                value: Value::Boolean(BooleanValue { value: true }),
713            }],
714            &ctx.arena,
715        );
716        assert_parse(
717            &ctx,
718            "{ test: true }",
719            ObjectValue {
720                children: list_children,
721            },
722        );
723    }
724
725    #[test]
726    fn values() {
727        let ctx = ASTContext::new();
728        assert_parse(&ctx, "true", Value::Boolean(BooleanValue { value: true }));
729        assert_parse(&ctx, "false", Value::Boolean(BooleanValue { value: false }));
730        assert_parse(&ctx, "$var", Value::Variable(Variable { name: "var" }));
731        assert_parse(&ctx, "Opt", Value::Enum(EnumValue { value: "Opt" }));
732        assert_parse(&ctx, "123", Value::Int(IntValue { value: "123" }));
733        assert_parse(&ctx, "0.0", Value::Float(FloatValue { value: "0.0" }));
734        assert_parse(&ctx, "null", Value::Null);
735
736        assert_parse(
737            &ctx,
738            "\"hello world\"",
739            Value::String(StringValue::new(&ctx, "hello world")),
740        );
741
742        assert_parse(
743            &ctx,
744            "[]",
745            Value::List(ListValue {
746                children: Vec::new_in(&ctx.arena),
747            }),
748        );
749        assert_parse(
750            &ctx,
751            "[null, null]",
752            Value::List(ListValue {
753                children: Vec::from_iter_in([Value::Null, Value::Null], &ctx.arena),
754            }),
755        );
756
757        assert_parse(
758            &ctx,
759            "{}",
760            Value::Object(ObjectValue {
761                children: Vec::new_in(&ctx.arena),
762            }),
763        );
764        assert_parse(
765            &ctx,
766            "{ test: true }",
767            Value::Object(ObjectValue {
768                children: Vec::from_iter_in(
769                    [ObjectField {
770                        name: "test",
771                        value: Value::Boolean(BooleanValue { value: true }),
772                    }],
773                    &ctx.arena,
774                ),
775            }),
776        );
777    }
778
779    #[test]
780    fn arguments() {
781        let ctx = ASTContext::new();
782        assert_parse(
783            &ctx,
784            "()",
785            Arguments {
786                children: Vec::new_in(&ctx.arena),
787            },
788        );
789        assert_parse(
790            &ctx,
791            "(a: 1, b: 2)",
792            Arguments {
793                children: Vec::from_iter_in(
794                    [
795                        Argument {
796                            name: "a",
797                            value: Value::Int(IntValue { value: "1" }),
798                        },
799                        Argument {
800                            name: "b",
801                            value: Value::Int(IntValue { value: "2" }),
802                        },
803                    ],
804                    &ctx.arena,
805                ),
806            },
807        );
808    }
809
810    #[test]
811    fn directives() {
812        let ctx = ASTContext::new();
813
814        assert_parse(
815            &ctx,
816            "#",
817            Directives {
818                children: Vec::new_in(&ctx.arena),
819            },
820        );
821
822        assert_parse(
823            &ctx,
824            "@defer",
825            Directives {
826                children: Vec::from_iter_in(
827                    [Directive {
828                        name: "defer",
829                        arguments: Arguments {
830                            children: Vec::new_in(&ctx.arena),
831                        },
832                    }],
833                    &ctx.arena,
834                ),
835            },
836        );
837
838        assert_parse(
839            &ctx,
840            "@defer @defer",
841            Directives {
842                children: Vec::from_iter_in(
843                    [
844                        Directive {
845                            name: "defer",
846                            arguments: Arguments {
847                                children: Vec::new_in(&ctx.arena),
848                            },
849                        },
850                        Directive {
851                            name: "defer",
852                            arguments: Arguments {
853                                children: Vec::new_in(&ctx.arena),
854                            },
855                        },
856                    ],
857                    &ctx.arena,
858                ),
859            },
860        );
861
862        assert_parse(
863            &ctx,
864            "@include(if: $hi)",
865            Directive {
866                name: "include",
867                arguments: Arguments {
868                    children: Vec::from_iter_in(
869                        [Argument {
870                            name: "if",
871                            value: Value::Variable(Variable { name: "hi" }),
872                        }],
873                        &ctx.arena,
874                    ),
875                },
876            },
877        );
878    }
879
880    #[test]
881    fn fields() {
882        let ctx = ASTContext::new();
883
884        assert_parse(
885            &ctx,
886            "name",
887            Field {
888                alias: None,
889                name: "name",
890                arguments: Arguments {
891                    children: Vec::new_in(&ctx.arena),
892                },
893                directives: Directives {
894                    children: Vec::new_in(&ctx.arena),
895                },
896                selection_set: SelectionSet {
897                    selections: Vec::new_in(&ctx.arena),
898                },
899            },
900        );
901
902        assert_parse(
903            &ctx,
904            "name: name",
905            Field {
906                alias: Some("name"),
907                name: "name",
908                arguments: Arguments {
909                    children: Vec::new_in(&ctx.arena),
910                },
911                directives: Directives {
912                    children: Vec::new_in(&ctx.arena),
913                },
914                selection_set: SelectionSet {
915                    selections: Vec::new_in(&ctx.arena),
916                },
917            },
918        );
919
920        assert_parse(
921            &ctx,
922            "alias: name",
923            Field {
924                alias: Some("alias"),
925                name: "name",
926                arguments: Arguments {
927                    children: Vec::new_in(&ctx.arena),
928                },
929                directives: Directives {
930                    children: Vec::new_in(&ctx.arena),
931                },
932                selection_set: SelectionSet {
933                    selections: Vec::new_in(&ctx.arena),
934                },
935            },
936        );
937
938        assert_parse(
939            &ctx,
940            "alias: name(x: null)",
941            Field {
942                alias: Some("alias"),
943                name: "name",
944                arguments: Arguments {
945                    children: Vec::from_iter_in(
946                        [Argument {
947                            name: "x",
948                            value: Value::Null,
949                        }],
950                        &ctx.arena,
951                    ),
952                },
953                directives: Directives {
954                    children: Vec::new_in(&ctx.arena),
955                },
956                selection_set: SelectionSet {
957                    selections: Vec::new_in(&ctx.arena),
958                },
959            },
960        );
961
962        assert_parse(
963            &ctx,
964            "alias: name(x: null) @skip(if: true)",
965            Field {
966                alias: Some("alias"),
967                name: "name",
968                arguments: Arguments {
969                    children: Vec::from_iter_in(
970                        [Argument {
971                            name: "x",
972                            value: Value::Null,
973                        }],
974                        &ctx.arena,
975                    ),
976                },
977                directives: Directives {
978                    children: Vec::from_iter_in(
979                        [Directive {
980                            name: "skip",
981                            arguments: Arguments {
982                                children: Vec::from_iter_in(
983                                    [Argument {
984                                        name: "if",
985                                        value: Value::Boolean(BooleanValue { value: true }),
986                                    }],
987                                    &ctx.arena,
988                                ),
989                            },
990                        }],
991                        &ctx.arena,
992                    ),
993                },
994                selection_set: SelectionSet {
995                    selections: Vec::new_in(&ctx.arena),
996                },
997            },
998        );
999
1000        assert_parse(
1001            &ctx,
1002            "alias: name(x: null) @skip(if: true) { child }",
1003            Field {
1004                alias: Some("alias"),
1005                name: "name",
1006                arguments: Arguments {
1007                    children: Vec::from_iter_in(
1008                        [Argument {
1009                            name: "x",
1010                            value: Value::Null,
1011                        }],
1012                        &ctx.arena,
1013                    ),
1014                },
1015                directives: Directives {
1016                    children: Vec::from_iter_in(
1017                        [Directive {
1018                            name: "skip",
1019                            arguments: Arguments {
1020                                children: Vec::from_iter_in(
1021                                    [Argument {
1022                                        name: "if",
1023                                        value: Value::Boolean(BooleanValue { value: true }),
1024                                    }],
1025                                    &ctx.arena,
1026                                ),
1027                            },
1028                        }],
1029                        &ctx.arena,
1030                    ),
1031                },
1032                selection_set: SelectionSet {
1033                    selections: Vec::from_iter_in(
1034                        [Selection::Field(Field {
1035                            alias: None,
1036                            name: "child",
1037                            arguments: Arguments {
1038                                children: Vec::new_in(&ctx.arena),
1039                            },
1040                            directives: Directives {
1041                                children: Vec::new_in(&ctx.arena),
1042                            },
1043                            selection_set: SelectionSet {
1044                                selections: Vec::new_in(&ctx.arena),
1045                            },
1046                        })],
1047                        &ctx.arena,
1048                    ),
1049                },
1050            },
1051        );
1052
1053        assert_parse(
1054            &ctx,
1055            "parent { child }",
1056            Field {
1057                alias: None,
1058                name: "parent",
1059                arguments: Arguments {
1060                    children: Vec::new_in(&ctx.arena),
1061                },
1062                directives: Directives {
1063                    children: Vec::new_in(&ctx.arena),
1064                },
1065                selection_set: SelectionSet {
1066                    selections: Vec::from_iter_in(
1067                        [Selection::Field(Field {
1068                            alias: None,
1069                            name: "child",
1070                            arguments: Arguments {
1071                                children: Vec::new_in(&ctx.arena),
1072                            },
1073                            directives: Directives {
1074                                children: Vec::new_in(&ctx.arena),
1075                            },
1076                            selection_set: SelectionSet {
1077                                selections: Vec::new_in(&ctx.arena),
1078                            },
1079                        })],
1080                        &ctx.arena,
1081                    ),
1082                },
1083            },
1084        );
1085    }
1086
1087    #[test]
1088    fn fragment_spread() {
1089        let ctx = ASTContext::new();
1090
1091        assert_parse(
1092            &ctx,
1093            "... FragName",
1094            FragmentSpread {
1095                name: NamedType { name: "FragName" },
1096                directives: Directives {
1097                    children: Vec::new_in(&ctx.arena),
1098                },
1099            },
1100        );
1101
1102        assert_parse(
1103            &ctx,
1104            "... FragName @skip(if: true)",
1105            FragmentSpread {
1106                name: NamedType { name: "FragName" },
1107                directives: Directives {
1108                    children: Vec::from_iter_in(
1109                        [Directive {
1110                            name: "skip",
1111                            arguments: Arguments {
1112                                children: Vec::from_iter_in(
1113                                    [Argument {
1114                                        name: "if",
1115                                        value: Value::Boolean(BooleanValue { value: true }),
1116                                    }],
1117                                    &ctx.arena,
1118                                ),
1119                            },
1120                        }],
1121                        &ctx.arena,
1122                    ),
1123                },
1124            },
1125        );
1126    }
1127
1128    #[test]
1129    fn inline_fragment() {
1130        let ctx = ASTContext::new();
1131
1132        assert_parse(
1133            &ctx,
1134            "... { __typename }",
1135            InlineFragment {
1136                type_condition: None,
1137                directives: Directives {
1138                    children: Vec::new_in(&ctx.arena),
1139                },
1140                selection_set: SelectionSet {
1141                    selections: Vec::from_iter_in(
1142                        [Selection::Field(Field {
1143                            alias: None,
1144                            name: "__typename",
1145                            arguments: Arguments {
1146                                children: Vec::new_in(&ctx.arena),
1147                            },
1148                            directives: Directives {
1149                                children: Vec::new_in(&ctx.arena),
1150                            },
1151                            selection_set: SelectionSet {
1152                                selections: Vec::new_in(&ctx.arena),
1153                            },
1154                        })],
1155                        &ctx.arena,
1156                    ),
1157                },
1158            },
1159        );
1160
1161        assert_parse(
1162            &ctx,
1163            "... on Frag { __typename }",
1164            InlineFragment {
1165                type_condition: Some(NamedType { name: "Frag" }),
1166                directives: Directives {
1167                    children: Vec::new_in(&ctx.arena),
1168                },
1169                selection_set: SelectionSet {
1170                    selections: Vec::from_iter_in(
1171                        [Selection::Field(Field {
1172                            alias: None,
1173                            name: "__typename",
1174                            arguments: Arguments {
1175                                children: Vec::new_in(&ctx.arena),
1176                            },
1177                            directives: Directives {
1178                                children: Vec::new_in(&ctx.arena),
1179                            },
1180                            selection_set: SelectionSet {
1181                                selections: Vec::new_in(&ctx.arena),
1182                            },
1183                        })],
1184                        &ctx.arena,
1185                    ),
1186                },
1187            },
1188        );
1189
1190        assert_parse(
1191            &ctx,
1192            "... @skip(if: true) { __typename }",
1193            InlineFragment {
1194                type_condition: None,
1195                directives: Directives {
1196                    children: Vec::from_iter_in(
1197                        [Directive {
1198                            name: "skip",
1199                            arguments: Arguments {
1200                                children: Vec::from_iter_in(
1201                                    [Argument {
1202                                        name: "if",
1203                                        value: Value::Boolean(BooleanValue { value: true }),
1204                                    }],
1205                                    &ctx.arena,
1206                                ),
1207                            },
1208                        }],
1209                        &ctx.arena,
1210                    ),
1211                },
1212                selection_set: SelectionSet {
1213                    selections: Vec::from_iter_in(
1214                        [Selection::Field(Field {
1215                            alias: None,
1216                            name: "__typename",
1217                            arguments: Arguments {
1218                                children: Vec::new_in(&ctx.arena),
1219                            },
1220                            directives: Directives {
1221                                children: Vec::new_in(&ctx.arena),
1222                            },
1223                            selection_set: SelectionSet {
1224                                selections: Vec::new_in(&ctx.arena),
1225                            },
1226                        })],
1227                        &ctx.arena,
1228                    ),
1229                },
1230            },
1231        );
1232
1233        assert_parse(
1234            &ctx,
1235            "...on Frag @skip(if: true) { __typename }",
1236            InlineFragment {
1237                type_condition: Some(NamedType { name: "Frag" }),
1238                directives: Directives {
1239                    children: Vec::from_iter_in(
1240                        [Directive {
1241                            name: "skip",
1242                            arguments: Arguments {
1243                                children: Vec::from_iter_in(
1244                                    [Argument {
1245                                        name: "if",
1246                                        value: Value::Boolean(BooleanValue { value: true }),
1247                                    }],
1248                                    &ctx.arena,
1249                                ),
1250                            },
1251                        }],
1252                        &ctx.arena,
1253                    ),
1254                },
1255                selection_set: SelectionSet {
1256                    selections: Vec::from_iter_in(
1257                        [Selection::Field(Field {
1258                            alias: None,
1259                            name: "__typename",
1260                            arguments: Arguments {
1261                                children: Vec::new_in(&ctx.arena),
1262                            },
1263                            directives: Directives {
1264                                children: Vec::new_in(&ctx.arena),
1265                            },
1266                            selection_set: SelectionSet {
1267                                selections: Vec::new_in(&ctx.arena),
1268                            },
1269                        })],
1270                        &ctx.arena,
1271                    ),
1272                },
1273            },
1274        );
1275    }
1276
1277    #[test]
1278    fn selections() {
1279        let ctx = ASTContext::new();
1280
1281        assert_parse(
1282            &ctx,
1283            "{ name, ... on Frag { name }, ... OtherFrag, ... { name }, name2: name }",
1284            SelectionSet {
1285                selections: Vec::from_iter_in(
1286                    [
1287                        Selection::Field(Field {
1288                            alias: None,
1289                            name: "name",
1290                            arguments: Arguments {
1291                                children: Vec::new_in(&ctx.arena),
1292                            },
1293                            directives: Directives {
1294                                children: Vec::new_in(&ctx.arena),
1295                            },
1296                            selection_set: SelectionSet {
1297                                selections: Vec::new_in(&ctx.arena),
1298                            },
1299                        }),
1300                        Selection::InlineFragment(InlineFragment {
1301                            type_condition: Some(NamedType { name: "Frag" }),
1302                            directives: Directives {
1303                                children: Vec::new_in(&ctx.arena),
1304                            },
1305                            selection_set: SelectionSet {
1306                                selections: Vec::from_iter_in(
1307                                    [Selection::Field(Field {
1308                                        alias: None,
1309                                        name: "name",
1310                                        arguments: Arguments {
1311                                            children: Vec::new_in(&ctx.arena),
1312                                        },
1313                                        directives: Directives {
1314                                            children: Vec::new_in(&ctx.arena),
1315                                        },
1316                                        selection_set: SelectionSet {
1317                                            selections: Vec::new_in(&ctx.arena),
1318                                        },
1319                                    })],
1320                                    &ctx.arena,
1321                                ),
1322                            },
1323                        }),
1324                        Selection::FragmentSpread(FragmentSpread {
1325                            name: NamedType { name: "OtherFrag" },
1326                            directives: Directives {
1327                                children: Vec::new_in(&ctx.arena),
1328                            },
1329                        }),
1330                        Selection::InlineFragment(InlineFragment {
1331                            type_condition: None,
1332                            directives: Directives {
1333                                children: Vec::new_in(&ctx.arena),
1334                            },
1335                            selection_set: SelectionSet {
1336                                selections: Vec::from_iter_in(
1337                                    [Selection::Field(Field {
1338                                        alias: None,
1339                                        name: "name",
1340                                        arguments: Arguments {
1341                                            children: Vec::new_in(&ctx.arena),
1342                                        },
1343                                        directives: Directives {
1344                                            children: Vec::new_in(&ctx.arena),
1345                                        },
1346                                        selection_set: SelectionSet {
1347                                            selections: Vec::new_in(&ctx.arena),
1348                                        },
1349                                    })],
1350                                    &ctx.arena,
1351                                ),
1352                            },
1353                        }),
1354                        Selection::Field(Field {
1355                            alias: Some("name2"),
1356                            name: "name",
1357                            arguments: Arguments {
1358                                children: Vec::new_in(&ctx.arena),
1359                            },
1360                            directives: Directives {
1361                                children: Vec::new_in(&ctx.arena),
1362                            },
1363                            selection_set: SelectionSet {
1364                                selections: Vec::new_in(&ctx.arena),
1365                            },
1366                        }),
1367                    ],
1368                    &ctx.arena,
1369                ),
1370            },
1371        )
1372    }
1373
1374    #[test]
1375    fn types() {
1376        let ctx = ASTContext::new();
1377
1378        assert_parse(&ctx, "Type", Type::NamedType(NamedType { name: "Type" }));
1379
1380        assert_parse(
1381            &ctx,
1382            "Type!",
1383            Type::NonNullType(ctx.alloc(Type::NamedType(NamedType { name: "Type" }))),
1384        );
1385
1386        assert_parse(
1387            &ctx,
1388            "[Type!]",
1389            Type::ListType(ctx.alloc(Type::NonNullType(
1390                ctx.alloc(Type::NamedType(NamedType { name: "Type" })),
1391            ))),
1392        );
1393
1394        assert_parse(
1395            &ctx,
1396            "[Type!]!",
1397            Type::NonNullType(ctx.alloc(Type::ListType(ctx.alloc(Type::NonNullType(
1398                ctx.alloc(Type::NamedType(NamedType { name: "Type" })),
1399            ))))),
1400        );
1401
1402        assert_parse(
1403            &ctx,
1404            "[[Type]]",
1405            Type::ListType(ctx.alloc(Type::ListType(
1406                ctx.alloc(Type::NamedType(NamedType { name: "Type" })),
1407            ))),
1408        );
1409    }
1410
1411    #[test]
1412    fn var_definitions() {
1413        let ctx = ASTContext::new();
1414        assert_parse(
1415            &ctx,
1416            "#",
1417            VariableDefinitions {
1418                children: Vec::new_in(&ctx.arena),
1419            },
1420        );
1421
1422        // A variable definition cannot refer to another variable
1423        VariableDefinitions::parse(&ctx, "($var: $var)").unwrap_err();
1424        VariableDefinitions::parse(&ctx, "($var: [$var])").unwrap_err();
1425
1426        assert_parse(
1427            &ctx,
1428            "($test: String)",
1429            VariableDefinitions {
1430                children: Vec::from_iter_in(
1431                    [VariableDefinition {
1432                        variable: Variable { name: "test" },
1433                        of_type: Type::NamedType(NamedType { name: "String" }),
1434                        default_value: Value::Null,
1435                        directives: Directives {
1436                            children: Vec::new_in(&ctx.arena),
1437                        },
1438                    }],
1439                    &ctx.arena,
1440                ),
1441            },
1442        );
1443
1444        assert_parse(
1445            &ctx,
1446            "($test1: String, $test2: Int)",
1447            VariableDefinitions {
1448                children: Vec::from_iter_in(
1449                    [
1450                        VariableDefinition {
1451                            variable: Variable { name: "test1" },
1452                            of_type: Type::NamedType(NamedType { name: "String" }),
1453                            default_value: Value::Null,
1454                            directives: Directives {
1455                                children: Vec::new_in(&ctx.arena),
1456                            },
1457                        },
1458                        VariableDefinition {
1459                            variable: Variable { name: "test2" },
1460                            of_type: Type::NamedType(NamedType { name: "Int" }),
1461                            default_value: Value::Null,
1462                            directives: Directives {
1463                                children: Vec::new_in(&ctx.arena),
1464                            },
1465                        },
1466                    ],
1467                    &ctx.arena,
1468                ),
1469            },
1470        );
1471
1472        assert_parse(
1473            &ctx,
1474            "$x: Int = 123",
1475            VariableDefinition {
1476                variable: Variable { name: "x" },
1477                of_type: Type::NamedType(NamedType { name: "Int" }),
1478                default_value: Value::Int(IntValue { value: "123" }),
1479                directives: Directives {
1480                    children: Vec::new_in(&ctx.arena),
1481                },
1482            },
1483        );
1484
1485        assert_parse(
1486            &ctx,
1487            "$x: Int = 123 @test",
1488            VariableDefinition {
1489                variable: Variable { name: "x" },
1490                of_type: Type::NamedType(NamedType { name: "Int" }),
1491                default_value: Value::Int(IntValue { value: "123" }),
1492                directives: Directives {
1493                    children: Vec::from_iter_in(
1494                        [Directive {
1495                            name: "test",
1496                            arguments: Arguments {
1497                                children: Vec::new_in(&ctx.arena),
1498                            },
1499                        }],
1500                        &ctx.arena,
1501                    ),
1502                },
1503            },
1504        );
1505
1506        assert_parse(
1507            &ctx,
1508            "$x: Int @test",
1509            VariableDefinition {
1510                variable: Variable { name: "x" },
1511                of_type: Type::NamedType(NamedType { name: "Int" }),
1512                default_value: Value::Null,
1513                directives: Directives {
1514                    children: Vec::from_iter_in(
1515                        [Directive {
1516                            name: "test",
1517                            arguments: Arguments {
1518                                children: Vec::new_in(&ctx.arena),
1519                            },
1520                        }],
1521                        &ctx.arena,
1522                    ),
1523                },
1524            },
1525        );
1526    }
1527
1528    #[test]
1529    fn fragment() {
1530        let ctx = ASTContext::new();
1531
1532        assert_parse(
1533            &ctx,
1534            "fragment Test on Type { name }",
1535            FragmentDefinition {
1536                name: NamedType { name: "Test" },
1537                type_condition: NamedType { name: "Type" },
1538                directives: Directives {
1539                    children: Vec::new_in(&ctx.arena),
1540                },
1541                selection_set: SelectionSet {
1542                    selections: Vec::from_iter_in(
1543                        [Selection::Field(Field {
1544                            alias: None,
1545                            name: "name",
1546                            arguments: Arguments {
1547                                children: Vec::new_in(&ctx.arena),
1548                            },
1549                            directives: Directives {
1550                                children: Vec::new_in(&ctx.arena),
1551                            },
1552                            selection_set: SelectionSet {
1553                                selections: Vec::new_in(&ctx.arena),
1554                            },
1555                        })],
1556                        &ctx.arena,
1557                    ),
1558                },
1559            },
1560        );
1561
1562        assert_parse(
1563            &ctx,
1564            "fragment Test on Type @test { name }",
1565            FragmentDefinition {
1566                name: NamedType { name: "Test" },
1567                type_condition: NamedType { name: "Type" },
1568                directives: Directives {
1569                    children: Vec::from_iter_in(
1570                        [Directive {
1571                            name: "test",
1572                            arguments: Arguments {
1573                                children: Vec::new_in(&ctx.arena),
1574                            },
1575                        }],
1576                        &ctx.arena,
1577                    ),
1578                },
1579                selection_set: SelectionSet {
1580                    selections: Vec::from_iter_in(
1581                        [Selection::Field(Field {
1582                            alias: None,
1583                            name: "name",
1584                            arguments: Arguments {
1585                                children: Vec::new_in(&ctx.arena),
1586                            },
1587                            directives: Directives {
1588                                children: Vec::new_in(&ctx.arena),
1589                            },
1590                            selection_set: SelectionSet {
1591                                selections: Vec::new_in(&ctx.arena),
1592                            },
1593                        })],
1594                        &ctx.arena,
1595                    ),
1596                },
1597            },
1598        );
1599    }
1600
1601    #[test]
1602    fn operation_with_high_int_value() {
1603        let ctx = ASTContext::new();
1604
1605        assert_parse(
1606            &ctx,
1607            "query { field(id: 1002275100009989500000000000000000000000000000000000) }",
1608            OperationDefinition {
1609                operation: OperationKind::Query,
1610                name: None,
1611                variable_definitions: VariableDefinitions { children: Vec::new_in(&ctx.arena )},
1612                directives: Directives { children: Vec::new_in(&ctx.arena )},
1613                selection_set: SelectionSet{ selections: Vec::from_iter_in(
1614                    [Selection::Field(Field {
1615                        alias: None,
1616                        name: "field",
1617                        arguments: Arguments { children: Vec::from_iter_in(
1618                            [Argument {
1619                                name: "id",
1620                                value: Value::Int(IntValue {
1621                                    value: "1002275100009989500000000000000000000000000000000000",
1622                                }),
1623                            }],
1624                            &ctx.arena,
1625                        )},
1626                        directives: Directives { children: Vec::new_in(&ctx.arena )},
1627                        selection_set: SelectionSet { selections: Vec::new_in(&ctx.arena )},
1628                    })],
1629                    &ctx.arena,
1630                )},
1631            },
1632        )
1633    }
1634
1635    #[test]
1636    fn operation() {
1637        let ctx = ASTContext::new();
1638
1639        assert_parse(
1640            &ctx,
1641            "{ name }",
1642            OperationDefinition {
1643                operation: OperationKind::Query,
1644                name: None,
1645                variable_definitions: VariableDefinitions {
1646                    children: Vec::new_in(&ctx.arena),
1647                },
1648                directives: Directives {
1649                    children: Vec::new_in(&ctx.arena),
1650                },
1651                selection_set: SelectionSet {
1652                    selections: Vec::from_iter_in(
1653                        [Selection::Field(Field {
1654                            alias: None,
1655                            name: "name",
1656                            arguments: Arguments {
1657                                children: Vec::new_in(&ctx.arena),
1658                            },
1659                            directives: Directives {
1660                                children: Vec::new_in(&ctx.arena),
1661                            },
1662                            selection_set: SelectionSet {
1663                                selections: Vec::new_in(&ctx.arena),
1664                            },
1665                        })],
1666                        &ctx.arena,
1667                    ),
1668                },
1669            },
1670        );
1671
1672        assert_parse(
1673            &ctx,
1674            "query { name }",
1675            OperationDefinition {
1676                operation: OperationKind::Query,
1677                name: None,
1678                variable_definitions: VariableDefinitions {
1679                    children: Vec::new_in(&ctx.arena),
1680                },
1681                directives: Directives {
1682                    children: Vec::new_in(&ctx.arena),
1683                },
1684                selection_set: SelectionSet {
1685                    selections: Vec::from_iter_in(
1686                        [Selection::Field(Field {
1687                            alias: None,
1688                            name: "name",
1689                            arguments: Arguments {
1690                                children: Vec::new_in(&ctx.arena),
1691                            },
1692                            directives: Directives {
1693                                children: Vec::new_in(&ctx.arena),
1694                            },
1695                            selection_set: SelectionSet {
1696                                selections: Vec::new_in(&ctx.arena),
1697                            },
1698                        })],
1699                        &ctx.arena,
1700                    ),
1701                },
1702            },
1703        );
1704
1705        assert_parse(
1706            &ctx,
1707            "mutation { name }",
1708            OperationDefinition {
1709                operation: OperationKind::Mutation,
1710                name: None,
1711                variable_definitions: VariableDefinitions {
1712                    children: Vec::new_in(&ctx.arena),
1713                },
1714                directives: Directives {
1715                    children: Vec::new_in(&ctx.arena),
1716                },
1717                selection_set: SelectionSet {
1718                    selections: Vec::from_iter_in(
1719                        [Selection::Field(Field {
1720                            alias: None,
1721                            name: "name",
1722                            arguments: Arguments {
1723                                children: Vec::new_in(&ctx.arena),
1724                            },
1725                            directives: Directives {
1726                                children: Vec::new_in(&ctx.arena),
1727                            },
1728                            selection_set: SelectionSet {
1729                                selections: Vec::new_in(&ctx.arena),
1730                            },
1731                        })],
1732                        &ctx.arena,
1733                    ),
1734                },
1735            },
1736        );
1737
1738        assert_parse(
1739            &ctx,
1740            "subscription { name }",
1741            OperationDefinition {
1742                operation: OperationKind::Subscription,
1743                name: None,
1744                variable_definitions: VariableDefinitions {
1745                    children: Vec::new_in(&ctx.arena),
1746                },
1747                directives: Directives {
1748                    children: Vec::new_in(&ctx.arena),
1749                },
1750                selection_set: SelectionSet {
1751                    selections: Vec::from_iter_in(
1752                        [Selection::Field(Field {
1753                            alias: None,
1754                            name: "name",
1755                            arguments: Arguments {
1756                                children: Vec::new_in(&ctx.arena),
1757                            },
1758                            directives: Directives {
1759                                children: Vec::new_in(&ctx.arena),
1760                            },
1761                            selection_set: SelectionSet {
1762                                selections: Vec::new_in(&ctx.arena),
1763                            },
1764                        })],
1765                        &ctx.arena,
1766                    ),
1767                },
1768            },
1769        );
1770
1771        assert_parse(
1772            &ctx,
1773            "query Name { name }",
1774            OperationDefinition {
1775                operation: OperationKind::Query,
1776                name: Some(NamedType { name: "Name" }),
1777                variable_definitions: VariableDefinitions {
1778                    children: Vec::new_in(&ctx.arena),
1779                },
1780                directives: Directives {
1781                    children: Vec::new_in(&ctx.arena),
1782                },
1783                selection_set: SelectionSet {
1784                    selections: Vec::from_iter_in(
1785                        [Selection::Field(Field {
1786                            alias: None,
1787                            name: "name",
1788                            arguments: Arguments {
1789                                children: Vec::new_in(&ctx.arena),
1790                            },
1791                            directives: Directives {
1792                                children: Vec::new_in(&ctx.arena),
1793                            },
1794                            selection_set: SelectionSet {
1795                                selections: Vec::new_in(&ctx.arena),
1796                            },
1797                        })],
1798                        &ctx.arena,
1799                    ),
1800                },
1801            },
1802        );
1803
1804        assert_parse(
1805            &ctx,
1806            "query Name($test: Int) { name }",
1807            OperationDefinition {
1808                operation: OperationKind::Query,
1809                name: Some(NamedType { name: "Name" }),
1810                variable_definitions: VariableDefinitions {
1811                    children: Vec::from_iter_in(
1812                        [VariableDefinition {
1813                            variable: Variable { name: "test" },
1814                            of_type: Type::NamedType(NamedType { name: "Int" }),
1815                            directives: Directives {
1816                                children: Vec::new_in(&ctx.arena),
1817                            },
1818                            default_value: Value::Null,
1819                        }],
1820                        &ctx.arena,
1821                    ),
1822                },
1823                directives: Directives {
1824                    children: Vec::new_in(&ctx.arena),
1825                },
1826                selection_set: SelectionSet {
1827                    selections: Vec::from_iter_in(
1828                        [Selection::Field(Field {
1829                            alias: None,
1830                            name: "name",
1831                            arguments: Arguments {
1832                                children: Vec::new_in(&ctx.arena),
1833                            },
1834                            directives: Directives {
1835                                children: Vec::new_in(&ctx.arena),
1836                            },
1837                            selection_set: SelectionSet {
1838                                selections: Vec::new_in(&ctx.arena),
1839                            },
1840                        })],
1841                        &ctx.arena,
1842                    ),
1843                },
1844            },
1845        );
1846
1847        assert_parse(
1848            &ctx,
1849            "query Name @test { name }",
1850            OperationDefinition {
1851                operation: OperationKind::Query,
1852                name: Some(NamedType { name: "Name" }),
1853                variable_definitions: VariableDefinitions {
1854                    children: Vec::new_in(&ctx.arena),
1855                },
1856                directives: Directives {
1857                    children: Vec::from_iter_in(
1858                        [Directive {
1859                            name: "test",
1860                            arguments: Arguments {
1861                                children: Vec::new_in(&ctx.arena),
1862                            },
1863                        }],
1864                        &ctx.arena,
1865                    ),
1866                },
1867                selection_set: SelectionSet {
1868                    selections: Vec::from_iter_in(
1869                        [Selection::Field(Field {
1870                            alias: None,
1871                            name: "name",
1872                            arguments: Arguments {
1873                                children: Vec::new_in(&ctx.arena),
1874                            },
1875                            directives: Directives {
1876                                children: Vec::new_in(&ctx.arena),
1877                            },
1878                            selection_set: SelectionSet {
1879                                selections: Vec::new_in(&ctx.arena),
1880                            },
1881                        })],
1882                        &ctx.arena,
1883                    ),
1884                },
1885            },
1886        );
1887    }
1888}