bluejay_validator/executable/operation/
visitor.rs

1use crate::executable::{operation::VariableValues, Cache};
2use bluejay_core::definition::{SchemaDefinition, TypeDefinitionReference};
3use bluejay_core::executable::ExecutableDocument;
4
5pub trait Visitor<'a, E: ExecutableDocument, S: SchemaDefinition, V: VariableValues> {
6    type ExtraInfo;
7
8    fn new(
9        operation_definition: &'a E::OperationDefinition,
10        schema_definition: &'a S,
11        variable_values: &'a V,
12        cache: &'a Cache<'a, E, S>,
13        extra_info: Self::ExtraInfo,
14    ) -> Self;
15
16    #[allow(unused_variables)]
17    fn visit_variable_argument(
18        &mut self,
19        argument: &'a E::Argument<false>,
20        _input_value_definition: &'a S::InputValueDefinition,
21    ) {
22    }
23
24    /// Visits the field. If a field is part of a fragment definition, it will be visited
25    /// every time the fragment is spread.
26    /// # Variables
27    /// - `field` is the field being visited
28    /// - `field_definition` is the definition of the field
29    /// - `scoped_type` is the type that the field definition is defined within
30    /// - `included` is true when the field is known to be included in the response
31    ///   (based on the usage of `@include` and `@skip` directives and the variable values)
32    #[allow(unused_variables)]
33    fn visit_field(
34        &mut self,
35        field: &'a E::Field,
36        field_definition: &'a S::FieldDefinition,
37        scoped_type: TypeDefinitionReference<'a, S::TypeDefinition>,
38        included: bool,
39    ) {
40    }
41
42    /// Called after the field and all of its children have been visited.
43    /// See `visit_field` for more information about the variables.
44    #[allow(unused_variables)]
45    fn leave_field(
46        &mut self,
47        field: &'a <E as ExecutableDocument>::Field,
48        field_definition: &'a S::FieldDefinition,
49        scoped_type: TypeDefinitionReference<'a, S::TypeDefinition>,
50        included: bool,
51    ) {
52    }
53
54    /// Visits the variable definition.
55    /// # Variables
56    /// - `variable_definition` is the variable definition being visited
57    #[allow(unused_variables)]
58    fn visit_variable_definition(&mut self, variable_definition: &'a E::VariableDefinition) {}
59}
60
61macro_rules! impl_visitor {
62    ($n:literal) => {
63        seq_macro::seq!(N in 0..$n {
64            #[warn(clippy::missing_trait_methods)]
65            impl<'a, E: ExecutableDocument, S: SchemaDefinition, V: VariableValues, #(T~N: Visitor<'a, E, S, V>,)*> Visitor<'a, E, S, V> for (#(T~N,)*) {
66                type ExtraInfo = (#(<T~N as Visitor<'a, E, S, V>>::ExtraInfo,)*);
67
68                fn new(
69                    operation_definition: &'a E::OperationDefinition,
70                    schema_definition: &'a S,
71                    variable_values: &'a V,
72                    cache: &'a Cache<'a, E, S>,
73                    extra_info: Self::ExtraInfo
74                ) -> Self {
75                    let ( #(extra_info~N,)* ) = extra_info;
76                    (
77                        #(T~N::new(
78                            operation_definition,
79                            schema_definition,
80                            variable_values,
81                            cache,
82                            extra_info~N
83                        ),)*
84                    )
85                }
86
87                fn visit_field(
88                    &mut self,
89                    field: &'a E::Field,
90                    field_definition: &'a S::FieldDefinition,
91                    owner_type: TypeDefinitionReference<'a, S::TypeDefinition>,
92                    included: bool,
93                ) {
94                    #(self.N.visit_field(field, field_definition, owner_type, included);)*
95                }
96
97                fn leave_field(
98                    &mut self,
99                    field: &'a <E as ExecutableDocument>::Field,
100                    field_definition: &'a S::FieldDefinition,
101                    owner_type: TypeDefinitionReference<'a, S::TypeDefinition>,
102                    included: bool,
103                ) {
104                    #(self.N.leave_field(field, field_definition, owner_type, included);)*
105                }
106
107                fn visit_variable_definition(&mut self, variable_definition: &'a E::VariableDefinition) {
108                    #(self.N.visit_variable_definition(variable_definition);)*
109                }
110
111                fn visit_variable_argument(&mut self, argument: &'a E::Argument<false>, input_value_definition: &'a S::InputValueDefinition) {
112                    #(self.N.visit_variable_argument(argument, input_value_definition);)*
113                }
114            }
115        });
116    }
117}
118
119seq_macro::seq!(N in 2..=10 {
120    impl_visitor!(N);
121});