bluejay_validator/executable/document/error/
argument_error.rs1use 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}