bluejay_validator/executable/document/rules/
fragment_spread_target_defined.rs

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