bluejay_validator/executable/document/rules/
argument_uniqueness.rs1use crate::executable::{
2 document::{ArgumentError, Error, Path, Rule, Visitor},
3 Cache,
4};
5use crate::utils::duplicates;
6use bluejay_core::definition::SchemaDefinition;
7use bluejay_core::executable::{ExecutableDocument, Field};
8use bluejay_core::{Argument, AsIter, Directive};
9
10pub struct ArgumentUniqueness<'a, E: ExecutableDocument, S: SchemaDefinition> {
11 errors: Vec<Error<'a, E, S>>,
12}
13
14impl<'a, E: ExecutableDocument + 'a, S: SchemaDefinition + 'a> ArgumentUniqueness<'a, E, S> {
15 fn visit_arguments<
16 const CONST: bool,
17 F: Fn(ArgumentError<'a, CONST, E, S>) -> Error<'a, E, S>,
18 >(
19 &mut self,
20 arguments: Option<&'a E::Arguments<CONST>>,
21 build_error: F,
22 ) {
23 if let Some(arguments) = arguments {
24 self.errors
25 .extend(
26 duplicates(arguments.iter(), Argument::name).map(|(name, arguments)| {
27 build_error(ArgumentError::NonUniqueArgumentNames { name, arguments })
28 }),
29 );
30 }
31 }
32}
33
34impl<'a, E: ExecutableDocument + 'a, S: SchemaDefinition + 'a> Visitor<'a, E, S>
35 for ArgumentUniqueness<'a, E, S>
36{
37 fn new(_: &'a E, _: &'a S, _: &'a Cache<'a, E, S>) -> Self {
38 Self { errors: Vec::new() }
39 }
40
41 fn visit_field(
42 &mut self,
43 field: &'a <E as ExecutableDocument>::Field,
44 _: &'a S::FieldDefinition,
45 _: &Path<'a, E>,
46 ) {
47 self.visit_arguments(field.arguments(), Error::InvalidVariableArgument)
48 }
49
50 fn visit_variable_directive(
51 &mut self,
52 directive: &'a <E as ExecutableDocument>::Directive<false>,
53 _: bluejay_core::definition::DirectiveLocation,
54 ) {
55 self.visit_arguments(directive.arguments(), Error::InvalidVariableArgument)
56 }
57
58 fn visit_const_directive(
59 &mut self,
60 directive: &'a <E as ExecutableDocument>::Directive<true>,
61 _: bluejay_core::definition::DirectiveLocation,
62 ) {
63 self.visit_arguments(directive.arguments(), Error::InvalidConstArgument)
64 }
65}
66
67impl<'a, E: ExecutableDocument + 'a, S: SchemaDefinition + 'a> Rule<'a, E, S>
68 for ArgumentUniqueness<'a, E, S>
69{
70 type Error = Error<'a, E, S>;
71 type Errors = std::vec::IntoIter<Error<'a, E, S>>;
72
73 fn into_errors(self) -> Self::Errors {
74 self.errors.into_iter()
75 }
76}