bluejay_validator/executable/document/rules/
fragment_spread_target_defined.rs1use crate::executable::{
2 document::{Error, Path, Rule, Visitor},
3 Cache,
4};
5use bluejay_core::definition::{SchemaDefinition, TypeDefinitionReference};
6use bluejay_core::executable::{ExecutableDocument, FragmentDefinition, FragmentSpread};
7use std::collections::HashSet;
8
9pub struct FragmentSpreadTargetDefined<'a, E: ExecutableDocument, S: SchemaDefinition> {
10 errors: Vec<Error<'a, E, S>>,
11 fragment_definition_names: HashSet<&'a str>,
12}
13
14impl<'a, E: ExecutableDocument, S: SchemaDefinition> Visitor<'a, E, S>
15 for FragmentSpreadTargetDefined<'a, E, S>
16{
17 fn new(executable_document: &'a E, _: &'a S, _: &'a Cache<'a, E, S>) -> Self {
18 Self {
19 errors: Vec::new(),
20 fragment_definition_names: HashSet::from_iter(
21 executable_document
22 .fragment_definitions()
23 .map(FragmentDefinition::name),
24 ),
25 }
26 }
27
28 fn visit_fragment_spread(
29 &mut self,
30 fragment_spread: &'a <E as ExecutableDocument>::FragmentSpread,
31 _scoped_type: TypeDefinitionReference<'a, S::TypeDefinition>,
32 _path: &Path<'a, E>,
33 ) {
34 if !self
35 .fragment_definition_names
36 .contains(fragment_spread.name())
37 {
38 self.errors
39 .push(Error::FragmentSpreadTargetUndefined { fragment_spread });
40 }
41 }
42}
43
44impl<'a, E: ExecutableDocument + 'a, S: SchemaDefinition + 'a> Rule<'a, E, S>
45 for FragmentSpreadTargetDefined<'a, E, S>
46{
47 type Error = Error<'a, E, S>;
48 type Errors = std::vec::IntoIter<Error<'a, E, S>>;
49
50 fn into_errors(self) -> Self::Errors {
51 self.errors.into_iter()
52 }
53}