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