bluejay_validator/executable/document/rules/
argument_names.rs1use crate::executable::{
2 document::{ArgumentError, Error, Path, Rule, Visitor},
3 Cache,
4};
5use bluejay_core::definition::{
6 DirectiveDefinition, FieldDefinition, InputValueDefinition, SchemaDefinition,
7};
8use bluejay_core::executable::{ExecutableDocument, Field};
9use bluejay_core::{Argument, AsIter, Directive};
10
11pub struct ArgumentNames<'a, E: ExecutableDocument, S: SchemaDefinition> {
12 schema_definition: &'a S,
13 errors: Vec<Error<'a, E, S>>,
14}
15
16impl<'a, E: ExecutableDocument + 'a, S: SchemaDefinition + 'a> ArgumentNames<'a, E, S> {
17 fn visit_directive<
18 const CONST: bool,
19 F: Fn(ArgumentError<'a, CONST, E, S>) -> Error<'a, E, S>,
20 >(
21 &mut self,
22 directive: &'a <E as ExecutableDocument>::Directive<CONST>,
23 build_error: F,
24 ) {
25 if let Some((arguments, directive_definition)) = directive.arguments().zip(
26 self.schema_definition
27 .get_directive_definition(directive.name()),
28 ) {
29 self.visit_arguments(
30 Some(arguments),
31 directive_definition.arguments_definition(),
32 |argument| {
33 build_error(ArgumentError::ArgumentDoesNotExistOnDirective {
34 argument,
35 directive_definition,
36 })
37 },
38 )
39 }
40 }
41
42 fn visit_arguments<const CONST: bool, F: Fn(&'a E::Argument<CONST>) -> Error<'a, E, S>>(
43 &mut self,
44 arguments: Option<&'a E::Arguments<CONST>>,
45 arguments_definition: Option<&'a S::ArgumentsDefinition>,
46 build_error: F,
47 ) {
48 if let Some(arguments) = arguments {
49 self.errors.extend(arguments.iter().filter_map(|argument| {
50 let argument_definition = arguments_definition.and_then(|arguments_definition| {
51 arguments_definition
52 .iter()
53 .find(|ivd| ivd.name() == argument.name())
54 });
55 argument_definition.is_none().then(|| build_error(argument))
56 }))
57 }
58 }
59}
60
61impl<'a, E: ExecutableDocument + 'a, S: SchemaDefinition + 'a> Visitor<'a, E, S>
62 for ArgumentNames<'a, E, S>
63{
64 fn new(_: &'a E, schema_definition: &'a S, _: &'a Cache<'a, E, S>) -> Self {
65 Self {
66 schema_definition,
67 errors: Vec::new(),
68 }
69 }
70
71 fn visit_field(
72 &mut self,
73 field: &'a <E as ExecutableDocument>::Field,
74 field_definition: &'a S::FieldDefinition,
75 _: &Path<'a, E>,
76 ) {
77 self.visit_arguments(
78 field.arguments(),
79 field_definition.arguments_definition(),
80 |argument| {
81 Error::InvalidVariableArgument(ArgumentError::ArgumentDoesNotExistOnField {
82 argument,
83 field_definition,
84 })
85 },
86 )
87 }
88
89 fn visit_variable_directive(
90 &mut self,
91 directive: &'a <E as ExecutableDocument>::Directive<false>,
92 _: bluejay_core::definition::DirectiveLocation,
93 ) {
94 self.visit_directive(directive, Error::InvalidVariableArgument)
95 }
96
97 fn visit_const_directive(
98 &mut self,
99 directive: &'a <E as ExecutableDocument>::Directive<true>,
100 _: bluejay_core::definition::DirectiveLocation,
101 ) {
102 self.visit_directive(directive, Error::InvalidConstArgument)
103 }
104}
105
106impl<'a, E: ExecutableDocument + 'a, S: SchemaDefinition + 'a> Rule<'a, E, S>
107 for ArgumentNames<'a, E, S>
108{
109 type Error = Error<'a, E, S>;
110 type Errors = std::vec::IntoIter<Error<'a, E, S>>;
111
112 fn into_errors(self) -> Self::Errors {
113 self.errors.into_iter()
114 }
115}