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 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 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}