bluejay_validator/executable/document/error/
argument_error.rs

1use bluejay_core::definition::{
2    DirectiveDefinition, FieldDefinition, InputValueDefinition, SchemaDefinition,
3};
4use bluejay_core::executable::ExecutableDocument;
5#[cfg(feature = "parser-integration")]
6use bluejay_parser::{
7    ast::executable::ExecutableDocument as ParserExecutableDocument,
8    error::{Annotation, Error as ParserError},
9    HasSpan,
10};
11use itertools::Itertools;
12
13pub enum ArgumentError<'a, const CONST: bool, E: ExecutableDocument, S: SchemaDefinition> {
14    NonUniqueArgumentNames {
15        arguments: Vec<&'a E::Argument<CONST>>,
16        name: &'a str,
17    },
18    ArgumentDoesNotExistOnField {
19        argument: &'a E::Argument<CONST>,
20        field_definition: &'a S::FieldDefinition,
21    },
22    ArgumentDoesNotExistOnDirective {
23        argument: &'a E::Argument<CONST>,
24        directive_definition: &'a S::DirectiveDefinition,
25    },
26    DirectiveMissingRequiredArguments {
27        directive: &'a E::Directive<CONST>,
28        directive_definition: &'a S::DirectiveDefinition,
29        missing_argument_definitions: Vec<&'a S::InputValueDefinition>,
30    },
31    FieldMissingRequiredArguments {
32        field: &'a E::Field,
33        field_definition: &'a S::FieldDefinition,
34        missing_argument_definitions: Vec<&'a S::InputValueDefinition>,
35    },
36}
37
38#[cfg(feature = "parser-integration")]
39impl<'a, const CONST: bool, S: SchemaDefinition>
40    From<ArgumentError<'a, CONST, ParserExecutableDocument<'a>, S>> for ParserError
41{
42    fn from(value: ArgumentError<'a, CONST, ParserExecutableDocument<'a>, S>) -> Self {
43        match value {
44            ArgumentError::NonUniqueArgumentNames { arguments, name } => Self::new(
45                format!("Multiple arguments with name `{name}`"),
46                None,
47                arguments
48                    .into_iter()
49                    .map(|argument| {
50                        Annotation::new(
51                            format!("Argument with name `{name}`"),
52                            argument.name().span().clone(),
53                        )
54                    })
55                    .collect(),
56            ),
57            ArgumentError::ArgumentDoesNotExistOnField {
58                argument,
59                field_definition,
60            } => Self::new(
61                format!(
62                    "Field `{}` does not define an argument named `{}`",
63                    field_definition.name(),
64                    argument.name().as_ref(),
65                ),
66                Some(Annotation::new(
67                    "No argument definition with this name",
68                    argument.name().span().clone(),
69                )),
70                Vec::new(),
71            ),
72            ArgumentError::ArgumentDoesNotExistOnDirective {
73                argument,
74                directive_definition,
75            } => Self::new(
76                format!(
77                    "Directive `{}` does not define an argument named `{}`",
78                    directive_definition.name(),
79                    argument.name().as_ref(),
80                ),
81                Some(Annotation::new(
82                    "No argument definition with this name",
83                    argument.name().span().clone(),
84                )),
85                Vec::new(),
86            ),
87            ArgumentError::DirectiveMissingRequiredArguments {
88                directive,
89                missing_argument_definitions,
90                ..
91            } => {
92                let missing_argument_names = missing_argument_definitions
93                    .into_iter()
94                    .map(InputValueDefinition::name)
95                    .join(", ");
96                Self::new(
97                    format!(
98                        "Directive `{}` missing argument(s): {missing_argument_names}",
99                        directive.name().as_ref(),
100                    ),
101                    Some(Annotation::new(
102                        format!("Missing argument(s): {missing_argument_names}"),
103                        directive.span().clone(),
104                    )),
105                    Vec::new(),
106                )
107            }
108            ArgumentError::FieldMissingRequiredArguments {
109                field,
110                field_definition: _,
111                missing_argument_definitions,
112            } => {
113                let missing_argument_names = missing_argument_definitions
114                    .into_iter()
115                    .map(InputValueDefinition::name)
116                    .join(", ");
117                let span = match field.arguments() {
118                    Some(arguments) => field.name().span().merge(arguments.span()),
119                    None => field.name().span().clone(),
120                };
121                Self::new(
122                    format!(
123                        "Field `{}` missing argument(s): {missing_argument_names}",
124                        field.response_key()
125                    ),
126                    Some(Annotation::new(
127                        format!("Missing argument(s): {missing_argument_names}"),
128                        span,
129                    )),
130                    Vec::new(),
131                )
132            }
133        }
134    }
135}