1use crate::value::input_coercion::Error as InputCoercionError;
2use bluejay_core::definition::{
3 FieldDefinition, InputType, OutputType, SchemaDefinition, TypeDefinitionReference,
4};
5use bluejay_core::executable::{ExecutableDocument, OperationDefinition, VariableType};
6use bluejay_core::{OperationType, Value};
7#[cfg(feature = "parser-integration")]
8use bluejay_parser::{
9 ast::executable::ExecutableDocument as ParserExecutableDocument,
10 error::{Annotation, Error as ParserError},
11 HasSpan,
12};
13use std::borrow::Cow;
14
15mod argument_error;
16mod directive_error;
17
18pub use argument_error::ArgumentError;
19pub use directive_error::DirectiveError;
20
21pub enum Error<'a, E: ExecutableDocument, S: SchemaDefinition> {
22 NonUniqueOperationNames {
23 name: &'a str,
24 operations: Vec<&'a E::ExplicitOperationDefinition>,
25 },
26 NotLoneAnonymousOperation {
27 anonymous_operations: Vec<&'a E::OperationDefinition>,
28 },
29 SubscriptionRootNotSingleField {
30 operation: &'a E::OperationDefinition,
31 },
32 FieldDoesNotExistOnType {
33 field: &'a E::Field,
34 r#type: TypeDefinitionReference<'a, S::TypeDefinition>,
35 },
36 OperationTypeNotDefined {
37 operation: &'a E::ExplicitOperationDefinition,
38 },
39 LeafFieldSelectionNotEmpty {
40 selection_set: &'a E::SelectionSet,
41 r#type: &'a S::OutputType,
42 },
43 NonLeafFieldSelectionEmpty {
44 field: &'a E::Field,
45 r#type: &'a S::OutputType,
46 },
47 NonUniqueFragmentDefinitionNames {
48 name: &'a str,
49 fragment_definitions: Vec<&'a E::FragmentDefinition>,
50 },
51 FragmentDefinitionTargetTypeDoesNotExist {
52 fragment_definition: &'a E::FragmentDefinition,
53 },
54 InlineFragmentTargetTypeDoesNotExist {
55 inline_fragment: &'a E::InlineFragment,
56 },
57 FragmentDefinitionTargetTypeNotComposite {
58 fragment_definition: &'a E::FragmentDefinition,
59 },
60 InlineFragmentTargetTypeNotComposite {
61 inline_fragment: &'a E::InlineFragment,
62 },
63 FragmentDefinitionUnused {
64 fragment_definition: &'a E::FragmentDefinition,
65 },
66 FragmentSpreadTargetUndefined {
67 fragment_spread: &'a E::FragmentSpread,
68 },
69 FragmentSpreadCycle {
70 fragment_definition: &'a E::FragmentDefinition,
71 fragment_spread: &'a E::FragmentSpread,
72 },
73 FieldSelectionsDoNotMergeIncompatibleTypes {
74 selection_set: &'a E::SelectionSet,
75 field_a: &'a E::Field,
76 field_definition_a: &'a S::FieldDefinition,
77 field_b: &'a E::Field,
78 field_definition_b: &'a S::FieldDefinition,
79 },
80 FieldSelectionsDoNotMergeDifferingNames {
81 selection_set: &'a E::SelectionSet,
82 field_a: &'a E::Field,
83 field_b: &'a E::Field,
84 },
85 FieldSelectionsDoNotMergeDifferingArguments {
86 selection_set: &'a E::SelectionSet,
87 field_a: &'a E::Field,
88 field_b: &'a E::Field,
89 },
90 FragmentSpreadIsNotPossible {
91 fragment_spread: &'a E::FragmentSpread,
92 parent_type: TypeDefinitionReference<'a, S::TypeDefinition>,
93 },
94 InlineFragmentSpreadIsNotPossible {
95 inline_fragment: &'a E::InlineFragment,
96 parent_type: TypeDefinitionReference<'a, S::TypeDefinition>,
97 },
98 InvalidConstValue(InputCoercionError<'a, true, E::Value<true>>),
99 InvalidVariableValue(InputCoercionError<'a, false, E::Value<false>>),
100 InvalidConstDirective(DirectiveError<'a, true, E, S>),
101 InvalidVariableDirective(DirectiveError<'a, false, E, S>),
102 InvalidConstArgument(ArgumentError<'a, true, E, S>),
103 InvalidVariableArgument(ArgumentError<'a, false, E, S>),
104 NonUniqueVariableDefinitionNames {
105 name: &'a str,
106 variable_definitions: Vec<&'a E::VariableDefinition>,
107 },
108 VariableDefinitionTypeNotInput {
109 variable_definition: &'a E::VariableDefinition,
110 },
111 VariableNotDefined {
112 variable: &'a <E::Value<false> as Value<false>>::Variable,
113 operation_definition: &'a E::OperationDefinition,
114 },
115 VariableDefinitionUnused {
116 variable_definition: &'a E::VariableDefinition,
117 },
118 InvalidVariableUsage {
119 variable: &'a <E::Value<false> as Value<false>>::Variable,
120 variable_type: &'a E::VariableType,
121 location_type: &'a S::InputType,
122 },
123 InvalidOneOfVariableUsage {
124 variable: &'a <E::Value<false> as Value<false>>::Variable,
125 variable_type: &'a E::VariableType,
126 parent_type_name: &'a str,
127 },
128}
129
130#[cfg(feature = "parser-integration")]
131impl<'a, S: SchemaDefinition> From<Error<'a, ParserExecutableDocument<'a>, S>> for ParserError {
132 fn from(value: Error<'a, ParserExecutableDocument<'a>, S>) -> Self {
133 match value {
134 Error::NonUniqueOperationNames { name, operations } => Self::new(
135 format!("Multiple operation definitions named `{name}`"),
136 None,
137 operations
138 .iter()
139 .filter_map(|operation| {
140 operation.name().map(|operation_name| {
141 Annotation::new(
142 format!("Operation definition with name `{name}`"),
143 *operation_name.span(),
144 )
145 })
146 })
147 .collect(),
148 ),
149 Error::NotLoneAnonymousOperation {
150 anonymous_operations,
151 } => Self::new(
152 "Anonymous operation not lone operation in document",
153 None,
154 anonymous_operations
155 .iter()
156 .map(|operation| {
157 Annotation::new(
158 "Anonymous operation definition",
159 *operation.as_ref().selection_set().span(),
160 )
161 })
162 .collect(),
163 ),
164 Error::SubscriptionRootNotSingleField { operation } => Self::new(
165 "Subscription root is not a single field",
166 Some(Annotation::new(
167 "Selection set contains multiple fields",
168 *operation.as_ref().selection_set().span(),
169 )),
170 Vec::new(),
171 ),
172 Error::FieldDoesNotExistOnType { field, r#type } => Self::new(
173 format!(
174 "Field `{}` does not exist on type `{}`",
175 field.name().as_ref(),
176 r#type.name()
177 ),
178 Some(Annotation::new(
179 format!("Field does not exist on type `{}`", r#type.name()),
180 *field.name().span(),
181 )),
182 Vec::new(),
183 ),
184 Error::OperationTypeNotDefined { operation } => Self::new(
185 format!(
186 "Schema does not define a {} root",
187 OperationType::from(operation.operation_type()),
188 ),
189 Some(Annotation::new(
190 format!(
191 "Schema does not define a {} root",
192 OperationType::from(operation.operation_type()),
193 ),
194 *operation.operation_type().span(),
195 )),
196 Vec::new(),
197 ),
198 Error::LeafFieldSelectionNotEmpty {
199 selection_set,
200 r#type,
201 } => Self::new(
202 format!(
203 "Selection on field of leaf type `{}` was not empty",
204 r#type.display_name()
205 ),
206 Some(Annotation::new(
207 "Selection set on field of leaf type must be empty",
208 *selection_set.span(),
209 )),
210 Vec::new(),
211 ),
212 Error::NonLeafFieldSelectionEmpty { field, r#type } => Self::new(
213 format!(
214 "No selection on field of non-leaf type `{}`",
215 r#type.display_name()
216 ),
217 Some(Annotation::new(
218 "Fields of non-leaf types must have a selection",
219 *field.name().span(),
220 )),
221 Vec::new(),
222 ),
223 Error::NonUniqueFragmentDefinitionNames {
224 name,
225 fragment_definitions,
226 } => Self::new(
227 format!("Multiple fragment definitions named `{name}`"),
228 None,
229 fragment_definitions
230 .iter()
231 .map(|fragment_definition| {
232 Annotation::new(
233 format!("Fragment definition with name `{name}`"),
234 *fragment_definition.name().span(),
235 )
236 })
237 .collect(),
238 ),
239 Error::FragmentDefinitionTargetTypeDoesNotExist {
240 fragment_definition,
241 } => Self::new(
242 format!(
243 "No type definition with name `{}`",
244 fragment_definition.type_condition().named_type().as_ref()
245 ),
246 Some(Annotation::new(
247 "No type with this name",
248 *fragment_definition
249 .type_condition()
250 .named_type()
251 .span(),
252 )),
253 Vec::new(),
254 ),
255 Error::InlineFragmentTargetTypeDoesNotExist { inline_fragment } => Self::new(
256 format!(
257 "No type definition with name `{}`",
258 inline_fragment
259 .type_condition()
260 .map(|tc| tc.named_type().as_ref())
261 .unwrap_or_default()
262 ),
263 inline_fragment.type_condition().map(|tc| {
264 Annotation::new("No type with this name", *tc.named_type().span())
265 }),
266 Vec::new(),
267 ),
268 Error::FragmentDefinitionTargetTypeNotComposite {
269 fragment_definition,
270 } => Self::new(
271 format!(
272 "`{}` is not a composite type",
273 fragment_definition.type_condition().named_type().as_ref()
274 ),
275 Some(Annotation::new(
276 "Fragment definition target types must be composite types",
277 *fragment_definition
278 .type_condition()
279 .named_type()
280 .span(),
281 )),
282 Vec::new(),
283 ),
284 Error::InlineFragmentTargetTypeNotComposite { inline_fragment } => Self::new(
285 format!(
286 "`{}` is not a composite type",
287 inline_fragment
288 .type_condition()
289 .map(|tc| tc.named_type().as_ref())
290 .unwrap_or_default()
291 ),
292 inline_fragment.type_condition().map(|tc| {
293 Annotation::new(
294 "Inline fragment target types must be composite types",
295 *tc.named_type().span(),
296 )
297 }),
298 Vec::new(),
299 ),
300 Error::FragmentDefinitionUnused {
301 fragment_definition,
302 } => Self::new(
303 format!(
304 "Fragment definition `{}` is unused",
305 fragment_definition.name().as_ref()
306 ),
307 Some(Annotation::new(
308 "Fragment definition is unused",
309 *fragment_definition.name().span(),
310 )),
311 Vec::new(),
312 ),
313 Error::FragmentSpreadTargetUndefined { fragment_spread } => Self::new(
314 format!(
315 "No fragment defined with name `{}`",
316 fragment_spread.name().as_ref()
317 ),
318 Some(Annotation::new(
319 "No fragment defined with this name",
320 *fragment_spread.name().span(),
321 )),
322 Vec::new(),
323 ),
324 Error::FragmentSpreadCycle {
325 fragment_definition,
326 fragment_spread,
327 } => Self::new(
328 format!(
329 "Cycle detected in fragment `{}`",
330 fragment_definition.name().as_ref()
331 ),
332 Some(Annotation::new(
333 "Cycle introduced by fragment spread",
334 *fragment_spread.name().span(),
335 )),
336 vec![Annotation::new(
337 "Affected fragment definition",
338 *fragment_definition.name().span(),
339 )],
340 ),
341 Error::FieldSelectionsDoNotMergeDifferingArguments {
342 selection_set,
343 field_a,
344 field_b,
345 } => Self::new(
346 "Fields in selection set do not merge due to unequal arguments",
347 Some(Annotation::new(
348 "Fields in selection set do not merge",
349 *selection_set.span(),
350 )),
351 vec![
352 Annotation::new("First field", *field_a.name().span()),
353 Annotation::new("Second field", *field_b.name().span()),
354 ],
355 ),
356 Error::FieldSelectionsDoNotMergeDifferingNames {
357 selection_set,
358 field_a,
359 field_b,
360 } => Self::new(
361 "Fields in selection set do not merge due to unequal field names",
362 Some(Annotation::new(
363 "Fields in selection set do not merge",
364 *selection_set.span(),
365 )),
366 vec![
367 Annotation::new("First field", *field_a.name().span()),
368 Annotation::new("Second field", *field_b.name().span()),
369 ],
370 ),
371 Error::FieldSelectionsDoNotMergeIncompatibleTypes {
372 selection_set,
373 field_a,
374 field_definition_a,
375 field_b,
376 field_definition_b,
377 } => Self::new(
378 "Fields in selection set do not merge due to incompatible types",
379 Some(Annotation::new(
380 "Fields in selection set do not merge",
381 *selection_set.span(),
382 )),
383 vec![
384 Annotation::new(
385 format!(
386 "First field has type {}",
387 field_definition_a.r#type().display_name(),
388 ),
389 *field_a.name().span(),
390 ),
391 Annotation::new(
392 format!(
393 "Second field has type {}",
394 field_definition_b.r#type().display_name(),
395 ),
396 *field_b.name().span(),
397 ),
398 ],
399 ),
400 Error::FragmentSpreadIsNotPossible {
401 fragment_spread,
402 parent_type,
403 } => Self::new(
404 format!(
405 "Fragment `{}` cannot be spread for type {}",
406 fragment_spread.name().as_ref(),
407 parent_type.name()
408 ),
409 Some(Annotation::new(
410 format!("Cannot be spread for type {}", parent_type.name()),
411 *fragment_spread.name().span(),
412 )),
413 Vec::new(),
414 ),
415 Error::InlineFragmentSpreadIsNotPossible {
416 inline_fragment,
417 parent_type,
418 } => Self::new(
419 format!(
420 "Fragment targeting type {} cannot be spread for type {}",
421 inline_fragment
422 .type_condition()
423 .map(|type_condition| type_condition.named_type().as_ref())
424 .unwrap_or_else(|| parent_type.name()),
425 parent_type.name(),
426 ),
427 Some(Annotation::new(
428 format!("Cannot be spread for type {}", parent_type.name()),
429 *inline_fragment.span(),
430 )),
431 Vec::new(),
432 ),
433 Error::InvalidConstValue(error) => Self::from(error),
434 Error::InvalidVariableValue(error) => Self::from(error),
435 Error::InvalidConstDirective(error) => Self::from(error),
436 Error::InvalidVariableDirective(error) => Self::from(error),
437 Error::InvalidConstArgument(error) => Self::from(error),
438 Error::InvalidVariableArgument(error) => Self::from(error),
439 Error::NonUniqueVariableDefinitionNames {
440 name,
441 variable_definitions,
442 } => Self::new(
443 format!("Multiple variable definitions named ${name}"),
444 None,
445 variable_definitions
446 .iter()
447 .map(|variable_definition| {
448 Annotation::new(
449 format!("Variable definition with name ${name}"),
450 *variable_definition.variable().span(),
451 )
452 })
453 .collect(),
454 ),
455 Error::VariableDefinitionTypeNotInput {
456 variable_definition,
457 } => Self::new(
458 format!(
459 "Type of variable ${}, {}, is not an input type",
460 variable_definition.variable().name(),
461 variable_definition.r#type().as_ref().name()
462 ),
463 Some(Annotation::new(
464 "Not an input type",
465 *variable_definition.r#type().span(),
466 )),
467 Vec::new(),
468 ),
469 Error::VariableNotDefined {
470 variable,
471 operation_definition,
472 } => {
473 let operation_name = match operation_definition.as_ref().name() {
474 Some(name) => Cow::Owned(format!("operation {name}")),
475 None => Cow::Borrowed("anonymous operation"),
476 };
477 Self::new(
478 format!(
479 "Variable ${} not defined in {operation_name}",
480 variable.name(),
481 ),
482 Some(Annotation::new(
483 format!(
484 "No variable definition with this name defined in {operation_name}",
485 ),
486 *variable.span(),
487 )),
488 Vec::new(),
489 )
490 }
491 Error::VariableDefinitionUnused {
492 variable_definition,
493 } => Self::new(
494 format!(
495 "Variable definition ${} not used",
496 variable_definition.variable().name(),
497 ),
498 Some(Annotation::new(
499 "Variable definition not used",
500 *variable_definition.variable().span(),
501 )),
502 Vec::new(),
503 ),
504 Error::InvalidVariableUsage {
505 variable,
506 variable_type,
507 location_type,
508 } => Self::new(
509 format!(
510 "Variable ${} of type {} cannot be used here, where {} is expected",
511 variable.name(),
512 variable_type.as_ref().display_name(),
513 location_type.display_name(),
514 ),
515 Some(Annotation::new(
516 format!(
517 "Cannot use variable of type {} where {} is expected",
518 variable_type.as_ref().display_name(),
519 location_type.display_name(),
520 ),
521 *variable.span(),
522 )),
523 Vec::new(),
524 ),
525 Error::InvalidOneOfVariableUsage {
526 variable,
527 variable_type,
528 parent_type_name,
529 } => Self::new(
530 format!(
531 "Variable ${} is of type {} but must be non-nullable to be used for OneOf Input Object {}",
532 variable.name(),
533 variable_type.as_ref().display_name(),
534 parent_type_name,
535 ),
536 Some(Annotation::new(
537 format!(
538 "Variable ${} is of type {} but must be non-nullable to be used for OneOf Input Object {}",
539 variable.name(),
540 variable_type.as_ref().display_name(),
541 parent_type_name,
542 ),
543 *variable.span(),
544 )),
545 Vec::new(),
546 ),
547 }
548 }
549}