use crate::executable::{operation::VariableValues, Cache};
use bluejay_core::definition::{SchemaDefinition, TypeDefinitionReference};
use bluejay_core::executable::ExecutableDocument;
pub trait Visitor<'a, E: ExecutableDocument, S: SchemaDefinition, V: VariableValues> {
type ExtraInfo;
fn new(
operation_definition: &'a E::OperationDefinition,
schema_definition: &'a S,
variable_values: &'a V,
cache: &'a Cache<'a, E, S>,
extra_info: Self::ExtraInfo,
) -> Self;
#[allow(unused_variables)]
fn visit_variable_argument(
&mut self,
argument: &'a E::Argument<false>,
_input_value_definition: &'a S::InputValueDefinition,
) {
}
#[allow(unused_variables)]
fn visit_field(
&mut self,
field: &'a E::Field,
field_definition: &'a S::FieldDefinition,
scoped_type: TypeDefinitionReference<'a, S::TypeDefinition>,
included: bool,
) {
}
#[allow(unused_variables)]
fn leave_field(
&mut self,
field: &'a <E as ExecutableDocument>::Field,
field_definition: &'a S::FieldDefinition,
scoped_type: TypeDefinitionReference<'a, S::TypeDefinition>,
included: bool,
) {
}
#[allow(unused_variables)]
fn visit_variable_definition(&mut self, variable_definition: &'a E::VariableDefinition) {}
}
macro_rules! impl_visitor {
($n:literal) => {
seq_macro::seq!(N in 0..$n {
#[warn(clippy::missing_trait_methods)]
impl<'a, E: ExecutableDocument, S: SchemaDefinition, V: VariableValues, #(T~N: Visitor<'a, E, S, V>,)*> Visitor<'a, E, S, V> for (#(T~N,)*) {
type ExtraInfo = (#(<T~N as Visitor<'a, E, S, V>>::ExtraInfo,)*);
fn new(
operation_definition: &'a E::OperationDefinition,
schema_definition: &'a S,
variable_values: &'a V,
cache: &'a Cache<'a, E, S>,
extra_info: Self::ExtraInfo
) -> Self {
let ( #(extra_info~N,)* ) = extra_info;
(
#(T~N::new(
operation_definition,
schema_definition,
variable_values,
cache,
extra_info~N
),)*
)
}
fn visit_field(
&mut self,
field: &'a E::Field,
field_definition: &'a S::FieldDefinition,
owner_type: TypeDefinitionReference<'a, S::TypeDefinition>,
included: bool,
) {
#(self.N.visit_field(field, field_definition, owner_type, included);)*
}
fn leave_field(
&mut self,
field: &'a <E as ExecutableDocument>::Field,
field_definition: &'a S::FieldDefinition,
owner_type: TypeDefinitionReference<'a, S::TypeDefinition>,
included: bool,
) {
#(self.N.leave_field(field, field_definition, owner_type, included);)*
}
fn visit_variable_definition(&mut self, variable_definition: &'a E::VariableDefinition) {
#(self.N.visit_variable_definition(variable_definition);)*
}
fn visit_variable_argument(&mut self, argument: &'a E::Argument<false>, input_value_definition: &'a S::InputValueDefinition) {
#(self.N.visit_variable_argument(argument, input_value_definition);)*
}
}
});
}
}
seq_macro::seq!(N in 2..=10 {
impl_visitor!(N);
});