Skip to main content

oxc_graphql_parser/
ast.rs

1use crate::Error;
2use crate::LimitTracker;
3use std::fmt;
4use std::slice::Iter;
5
6pub use oxc_allocator::{Box as AstBox, Vec as AstVec};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)]
9pub struct Span {
10    pub start: usize,
11    pub end: usize,
12}
13
14impl Span {
15    pub fn new(start: usize, end: usize) -> Self {
16        Self { start, end }
17    }
18}
19
20#[derive(Debug, PartialEq)]
21pub struct Ast<'a, T> {
22    source: &'a str,
23    root: T,
24    errors: Vec<Error>,
25    comments: Vec<Span>,
26    recursion_limit: LimitTracker,
27    token_limit: LimitTracker,
28}
29
30impl<'a, T> Ast<'a, T> {
31    pub(crate) fn new(
32        source: &'a str,
33        root: T,
34        errors: Vec<Error>,
35        comments: Vec<Span>,
36        recursion_limit: LimitTracker,
37        token_limit: LimitTracker,
38    ) -> Self {
39        Self { source, root, errors, comments, recursion_limit, token_limit }
40    }
41
42    pub fn root(&self) -> &T {
43        &self.root
44    }
45
46    pub fn into_root(self) -> T {
47        self.root
48    }
49
50    pub fn source(&self) -> &str {
51        self.source
52    }
53
54    pub fn errors(&self) -> Iter<'_, Error> {
55        self.errors.iter()
56    }
57
58    /// Comment token spans in document order.
59    ///
60    /// GraphQL comments are always line comments: each span covers `#` through
61    /// the end of the line (excluding the line terminator).
62    ///
63    /// NOTE: Only comments consumed while parsing are recorded.
64    /// [`Parser::parse`] reads to the end of input, so it collects every comment in the source.
65    /// Partial roots ([`Parser::parse_selection_set`], [`Parser::parse_type`])
66    /// stop at the end of the root, so comments past it are not included.
67    ///
68    /// [`Parser::parse`]: crate::Parser::parse
69    /// [`Parser::parse_selection_set`]: crate::Parser::parse_selection_set
70    /// [`Parser::parse_type`]: crate::Parser::parse_type
71    pub fn comments(&self) -> &[Span] {
72        &self.comments
73    }
74
75    pub fn recursion_limit(&self) -> LimitTracker {
76        self.recursion_limit
77    }
78
79    pub fn token_limit(&self) -> LimitTracker {
80        self.token_limit
81    }
82}
83
84impl<'a> Ast<'a, Document<'a>> {
85    pub fn document(&self) -> &Document<'a> {
86        self.root()
87    }
88}
89
90impl<'a> Ast<'a, SelectionSet<'a>> {
91    pub fn field_set(&self) -> &SelectionSet<'a> {
92        self.root()
93    }
94}
95
96impl<'a> Ast<'a, Type<'a>> {
97    pub fn ty(&self) -> &Type<'a> {
98        self.root()
99    }
100}
101
102#[derive(Debug, PartialEq)]
103pub struct Document<'a> {
104    pub definitions: AstVec<'a, Definition<'a>>,
105    pub span: Span,
106}
107
108#[derive(Debug, PartialEq)]
109pub enum Definition<'a> {
110    Operation(OperationDefinition<'a>),
111    Fragment(FragmentDefinition<'a>),
112    Directive(DirectiveDefinition<'a>),
113    Schema(SchemaDefinition<'a>),
114    SchemaExtension(SchemaExtension<'a>),
115    ScalarType(ScalarTypeDefinition<'a>),
116    ScalarTypeExtension(ScalarTypeExtension<'a>),
117    ObjectType(ObjectTypeDefinition<'a>),
118    ObjectTypeExtension(ObjectTypeExtension<'a>),
119    InterfaceType(InterfaceTypeDefinition<'a>),
120    InterfaceTypeExtension(InterfaceTypeExtension<'a>),
121    UnionType(UnionTypeDefinition<'a>),
122    UnionTypeExtension(UnionTypeExtension<'a>),
123    EnumType(EnumTypeDefinition<'a>),
124    EnumTypeExtension(EnumTypeExtension<'a>),
125    InputObjectType(InputObjectTypeDefinition<'a>),
126    InputObjectTypeExtension(InputObjectTypeExtension<'a>),
127}
128
129impl<'a> Definition<'a> {
130    pub fn name(&self) -> Option<&Name<'a>> {
131        match self {
132            Self::Operation(definition) => definition.name.as_ref(),
133            Self::Fragment(definition) => Some(&definition.name),
134            Self::Directive(definition) => Some(&definition.name),
135            Self::Schema(_) | Self::SchemaExtension(_) => None,
136            Self::ScalarType(definition) => Some(&definition.name),
137            Self::ScalarTypeExtension(definition) => Some(&definition.name),
138            Self::ObjectType(definition) => Some(&definition.name),
139            Self::ObjectTypeExtension(definition) => Some(&definition.name),
140            Self::InterfaceType(definition) => Some(&definition.name),
141            Self::InterfaceTypeExtension(definition) => Some(&definition.name),
142            Self::UnionType(definition) => Some(&definition.name),
143            Self::UnionTypeExtension(definition) => Some(&definition.name),
144            Self::EnumType(definition) => Some(&definition.name),
145            Self::EnumTypeExtension(definition) => Some(&definition.name),
146            Self::InputObjectType(definition) => Some(&definition.name),
147            Self::InputObjectTypeExtension(definition) => Some(&definition.name),
148        }
149    }
150
151    /// The source span of the definition, whichever variant it is.
152    ///
153    /// When adding a new variant, remember to extend this match as well.
154    pub fn span(&self) -> Span {
155        match self {
156            Self::Operation(definition) => definition.span,
157            Self::Fragment(definition) => definition.span,
158            Self::Directive(definition) => definition.span,
159            Self::Schema(definition) => definition.span,
160            Self::SchemaExtension(definition) => definition.span,
161            Self::ScalarType(definition) => definition.span,
162            Self::ScalarTypeExtension(definition) => definition.span,
163            Self::ObjectType(definition) => definition.span,
164            Self::ObjectTypeExtension(definition) => definition.span,
165            Self::InterfaceType(definition) => definition.span,
166            Self::InterfaceTypeExtension(definition) => definition.span,
167            Self::UnionType(definition) => definition.span,
168            Self::UnionTypeExtension(definition) => definition.span,
169            Self::EnumType(definition) => definition.span,
170            Self::EnumTypeExtension(definition) => definition.span,
171            Self::InputObjectType(definition) => definition.span,
172            Self::InputObjectTypeExtension(definition) => definition.span,
173        }
174    }
175}
176
177#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
178pub struct Name<'a> {
179    pub value: &'a str,
180    pub span: Span,
181}
182
183impl Name<'_> {
184    pub fn as_str(&self) -> &str {
185        self.value
186    }
187}
188
189impl fmt::Display for Name<'_> {
190    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191        f.write_str(self.value)
192    }
193}
194
195#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
196pub struct StringValue<'a> {
197    pub raw: &'a str,
198    pub value: &'a str,
199    pub block: bool,
200    pub span: Span,
201}
202
203#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
204pub enum OperationType {
205    Query,
206    Mutation,
207    Subscription,
208}
209
210#[derive(Debug, PartialEq)]
211pub struct OperationDefinition<'a> {
212    pub description: Option<StringValue<'a>>,
213    pub operation_type: OperationType,
214    pub name: Option<Name<'a>>,
215    pub variable_definitions: AstVec<'a, VariableDefinition<'a>>,
216    pub directives: AstVec<'a, Directive<'a>>,
217    pub selection_set: Option<SelectionSet<'a>>,
218    pub span: Span,
219}
220
221#[derive(Debug, PartialEq)]
222pub struct FragmentDefinition<'a> {
223    pub description: Option<StringValue<'a>>,
224    pub name: Name<'a>,
225    pub variable_definitions: AstVec<'a, VariableDefinition<'a>>,
226    pub type_condition: NamedType<'a>,
227    pub directives: AstVec<'a, Directive<'a>>,
228    pub selection_set: Option<SelectionSet<'a>>,
229    pub span: Span,
230}
231
232#[derive(Debug, PartialEq)]
233pub struct SelectionSet<'a> {
234    pub selections: AstVec<'a, Selection<'a>>,
235    pub span: Span,
236}
237
238#[derive(Debug, PartialEq)]
239pub enum Selection<'a> {
240    Field(Field<'a>),
241    FragmentSpread(FragmentSpread<'a>),
242    InlineFragment(InlineFragment<'a>),
243}
244
245impl Selection<'_> {
246    /// The source span of the selection, whichever variant it is.
247    ///
248    /// When adding a new variant, remember to extend this match as well.
249    pub fn span(&self) -> Span {
250        match self {
251            Self::Field(selection) => selection.span,
252            Self::FragmentSpread(selection) => selection.span,
253            Self::InlineFragment(selection) => selection.span,
254        }
255    }
256}
257
258#[derive(Debug, PartialEq)]
259pub struct Field<'a> {
260    pub alias: Option<Name<'a>>,
261    pub name: Name<'a>,
262    pub arguments: AstVec<'a, Argument<'a>>,
263    pub directives: AstVec<'a, Directive<'a>>,
264    pub selection_set: Option<SelectionSet<'a>>,
265    pub span: Span,
266}
267
268#[derive(Debug, PartialEq)]
269pub struct FragmentSpread<'a> {
270    pub name: Name<'a>,
271    pub directives: AstVec<'a, Directive<'a>>,
272    pub span: Span,
273}
274
275#[derive(Debug, PartialEq)]
276pub struct InlineFragment<'a> {
277    pub type_condition: Option<NamedType<'a>>,
278    pub directives: AstVec<'a, Directive<'a>>,
279    pub selection_set: Option<SelectionSet<'a>>,
280    pub span: Span,
281}
282
283#[derive(Debug, PartialEq)]
284pub struct VariableDefinition<'a> {
285    pub description: Option<StringValue<'a>>,
286    pub variable: Variable<'a>,
287    pub ty: Option<Type<'a>>,
288    pub default_value: Option<Value<'a>>,
289    pub directives: AstVec<'a, Directive<'a>>,
290    pub span: Span,
291}
292
293#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
294pub struct Variable<'a> {
295    pub name: Name<'a>,
296    pub span: Span,
297}
298
299#[derive(Debug, PartialEq)]
300pub struct Argument<'a> {
301    pub name: Name<'a>,
302    pub value: Option<Value<'a>>,
303    pub span: Span,
304}
305
306#[derive(Debug, PartialEq)]
307pub struct Directive<'a> {
308    pub name: Name<'a>,
309    pub arguments: AstVec<'a, Argument<'a>>,
310    pub span: Span,
311}
312
313#[derive(Debug, PartialEq)]
314pub enum Value<'a> {
315    Variable(Variable<'a>),
316    Int(IntValue<'a>),
317    Float(FloatValue<'a>),
318    String(StringValue<'a>),
319    Boolean(BooleanValue),
320    Null(NullValue),
321    Enum(EnumValue<'a>),
322    List(ListValue<'a>),
323    Object(ObjectValue<'a>),
324    Missing(Span),
325}
326
327impl Value<'_> {
328    pub fn span(&self) -> Span {
329        match self {
330            Self::Variable(value) => value.span,
331            Self::Int(value) => value.span,
332            Self::Float(value) => value.span,
333            Self::String(value) => value.span,
334            Self::Boolean(value) => value.span,
335            Self::Null(value) => value.span,
336            Self::Enum(value) => value.name.span,
337            Self::List(value) => value.span,
338            Self::Object(value) => value.span,
339            Self::Missing(span) => *span,
340        }
341    }
342}
343
344#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
345pub struct IntValue<'a> {
346    pub raw: &'a str,
347    pub span: Span,
348}
349
350#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
351pub struct FloatValue<'a> {
352    pub raw: &'a str,
353    pub span: Span,
354}
355
356#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
357pub struct BooleanValue {
358    pub value: bool,
359    pub span: Span,
360}
361
362#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
363pub struct NullValue {
364    pub span: Span,
365}
366
367#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
368pub struct EnumValue<'a> {
369    pub name: Name<'a>,
370}
371
372#[derive(Debug, PartialEq)]
373pub struct ListValue<'a> {
374    pub values: AstVec<'a, Value<'a>>,
375    pub span: Span,
376}
377
378#[derive(Debug, PartialEq)]
379pub struct ObjectValue<'a> {
380    pub fields: AstVec<'a, ObjectField<'a>>,
381    pub span: Span,
382}
383
384#[derive(Debug, PartialEq)]
385pub struct ObjectField<'a> {
386    pub name: Name<'a>,
387    pub value: Option<Value<'a>>,
388    pub span: Span,
389}
390
391#[derive(Debug, PartialEq)]
392pub enum Type<'a> {
393    Named(NamedType<'a>),
394    List(ListType<'a>),
395    NonNull(NonNullType<'a>),
396    Missing(Span),
397}
398
399impl Type<'_> {
400    pub fn span(&self) -> Span {
401        match self {
402            Self::Named(value) => value.name.span,
403            Self::List(value) => value.span,
404            Self::NonNull(value) => value.span,
405            Self::Missing(span) => *span,
406        }
407    }
408}
409
410#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
411pub struct NamedType<'a> {
412    pub name: Name<'a>,
413}
414
415#[derive(Debug)]
416pub struct ListType<'a> {
417    pub ty: AstBox<'a, Type<'a>>,
418    pub span: Span,
419}
420
421impl PartialEq for ListType<'_> {
422    fn eq(&self, other: &Self) -> bool {
423        self.ty.as_ref() == other.ty.as_ref() && self.span == other.span
424    }
425}
426
427#[derive(Debug)]
428pub struct NonNullType<'a> {
429    pub ty: AstBox<'a, Type<'a>>,
430    pub span: Span,
431}
432
433impl PartialEq for NonNullType<'_> {
434    fn eq(&self, other: &Self) -> bool {
435        self.ty.as_ref() == other.ty.as_ref() && self.span == other.span
436    }
437}
438
439#[derive(Debug, PartialEq)]
440pub struct SchemaDefinition<'a> {
441    pub description: Option<StringValue<'a>>,
442    pub directives: AstVec<'a, Directive<'a>>,
443    pub root_operations: AstVec<'a, RootOperationTypeDefinition<'a>>,
444    pub span: Span,
445}
446
447#[derive(Debug, PartialEq)]
448pub struct SchemaExtension<'a> {
449    pub directives: AstVec<'a, Directive<'a>>,
450    pub root_operations: AstVec<'a, RootOperationTypeDefinition<'a>>,
451    pub span: Span,
452}
453
454#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
455pub struct RootOperationTypeDefinition<'a> {
456    pub operation_type: OperationType,
457    pub named_type: NamedType<'a>,
458    pub span: Span,
459}
460
461#[derive(Debug, PartialEq)]
462pub struct DirectiveDefinition<'a> {
463    pub description: Option<StringValue<'a>>,
464    pub name: Name<'a>,
465    pub arguments: AstVec<'a, InputValueDefinition<'a>>,
466    pub repeatable: bool,
467    pub locations: AstVec<'a, DirectiveLocation<'a>>,
468    pub span: Span,
469}
470
471#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
472pub struct DirectiveLocation<'a> {
473    pub name: &'a str,
474    pub span: Span,
475}
476
477#[derive(Debug, PartialEq)]
478pub struct ScalarTypeDefinition<'a> {
479    pub description: Option<StringValue<'a>>,
480    pub name: Name<'a>,
481    pub directives: AstVec<'a, Directive<'a>>,
482    pub span: Span,
483}
484
485#[derive(Debug, PartialEq)]
486pub struct ScalarTypeExtension<'a> {
487    pub name: Name<'a>,
488    pub directives: AstVec<'a, Directive<'a>>,
489    pub span: Span,
490}
491
492#[derive(Debug, PartialEq)]
493pub struct ObjectTypeDefinition<'a> {
494    pub description: Option<StringValue<'a>>,
495    pub name: Name<'a>,
496    pub interfaces: AstVec<'a, NamedType<'a>>,
497    pub directives: AstVec<'a, Directive<'a>>,
498    pub fields: AstVec<'a, FieldDefinition<'a>>,
499    pub span: Span,
500}
501
502#[derive(Debug, PartialEq)]
503pub struct ObjectTypeExtension<'a> {
504    pub name: Name<'a>,
505    pub interfaces: AstVec<'a, NamedType<'a>>,
506    pub directives: AstVec<'a, Directive<'a>>,
507    pub fields: AstVec<'a, FieldDefinition<'a>>,
508    pub span: Span,
509}
510
511#[derive(Debug, PartialEq)]
512pub struct InterfaceTypeDefinition<'a> {
513    pub description: Option<StringValue<'a>>,
514    pub name: Name<'a>,
515    pub interfaces: AstVec<'a, NamedType<'a>>,
516    pub directives: AstVec<'a, Directive<'a>>,
517    pub fields: AstVec<'a, FieldDefinition<'a>>,
518    pub span: Span,
519}
520
521#[derive(Debug, PartialEq)]
522pub struct InterfaceTypeExtension<'a> {
523    pub name: Name<'a>,
524    pub interfaces: AstVec<'a, NamedType<'a>>,
525    pub directives: AstVec<'a, Directive<'a>>,
526    pub fields: AstVec<'a, FieldDefinition<'a>>,
527    pub span: Span,
528}
529
530#[derive(Debug, PartialEq)]
531pub struct UnionTypeDefinition<'a> {
532    pub description: Option<StringValue<'a>>,
533    pub name: Name<'a>,
534    pub directives: AstVec<'a, Directive<'a>>,
535    pub members: AstVec<'a, NamedType<'a>>,
536    pub span: Span,
537}
538
539#[derive(Debug, PartialEq)]
540pub struct UnionTypeExtension<'a> {
541    pub name: Name<'a>,
542    pub directives: AstVec<'a, Directive<'a>>,
543    pub members: AstVec<'a, NamedType<'a>>,
544    pub span: Span,
545}
546
547#[derive(Debug, PartialEq)]
548pub struct EnumTypeDefinition<'a> {
549    pub description: Option<StringValue<'a>>,
550    pub name: Name<'a>,
551    pub directives: AstVec<'a, Directive<'a>>,
552    pub values: AstVec<'a, EnumValueDefinition<'a>>,
553    pub span: Span,
554}
555
556#[derive(Debug, PartialEq)]
557pub struct EnumTypeExtension<'a> {
558    pub name: Name<'a>,
559    pub directives: AstVec<'a, Directive<'a>>,
560    pub values: AstVec<'a, EnumValueDefinition<'a>>,
561    pub span: Span,
562}
563
564#[derive(Debug, PartialEq)]
565pub struct EnumValueDefinition<'a> {
566    pub description: Option<StringValue<'a>>,
567    pub value: EnumValue<'a>,
568    pub directives: AstVec<'a, Directive<'a>>,
569    pub span: Span,
570}
571
572#[derive(Debug, PartialEq)]
573pub struct InputObjectTypeDefinition<'a> {
574    pub description: Option<StringValue<'a>>,
575    pub name: Name<'a>,
576    pub directives: AstVec<'a, Directive<'a>>,
577    pub fields: AstVec<'a, InputValueDefinition<'a>>,
578    pub span: Span,
579}
580
581#[derive(Debug, PartialEq)]
582pub struct InputObjectTypeExtension<'a> {
583    pub name: Name<'a>,
584    pub directives: AstVec<'a, Directive<'a>>,
585    pub fields: AstVec<'a, InputValueDefinition<'a>>,
586    pub span: Span,
587}
588
589#[derive(Debug, PartialEq)]
590pub struct FieldDefinition<'a> {
591    pub description: Option<StringValue<'a>>,
592    pub name: Name<'a>,
593    pub arguments: AstVec<'a, InputValueDefinition<'a>>,
594    pub ty: Option<Type<'a>>,
595    pub directives: AstVec<'a, Directive<'a>>,
596    pub span: Span,
597}
598
599#[derive(Debug, PartialEq)]
600pub struct InputValueDefinition<'a> {
601    pub description: Option<StringValue<'a>>,
602    pub name: Name<'a>,
603    pub ty: Option<Type<'a>>,
604    pub default_value: Option<Value<'a>>,
605    pub directives: AstVec<'a, Directive<'a>>,
606    pub span: Span,
607}