Skip to main content

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