bluejay_parser/ast/definition/
definition_document.rs

1use crate::ast::definition::{
2    directive_definition::BuiltinDirectiveDefinition, BaseInputType, BaseOutputType, Context,
3    CustomScalarTypeDefinition, DefaultContext, DirectiveDefinition, Directives,
4    EnumTypeDefinition, ExplicitSchemaDefinition, FieldsDefinition, InputObjectTypeDefinition,
5    InputValueDefinition, InterfaceImplementations, InterfaceTypeDefinition, ObjectTypeDefinition,
6    SchemaDefinition, TypeDefinition, UnionTypeDefinition,
7};
8use crate::ast::{DepthLimiter, FromTokens, Parse, ParseError, Tokens};
9use crate::Error;
10use bluejay_core::definition::{prelude::*, HasDirectives};
11use bluejay_core::{
12    AsIter, BuiltinScalarDefinition, Directive as _, IntoEnumIterator, OperationType,
13};
14use std::collections::btree_map::Entry;
15use std::collections::{BTreeMap, HashMap, HashSet};
16
17mod definition_document_error;
18use definition_document_error::DefinitionDocumentError;
19
20#[derive(Debug)]
21pub struct DefinitionDocument<'a, C: Context = DefaultContext> {
22    schema_definitions: Vec<ExplicitSchemaDefinition<'a, C>>,
23    directive_definitions: Vec<DirectiveDefinition<'a, C>>,
24    type_definitions: Vec<TypeDefinition<'a, C>>,
25}
26
27#[derive(Debug)]
28pub struct ImplicitSchemaDefinition<'a, C: Context> {
29    query: &'a ObjectTypeDefinition<'a, C>,
30    mutation: Option<&'a ObjectTypeDefinition<'a, C>>,
31    subscription: Option<&'a ObjectTypeDefinition<'a, C>>,
32}
33
34type ExplicitSchemaDefinitionWithRootTypes<'a, C> = (
35    &'a ExplicitSchemaDefinition<'a, C>,
36    &'a ObjectTypeDefinition<'a, C>,
37    Option<&'a ObjectTypeDefinition<'a, C>>,
38    Option<&'a ObjectTypeDefinition<'a, C>>,
39);
40
41impl<'a, C: Context> Parse<'a> for DefinitionDocument<'a, C> {
42    fn parse_from_tokens(
43        mut tokens: impl Tokens<'a>,
44        max_depth: usize,
45    ) -> Result<Self, Vec<Error>> {
46        let mut instance: Self = Self::new();
47        let mut errors = Vec::new();
48        let mut last_pass_had_error = false;
49
50        loop {
51            match Self::next_definition_identifier(&mut tokens) {
52                Some(CustomScalarTypeDefinition::<C>::SCALAR_IDENTIFIER) => {
53                    Self::parse_definition::<_, CustomScalarTypeDefinition<C>>(
54                        &mut instance.type_definitions,
55                        &mut tokens,
56                        &mut errors,
57                        &mut last_pass_had_error,
58                        max_depth,
59                    )
60                }
61                Some(ObjectTypeDefinition::<C>::TYPE_IDENTIFIER) => {
62                    Self::parse_definition::<_, ObjectTypeDefinition<C>>(
63                        &mut instance.type_definitions,
64                        &mut tokens,
65                        &mut errors,
66                        &mut last_pass_had_error,
67                        max_depth,
68                    )
69                }
70                Some(InputObjectTypeDefinition::<C>::INPUT_IDENTIFIER) => {
71                    Self::parse_definition::<_, InputObjectTypeDefinition<C>>(
72                        &mut instance.type_definitions,
73                        &mut tokens,
74                        &mut errors,
75                        &mut last_pass_had_error,
76                        max_depth,
77                    )
78                }
79                Some(EnumTypeDefinition::<C>::ENUM_IDENTIFIER) => {
80                    Self::parse_definition::<_, EnumTypeDefinition<C>>(
81                        &mut instance.type_definitions,
82                        &mut tokens,
83                        &mut errors,
84                        &mut last_pass_had_error,
85                        max_depth,
86                    )
87                }
88                Some(UnionTypeDefinition::<C>::UNION_IDENTIFIER) => {
89                    Self::parse_definition::<_, UnionTypeDefinition<C>>(
90                        &mut instance.type_definitions,
91                        &mut tokens,
92                        &mut errors,
93                        &mut last_pass_had_error,
94                        max_depth,
95                    )
96                }
97                Some(InterfaceTypeDefinition::<C>::INTERFACE_IDENTIFIER) => {
98                    Self::parse_definition::<_, InterfaceTypeDefinition<C>>(
99                        &mut instance.type_definitions,
100                        &mut tokens,
101                        &mut errors,
102                        &mut last_pass_had_error,
103                        max_depth,
104                    )
105                }
106                Some(ExplicitSchemaDefinition::<C>::SCHEMA_IDENTIFIER) => {
107                    Self::parse_definition::<_, ExplicitSchemaDefinition<C>>(
108                        &mut instance.schema_definitions,
109                        &mut tokens,
110                        &mut errors,
111                        &mut last_pass_had_error,
112                        max_depth,
113                    )
114                }
115                Some(DirectiveDefinition::<C>::DIRECTIVE_IDENTIFIER) => {
116                    Self::parse_definition::<_, DirectiveDefinition<C>>(
117                        &mut instance.directive_definitions,
118                        &mut tokens,
119                        &mut errors,
120                        &mut last_pass_had_error,
121                        max_depth,
122                    )
123                }
124                _ => {
125                    if let Some(token) = tokens.next() {
126                        if !last_pass_had_error {
127                            errors.push(ParseError::UnexpectedToken { span: token.into() });
128                            last_pass_had_error = true;
129                        }
130                    } else {
131                        break;
132                    }
133                }
134            }
135        }
136
137        let lex_errors = tokens.into_errors();
138
139        let errors = if lex_errors.is_empty() {
140            if errors.is_empty() && instance.is_empty() {
141                vec![ParseError::EmptyDocument.into()]
142            } else {
143                errors.into_iter().map(Into::into).collect()
144            }
145        } else {
146            lex_errors.into_iter().map(Into::into).collect()
147        };
148
149        if errors.is_empty() {
150            instance.insert_builtin_scalar_definitions();
151            instance.insert_builtin_directive_definitions();
152            instance.add_query_root_fields();
153            Ok(instance)
154        } else {
155            Err(errors)
156        }
157    }
158}
159
160impl<'a, C: Context> DefinitionDocument<'a, C> {
161    fn new() -> Self {
162        Self {
163            schema_definitions: Vec::new(),
164            directive_definitions: Vec::new(),
165            type_definitions: vec![
166                ObjectTypeDefinition::__schema().into(),
167                ObjectTypeDefinition::__type().into(),
168                ObjectTypeDefinition::__field().into(),
169                ObjectTypeDefinition::__input_value().into(),
170                ObjectTypeDefinition::__enum_value().into(),
171                ObjectTypeDefinition::__directive().into(),
172                EnumTypeDefinition::__type_kind().into(),
173                EnumTypeDefinition::__directive_location().into(),
174            ],
175        }
176    }
177
178    fn parse_definition<'b, S, T: FromTokens<'b> + Into<S>>(
179        definitions: &mut Vec<S>,
180        tokens: &mut impl Tokens<'b>,
181        errors: &mut Vec<ParseError>,
182        last_pass_had_error: &mut bool,
183        max_depth: usize,
184    ) {
185        match T::from_tokens(tokens, DepthLimiter::new(max_depth)) {
186            Ok(definition) => {
187                definitions.push(definition.into());
188                *last_pass_had_error = false;
189            }
190            Err(err) => {
191                if !*last_pass_had_error {
192                    errors.push(err);
193                    *last_pass_had_error = true;
194                }
195            }
196        }
197    }
198
199    /// Inserts builtin scalars only for type names that have not already been parsed
200    /// to allow overriding of builtin scalars
201    fn insert_builtin_scalar_definitions(&mut self) {
202        let mut builtin_scalars_by_name: HashMap<&str, BuiltinScalarDefinition> =
203            HashMap::from_iter(BuiltinScalarDefinition::iter().map(|bstd| (bstd.name(), bstd)));
204
205        self.type_definitions.iter().for_each(|td| {
206            builtin_scalars_by_name.remove(td.name());
207        });
208
209        self.type_definitions.extend(
210            builtin_scalars_by_name
211                .into_values()
212                .map(TypeDefinition::BuiltinScalar),
213        );
214    }
215
216    /// Inserts builtin directive definitions only for type names that have not already been parsed
217    /// to allow optional explicit definition of builtin definitions (since they are optional)
218    fn insert_builtin_directive_definitions(&mut self) {
219        let mut builtin_directive_definitions_by_name: HashMap<&str, BuiltinDirectiveDefinition> =
220            HashMap::from_iter(
221                BuiltinDirectiveDefinition::iter()
222                    .map(|bdd: BuiltinDirectiveDefinition| (bdd.into(), bdd)),
223            );
224
225        self.directive_definitions().iter().for_each(|dd| {
226            builtin_directive_definitions_by_name.remove(dd.name());
227        });
228
229        self.directive_definitions.extend(
230            builtin_directive_definitions_by_name
231                .into_values()
232                .map(DirectiveDefinition::from),
233        );
234    }
235
236    fn add_query_root_fields(&mut self) {
237        let explicit_query_roots: HashSet<&str> = HashSet::from_iter(
238            self.schema_definitions
239                .iter()
240                .flat_map(|schema_definition| {
241                    schema_definition
242                        .root_operation_type_definitions()
243                        .iter()
244                        .filter(|rotd| rotd.operation_type() == OperationType::Query)
245                        .map(|rotd| rotd.name())
246                }),
247        );
248
249        self.type_definitions
250            .iter_mut()
251            .for_each(|type_definition| {
252                if let TypeDefinition::Object(otd) = type_definition {
253                    let name = otd.name().as_ref();
254                    if name == "Query" || explicit_query_roots.contains(name) {
255                        otd.add_query_root_fields();
256                    }
257                }
258            })
259    }
260
261    fn is_empty(&self) -> bool {
262        self.definition_count() == 0
263    }
264
265    fn next_definition_identifier(tokens: &mut impl Tokens<'a>) -> Option<&str> {
266        let idx_to_peek = if tokens.peek_string_value(0) { 1 } else { 0 };
267        tokens.peek_name(idx_to_peek).map(AsRef::as_ref)
268    }
269
270    pub fn definition_count(&self) -> usize {
271        self.directive_definitions
272            .iter()
273            .filter(|dd| !dd.is_builtin())
274            .count()
275            + self.schema_definitions.len()
276            + self
277                .type_definitions
278                .iter()
279                .filter(|td| !td.as_ref().is_builtin())
280                .count()
281    }
282
283    pub fn directive_definitions(&self) -> &[DirectiveDefinition<'a, C>] {
284        &self.directive_definitions
285    }
286
287    fn index_directive_definitions(
288        &'a self,
289        errors: &mut Vec<DefinitionDocumentError<'a, C>>,
290    ) -> BTreeMap<&'a str, &'a DirectiveDefinition<'a, C>> {
291        let mut indexed: BTreeMap<&str, &DirectiveDefinition<'a, C>> = BTreeMap::new();
292        let mut duplicates: BTreeMap<&str, Vec<&DirectiveDefinition<'a, C>>> = BTreeMap::new();
293
294        self.directive_definitions
295            .iter()
296            .for_each(|directive_definition| {
297                match indexed.entry(directive_definition.name().as_ref()) {
298                    Entry::Vacant(entry) => {
299                        entry.insert(directive_definition);
300                    }
301                    Entry::Occupied(entry) => {
302                        duplicates
303                            .entry(directive_definition.name().as_ref())
304                            .or_insert_with(|| vec![entry.get()])
305                            .push(directive_definition);
306                    }
307                }
308            });
309
310        errors.extend(duplicates.into_iter().map(|(name, definitions)| {
311            DefinitionDocumentError::DuplicateDirectiveDefinitions { name, definitions }
312        }));
313
314        indexed
315    }
316
317    fn index_type_definitions(
318        &'a self,
319        errors: &mut Vec<DefinitionDocumentError<'a, C>>,
320    ) -> BTreeMap<&'a str, &'a TypeDefinition<'a, C>> {
321        let mut indexed: BTreeMap<&str, &TypeDefinition<'a, C>> = BTreeMap::new();
322        let mut duplicates: BTreeMap<&str, Vec<&TypeDefinition<'a, C>>> = BTreeMap::new();
323
324        self.type_definitions
325            .iter()
326            .for_each(|td| match indexed.entry(td.name()) {
327                Entry::Vacant(entry) => {
328                    entry.insert(td);
329                }
330                Entry::Occupied(entry) => {
331                    duplicates
332                        .entry(td.name())
333                        .or_insert_with(|| vec![entry.get()])
334                        .push(td);
335                }
336            });
337
338        errors.extend(duplicates.into_iter().map(|(name, definitions)| {
339            DefinitionDocumentError::DuplicateTypeDefinitions { name, definitions }
340        }));
341
342        indexed
343    }
344
345    fn implicit_schema_definition(
346        indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
347    ) -> Result<Option<ImplicitSchemaDefinition<'a, C>>, Vec<DefinitionDocumentError<'a, C>>> {
348        let mut errors = Vec::new();
349        let query =
350            Self::implicit_root_operation_type("Query", indexed_type_definitions, &mut errors);
351        let mutation =
352            Self::implicit_root_operation_type("Mutation", indexed_type_definitions, &mut errors);
353        let subscription = Self::implicit_root_operation_type(
354            "Subscription",
355            indexed_type_definitions,
356            &mut errors,
357        );
358
359        if !errors.is_empty() {
360            return Err(errors);
361        }
362
363        if let Some(query) = query {
364            Ok(Some(ImplicitSchemaDefinition {
365                query,
366                mutation,
367                subscription,
368            }))
369        } else if mutation.is_some() || subscription.is_some() {
370            Err(vec![
371                DefinitionDocumentError::ImplicitSchemaDefinitionMissingQuery,
372            ])
373        } else {
374            Ok(None)
375        }
376    }
377
378    fn implicit_root_operation_type(
379        name: &str,
380        indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
381        errors: &mut Vec<DefinitionDocumentError<'a, C>>,
382    ) -> Option<&'a ObjectTypeDefinition<'a, C>> {
383        match indexed_type_definitions.get(name) {
384            Some(TypeDefinition::Object(o)) => Some(o),
385            Some(definition) => {
386                errors.push(
387                    DefinitionDocumentError::ImplicitRootOperationTypeNotAnObject { definition },
388                );
389                None
390            }
391            None => None,
392        }
393    }
394
395    fn explicit_schema_definition(
396        &'a self,
397        indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
398    ) -> Result<
399        Option<ExplicitSchemaDefinitionWithRootTypes<'a, C>>,
400        Vec<DefinitionDocumentError<'a, C>>,
401    > {
402        let mut errors = Vec::new();
403        if let Some(first) = self.schema_definitions.first() {
404            if self.schema_definitions.len() == 1 {
405                let query = match Self::explicit_operation_type_definition(
406                    OperationType::Query,
407                    first,
408                    indexed_type_definitions,
409                ) {
410                    Ok(query) => query,
411                    Err(err) => {
412                        errors.push(err);
413                        None
414                    }
415                };
416                let mutation = match Self::explicit_operation_type_definition(
417                    OperationType::Mutation,
418                    first,
419                    indexed_type_definitions,
420                ) {
421                    Ok(mutation) => mutation,
422                    Err(err) => {
423                        errors.push(err);
424                        None
425                    }
426                };
427                let subscription = match Self::explicit_operation_type_definition(
428                    OperationType::Subscription,
429                    first,
430                    indexed_type_definitions,
431                ) {
432                    Ok(subscription) => subscription,
433                    Err(err) => {
434                        errors.push(err);
435                        None
436                    }
437                };
438                if !errors.is_empty() {
439                    return Err(errors);
440                }
441                if let Some(query) = query {
442                    Ok(Some((first, query, mutation, subscription)))
443                } else {
444                    Err(vec![
445                        DefinitionDocumentError::ExplicitSchemaDefinitionMissingQuery {
446                            definition: first,
447                        },
448                    ])
449                }
450            } else {
451                Err(vec![
452                    DefinitionDocumentError::DuplicateExplicitSchemaDefinitions {
453                        definitions: &self.schema_definitions,
454                    },
455                ])
456            }
457        } else {
458            Ok(None)
459        }
460    }
461
462    fn explicit_operation_type_definition(
463        operation_type: OperationType,
464        explicit_schema_definition: &'a ExplicitSchemaDefinition<'a, C>,
465        indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
466    ) -> Result<Option<&'a ObjectTypeDefinition<'a, C>>, DefinitionDocumentError<'a, C>> {
467        let root_operation_type_definitions: Vec<_> = explicit_schema_definition
468            .root_operation_type_definitions()
469            .iter()
470            .filter(|rotd| rotd.operation_type() == operation_type)
471            .collect();
472
473        if let Some(first) = root_operation_type_definitions.first() {
474            if root_operation_type_definitions.len() == 1 {
475                match indexed_type_definitions.get(first.name()) {
476                    Some(TypeDefinition::Object(o)) => Ok(Some(o)),
477                    Some(_) => Err(
478                        DefinitionDocumentError::ExplicitRootOperationTypeNotAnObject {
479                            name: first.name_token(),
480                        },
481                    ),
482                    None => Err(
483                        DefinitionDocumentError::ExplicitRootOperationTypeDoesNotExist {
484                            root_operation_type_definition: first,
485                        },
486                    ),
487                }
488            } else {
489                Err(
490                    DefinitionDocumentError::DuplicateExplicitRootOperationDefinitions {
491                        operation_type,
492                        root_operation_type_definitions,
493                    },
494                )
495            }
496        } else {
497            Ok(None)
498        }
499    }
500
501    fn resolve_type_and_directive_definitions(
502        indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
503        indexed_directive_definitions: &BTreeMap<&str, &'a DirectiveDefinition<'a, C>>,
504        errors: &mut Vec<DefinitionDocumentError<'a, C>>,
505    ) {
506        indexed_type_definitions
507            .values()
508            .for_each(|type_definition| match type_definition {
509                TypeDefinition::Object(otd) => {
510                    Self::resolve_fields_definition_types_and_directives(
511                        indexed_type_definitions,
512                        indexed_directive_definitions,
513                        otd.fields_definition(),
514                        errors,
515                    );
516                    if let Some(interface_implementations) = otd.interface_implementations() {
517                        Self::resolve_interface_implementations(
518                            indexed_type_definitions,
519                            interface_implementations,
520                            errors,
521                        );
522                    }
523                    Self::resolve_directive_definitions(indexed_directive_definitions, otd, errors);
524                }
525                TypeDefinition::Interface(itd) => {
526                    Self::resolve_fields_definition_types_and_directives(
527                        indexed_type_definitions,
528                        indexed_directive_definitions,
529                        itd.fields_definition(),
530                        errors,
531                    );
532                    if let Some(interface_implementations) = itd.interface_implementations() {
533                        Self::resolve_interface_implementations(
534                            indexed_type_definitions,
535                            interface_implementations,
536                            errors,
537                        );
538                    }
539                    Self::resolve_directive_definitions(indexed_directive_definitions, itd, errors);
540                }
541                TypeDefinition::Union(utd) => {
542                    Self::resolve_fields_definition_types_and_directives(
543                        indexed_type_definitions,
544                        indexed_directive_definitions,
545                        utd.fields_definition(),
546                        errors,
547                    );
548                    utd.union_member_types().iter().for_each(|member_type| {
549                        match indexed_type_definitions.get(member_type.name().as_ref()) {
550                            Some(TypeDefinition::Object(_)) => {}
551                            Some(_) => errors.push(
552                                DefinitionDocumentError::ReferencedUnionMemberTypeIsNotAnObject {
553                                    name: member_type.name(),
554                                },
555                            ),
556                            None => {
557                                errors.push(DefinitionDocumentError::ReferencedTypeDoesNotExist {
558                                    name: member_type.name(),
559                                })
560                            }
561                        }
562                    });
563                    Self::resolve_directive_definitions(indexed_directive_definitions, utd, errors);
564                }
565                TypeDefinition::InputObject(iotd) => {
566                    Self::resolve_input_types_and_directives(
567                        indexed_type_definitions,
568                        indexed_directive_definitions,
569                        iotd.input_field_definitions().iter(),
570                        errors,
571                    );
572
573                    Self::resolve_directive_definitions(
574                        indexed_directive_definitions,
575                        iotd,
576                        errors,
577                    );
578                }
579                TypeDefinition::CustomScalar(cstd) => {
580                    Self::resolve_directive_definitions(indexed_directive_definitions, cstd, errors)
581                }
582                TypeDefinition::Enum(etd) => {
583                    Self::resolve_directive_definitions(indexed_directive_definitions, etd, errors);
584                    etd.enum_value_definitions().iter().for_each(|evd| {
585                        Self::resolve_directive_definitions(
586                            indexed_directive_definitions,
587                            evd,
588                            errors,
589                        );
590                    });
591                }
592                TypeDefinition::BuiltinScalar(_) => {}
593            });
594
595        indexed_directive_definitions
596            .values()
597            .for_each(|directive_definition| {
598                if let Some(arguments_definition) = directive_definition.arguments_definition() {
599                    Self::resolve_input_types_and_directives(
600                        indexed_type_definitions,
601                        indexed_directive_definitions,
602                        arguments_definition.iter(),
603                        errors,
604                    );
605                }
606            })
607    }
608
609    fn resolve_fields_definition_types_and_directives(
610        indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
611        indexed_directive_definitions: &BTreeMap<&str, &'a DirectiveDefinition<'a, C>>,
612        fields_definition: &'a FieldsDefinition<'a, C>,
613        errors: &mut Vec<DefinitionDocumentError<'a, C>>,
614    ) {
615        fields_definition.iter().for_each(|field_definition| {
616            let t = field_definition.r#type().base();
617            match indexed_type_definitions.get(t.name().as_ref()) {
618                Some(&td) => match BaseOutputType::core_type_from_type_definition(td) {
619                    Ok(_) => {}
620                    Err(_) => {
621                        errors.push(DefinitionDocumentError::ReferencedTypeIsNotAnOutputType {
622                            name: t.name(),
623                        })
624                    }
625                },
626                None => errors
627                    .push(DefinitionDocumentError::ReferencedTypeDoesNotExist { name: t.name() }),
628            }
629
630            if let Some(arguments_definition) = field_definition.arguments_definition() {
631                Self::resolve_input_types_and_directives(
632                    indexed_type_definitions,
633                    indexed_directive_definitions,
634                    arguments_definition.iter(),
635                    errors,
636                )
637            }
638
639            Self::resolve_directive_definitions(
640                indexed_directive_definitions,
641                field_definition,
642                errors,
643            );
644        })
645    }
646
647    fn resolve_interface_implementations(
648        indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
649        interface_impelementations: &'a InterfaceImplementations<'a, C>,
650        errors: &mut Vec<DefinitionDocumentError<'a, C>>,
651    ) {
652        interface_impelementations
653            .iter()
654            .for_each(|interface_implementation| {
655                let name = interface_implementation.interface_name();
656                match indexed_type_definitions.get(name.as_ref()) {
657                    Some(TypeDefinition::Interface(_)) => {}
658                    Some(_) => errors
659                        .push(DefinitionDocumentError::ReferencedTypeIsNotAnInterface { name }),
660                    None => {
661                        errors.push(DefinitionDocumentError::ReferencedTypeDoesNotExist { name })
662                    }
663                }
664            })
665    }
666
667    fn resolve_input_types_and_directives(
668        indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
669        indexed_directive_definitions: &BTreeMap<&str, &'a DirectiveDefinition<'a, C>>,
670        input_value_definitions: impl Iterator<Item = &'a InputValueDefinition<'a, C>>,
671        errors: &mut Vec<DefinitionDocumentError<'a, C>>,
672    ) {
673        input_value_definitions.for_each(|input_value_definition| {
674            let t = input_value_definition.r#type().base();
675            match indexed_type_definitions.get(t.name().as_ref()) {
676                Some(&td) => match BaseInputType::core_type_from_type_definition(td) {
677                    Ok(_) => {}
678                    Err(_) => {
679                        errors.push(DefinitionDocumentError::ReferencedTypeIsNotAnInputType {
680                            name: t.name(),
681                        })
682                    }
683                },
684                None => errors
685                    .push(DefinitionDocumentError::ReferencedTypeDoesNotExist { name: t.name() }),
686            }
687
688            Self::resolve_directive_definitions(
689                indexed_directive_definitions,
690                input_value_definition,
691                errors,
692            );
693        })
694    }
695
696    fn resolve_directive_definitions(
697        indexed_directive_definitions: &BTreeMap<&str, &'a DirectiveDefinition<'a, C>>,
698        subject: &'a impl HasDirectives<Directives = Directives<'a, C>>,
699        errors: &mut Vec<DefinitionDocumentError<'a, C>>,
700    ) {
701        if let Some(directives) = subject.directives() {
702            directives.iter().for_each(|directive| {
703                match indexed_directive_definitions.get(directive.name()) {
704                    Some(_) => {}
705                    None => errors.push(DefinitionDocumentError::ReferencedDirectiveDoesNotExist {
706                        directive,
707                    }),
708                }
709            })
710        }
711    }
712}
713
714impl<'a, C: Context> TryFrom<&'a DefinitionDocument<'a, C>> for SchemaDefinition<'a, C> {
715    type Error = Vec<DefinitionDocumentError<'a, C>>;
716
717    fn try_from(definition_document: &'a DefinitionDocument<'a, C>) -> Result<Self, Self::Error> {
718        let mut errors = Vec::new();
719
720        let indexed_type_definitions = definition_document.index_type_definitions(&mut errors);
721
722        let indexed_directive_definitions =
723            definition_document.index_directive_definitions(&mut errors);
724
725        DefinitionDocument::resolve_type_and_directive_definitions(
726            &indexed_type_definitions,
727            &indexed_directive_definitions,
728            &mut errors,
729        );
730
731        if !errors.is_empty() {
732            return Err(errors);
733        }
734
735        if let Some((explicit, query, mutation, subscription)) =
736            definition_document.explicit_schema_definition(&indexed_type_definitions)?
737        {
738            return Ok(Self::new(
739                indexed_type_definitions,
740                indexed_directive_definitions,
741                explicit.description(),
742                query,
743                mutation,
744                subscription,
745                explicit.directives(),
746            ));
747        }
748
749        match DefinitionDocument::implicit_schema_definition(&indexed_type_definitions)? {
750            Some(implicit) => Ok(Self::new(
751                indexed_type_definitions,
752                indexed_directive_definitions,
753                None,
754                implicit.query,
755                implicit.mutation,
756                implicit.subscription,
757                None,
758            )),
759            None => Err(vec![DefinitionDocumentError::NoSchemaDefinition]),
760        }
761    }
762}
763
764#[cfg(test)]
765mod tests {
766    use std::collections::HashSet;
767
768    use bluejay_core::{
769        definition::{
770            FieldDefinition as CoreFieldDefinition,
771            ObjectTypeDefinition as CoreObjectTypeDefinition,
772            SchemaDefinition as CoreSchemaDefinition,
773        },
774        AsIter,
775    };
776
777    use super::{DefinitionDocument, Parse, SchemaDefinition};
778
779    #[test]
780    fn test_can_be_used_owned_with_self_cell() {
781        self_cell::self_cell!(
782            struct OwnedDefinitionDocument {
783                owner: String,
784
785                #[covariant]
786                dependent: DefinitionDocument,
787            }
788        );
789
790        self_cell::self_cell!(
791            struct OwnedSchemaDefinition {
792                owner: OwnedDefinitionDocument,
793
794                #[covariant]
795                dependent: SchemaDefinition,
796            }
797        );
798
799        let source = r#"
800        """
801        Description
802        """
803        type Query {
804            foo: String!
805        }
806        "#
807        .to_string();
808
809        let owned_definition_document = OwnedDefinitionDocument::new(source, |source| {
810            DefinitionDocument::parse(source).unwrap()
811        });
812
813        let owned_schema_definition =
814            OwnedSchemaDefinition::new(owned_definition_document, |owned_definition_document| {
815                SchemaDefinition::try_from(owned_definition_document.borrow_dependent()).unwrap()
816            });
817
818        let schema_definition = owned_schema_definition.borrow_dependent();
819
820        assert_eq!("Query", schema_definition.query().name().as_str());
821    }
822
823    #[test]
824    fn smoke_test() {
825        let s = r#"
826        """
827        Description
828        """
829        type Object {
830            foo: String!
831        }
832        "#;
833
834        let document: DefinitionDocument = DefinitionDocument::parse(s).unwrap();
835
836        assert_eq!(1, document.definition_count());
837    }
838
839    #[test]
840    fn builtin_fields_and_types_test() {
841        let s = r#"
842        directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
843
844        type Query {
845            foo: String!
846        }
847
848        type Mutation {
849            foo: String!
850        }
851        "#;
852
853        let document: DefinitionDocument =
854            DefinitionDocument::parse(s).expect("Document had parse errors");
855
856        let schema_definition = SchemaDefinition::try_from(&document)
857            .expect("Could not convert document to schema definition");
858
859        let query_root_builtin_fields: HashSet<&str> = schema_definition
860            .query()
861            .fields_definition()
862            .iter()
863            .filter_map(|fd| fd.is_builtin().then_some(fd.name()))
864            .collect();
865
866        assert_eq!(
867            HashSet::from(["__typename", "__schema", "__type"]),
868            query_root_builtin_fields,
869        );
870
871        let mutation_root = schema_definition
872            .mutation()
873            .expect("Schema definition did not have a mutation root");
874
875        let mutation_root_builtin_fields: HashSet<&str> = mutation_root
876            .fields_definition()
877            .iter()
878            .filter_map(|fd| fd.is_builtin().then_some(fd.name()))
879            .collect();
880
881        assert_eq!(HashSet::from(["__typename"]), mutation_root_builtin_fields);
882
883        let directives: HashSet<&str> = schema_definition
884            .directive_definitions()
885            .map(|dd| dd.name())
886            .collect();
887
888        assert!(
889            HashSet::from(["include", "skip", "deprecated", "specifiedBy", "oneOf"])
890                .is_subset(&directives)
891        );
892
893        let builtin_types: HashSet<&str> = schema_definition
894            .type_definitions()
895            .filter_map(|td| td.is_builtin().then_some(td.name()))
896            .collect();
897
898        assert_eq!(
899            HashSet::from([
900                "__TypeKind",
901                "__DirectiveLocation",
902                "__Schema",
903                "__Type",
904                "__Field",
905                "__InputValue",
906                "__EnumValue",
907                "__Directive",
908                "String",
909                "ID",
910                "Boolean",
911                "Int",
912                "Float",
913            ]),
914            builtin_types,
915        );
916    }
917}