bluejay_validator/executable/document/rules/
leaf_field_selections.rs

1use crate::executable::{
2    document::{Error, Path, Rule, Visitor},
3    Cache,
4};
5use bluejay_core::definition::{FieldDefinition, OutputType, SchemaDefinition};
6use bluejay_core::executable::{ExecutableDocument, Field};
7
8pub struct LeafFieldSelections<'a, E: ExecutableDocument, S: SchemaDefinition> {
9    schema_definition: &'a S,
10    errors: Vec<Error<'a, E, S>>,
11}
12
13impl<'a, E: ExecutableDocument + 'a, S: SchemaDefinition + 'a> Visitor<'a, E, S>
14    for LeafFieldSelections<'a, E, S>
15{
16    fn new(_: &'a E, schema_definition: &'a S, _: &'a Cache<'a, E, S>) -> Self {
17        Self {
18            schema_definition,
19            errors: Vec::new(),
20        }
21    }
22
23    fn visit_field(
24        &mut self,
25        field: &'a <E as ExecutableDocument>::Field,
26        field_definition: &'a S::FieldDefinition,
27        _: &Path<'a, E>,
28    ) {
29        let r#type = field_definition.r#type();
30        if r#type.base(self.schema_definition).is_scalar_or_enum() {
31            if let Some(selection_set) = field.selection_set() {
32                self.errors.push(Error::LeafFieldSelectionNotEmpty {
33                    selection_set,
34                    r#type,
35                });
36            }
37        } else if field.selection_set().is_none() {
38            self.errors
39                .push(Error::NonLeafFieldSelectionEmpty { field, r#type });
40        }
41    }
42}
43
44impl<'a, E: ExecutableDocument + 'a, S: SchemaDefinition + 'a> Rule<'a, E, S>
45    for LeafFieldSelections<'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}