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