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().clone(),
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().clone(),
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().clone(),
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().clone(),
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().clone(),
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().clone(),
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().clone(),
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().clone(),
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 .clone(),
253 )),
254 Vec::new(),
255 ),
256 Error::InlineFragmentTargetTypeDoesNotExist { inline_fragment } => Self::new(
257 format!(
258 "No type definition with name `{}`",
259 inline_fragment
260 .type_condition()
261 .map(|tc| tc.named_type().as_ref())
262 .unwrap_or_default()
263 ),
264 inline_fragment.type_condition().map(|tc| {
265 Annotation::new("No type with this name", tc.named_type().span().clone())
266 }),
267 Vec::new(),
268 ),
269 Error::FragmentDefinitionTargetTypeNotComposite {
270 fragment_definition,
271 } => Self::new(
272 format!(
273 "`{}` is not a composite type",
274 fragment_definition.type_condition().named_type().as_ref()
275 ),
276 Some(Annotation::new(
277 "Fragment definition target types must be composite types",
278 fragment_definition
279 .type_condition()
280 .named_type()
281 .span()
282 .clone(),
283 )),
284 Vec::new(),
285 ),
286 Error::InlineFragmentTargetTypeNotComposite { inline_fragment } => Self::new(
287 format!(
288 "`{}` is not a composite type",
289 inline_fragment
290 .type_condition()
291 .map(|tc| tc.named_type().as_ref())
292 .unwrap_or_default()
293 ),
294 inline_fragment.type_condition().map(|tc| {
295 Annotation::new(
296 "Inline fragment target types must be composite types",
297 tc.named_type().span().clone(),
298 )
299 }),
300 Vec::new(),
301 ),
302 Error::FragmentDefinitionUnused {
303 fragment_definition,
304 } => Self::new(
305 format!(
306 "Fragment definition `{}` is unused",
307 fragment_definition.name().as_ref()
308 ),
309 Some(Annotation::new(
310 "Fragment definition is unused",
311 fragment_definition.name().span().clone(),
312 )),
313 Vec::new(),
314 ),
315 Error::FragmentSpreadTargetUndefined { fragment_spread } => Self::new(
316 format!(
317 "No fragment defined with name `{}`",
318 fragment_spread.name().as_ref()
319 ),
320 Some(Annotation::new(
321 "No fragment defined with this name",
322 fragment_spread.name().span().clone(),
323 )),
324 Vec::new(),
325 ),
326 Error::FragmentSpreadCycle {
327 fragment_definition,
328 fragment_spread,
329 } => Self::new(
330 format!(
331 "Cycle detected in fragment `{}`",
332 fragment_definition.name().as_ref()
333 ),
334 Some(Annotation::new(
335 "Cycle introduced by fragment spread",
336 fragment_spread.name().span().clone(),
337 )),
338 vec![Annotation::new(
339 "Affected fragment definition",
340 fragment_definition.name().span().clone(),
341 )],
342 ),
343 Error::FieldSelectionsDoNotMergeDifferingArguments {
344 selection_set,
345 field_a,
346 field_b,
347 } => Self::new(
348 "Fields in selection set do not merge due to unequal arguments",
349 Some(Annotation::new(
350 "Fields in selection set do not merge",
351 selection_set.span().clone(),
352 )),
353 vec![
354 Annotation::new("First field", field_a.name().span().clone()),
355 Annotation::new("Second field", field_b.name().span().clone()),
356 ],
357 ),
358 Error::FieldSelectionsDoNotMergeDifferingNames {
359 selection_set,
360 field_a,
361 field_b,
362 } => Self::new(
363 "Fields in selection set do not merge due to unequal field names",
364 Some(Annotation::new(
365 "Fields in selection set do not merge",
366 selection_set.span().clone(),
367 )),
368 vec![
369 Annotation::new("First field", field_a.name().span().clone()),
370 Annotation::new("Second field", field_b.name().span().clone()),
371 ],
372 ),
373 Error::FieldSelectionsDoNotMergeIncompatibleTypes {
374 selection_set,
375 field_a,
376 field_definition_a,
377 field_b,
378 field_definition_b,
379 } => Self::new(
380 "Fields in selection set do not merge due to incompatible types",
381 Some(Annotation::new(
382 "Fields in selection set do not merge",
383 selection_set.span().clone(),
384 )),
385 vec![
386 Annotation::new(
387 format!(
388 "First field has type {}",
389 field_definition_a.r#type().display_name(),
390 ),
391 field_a.name().span().clone(),
392 ),
393 Annotation::new(
394 format!(
395 "Second field has type {}",
396 field_definition_b.r#type().display_name(),
397 ),
398 field_b.name().span().clone(),
399 ),
400 ],
401 ),
402 Error::FragmentSpreadIsNotPossible {
403 fragment_spread,
404 parent_type,
405 } => Self::new(
406 format!(
407 "Fragment `{}` cannot be spread for type {}",
408 fragment_spread.name().as_ref(),
409 parent_type.name()
410 ),
411 Some(Annotation::new(
412 format!("Cannot be spread for type {}", parent_type.name()),
413 fragment_spread.name().span().clone(),
414 )),
415 Vec::new(),
416 ),
417 Error::InlineFragmentSpreadIsNotPossible {
418 inline_fragment,
419 parent_type,
420 } => Self::new(
421 format!(
422 "Fragment targeting type {} cannot be spread for type {}",
423 inline_fragment
424 .type_condition()
425 .map(|type_condition| type_condition.named_type().as_ref())
426 .unwrap_or_else(|| parent_type.name()),
427 parent_type.name(),
428 ),
429 Some(Annotation::new(
430 format!("Cannot be spread for type {}", parent_type.name()),
431 inline_fragment.span().clone(),
432 )),
433 Vec::new(),
434 ),
435 Error::InvalidConstValue(error) => Self::from(error),
436 Error::InvalidVariableValue(error) => Self::from(error),
437 Error::InvalidConstDirective(error) => Self::from(error),
438 Error::InvalidVariableDirective(error) => Self::from(error),
439 Error::InvalidConstArgument(error) => Self::from(error),
440 Error::InvalidVariableArgument(error) => Self::from(error),
441 Error::NonUniqueVariableDefinitionNames {
442 name,
443 variable_definitions,
444 } => Self::new(
445 format!("Multiple variable definitions named ${name}"),
446 None,
447 variable_definitions
448 .iter()
449 .map(|variable_definition| {
450 Annotation::new(
451 format!("Variable definition with name ${name}"),
452 variable_definition.variable().span().clone(),
453 )
454 })
455 .collect(),
456 ),
457 Error::VariableDefinitionTypeNotInput {
458 variable_definition,
459 } => Self::new(
460 format!(
461 "Type of variable ${}, {}, is not an input type",
462 variable_definition.variable().name(),
463 variable_definition.r#type().as_ref().name()
464 ),
465 Some(Annotation::new(
466 "Not an input type",
467 variable_definition.r#type().span().clone(),
468 )),
469 Vec::new(),
470 ),
471 Error::VariableNotDefined {
472 variable,
473 operation_definition,
474 } => {
475 let operation_name = match operation_definition.as_ref().name() {
476 Some(name) => Cow::Owned(format!("operation {name}")),
477 None => Cow::Borrowed("anonymous operation"),
478 };
479 Self::new(
480 format!(
481 "Variable ${} not defined in {operation_name}",
482 variable.name(),
483 ),
484 Some(Annotation::new(
485 format!(
486 "No variable definition with this name defined in {operation_name}",
487 ),
488 variable.span().clone(),
489 )),
490 Vec::new(),
491 )
492 }
493 Error::VariableDefinitionUnused {
494 variable_definition,
495 } => Self::new(
496 format!(
497 "Variable definition ${} not used",
498 variable_definition.variable().name(),
499 ),
500 Some(Annotation::new(
501 "Variable definition not used",
502 variable_definition.variable().span().clone(),
503 )),
504 Vec::new(),
505 ),
506 Error::InvalidVariableUsage {
507 variable,
508 variable_type,
509 location_type,
510 } => Self::new(
511 format!(
512 "Variable ${} of type {} cannot be used here, where {} is expected",
513 variable.name(),
514 variable_type.as_ref().display_name(),
515 location_type.display_name(),
516 ),
517 Some(Annotation::new(
518 format!(
519 "Cannot use variable of type {} where {} is expected",
520 variable_type.as_ref().display_name(),
521 location_type.display_name(),
522 ),
523 variable.span().clone(),
524 )),
525 Vec::new(),
526 ),
527 Error::InvalidOneOfVariableUsage {
528 variable,
529 variable_type,
530 parent_type_name,
531 } => Self::new(
532 format!(
533 "Variable ${} is of type {} but must be non-nullable to be used for OneOf Input Object {}",
534 variable.name(),
535 variable_type.as_ref().display_name(),
536 parent_type_name,
537 ),
538 Some(Annotation::new(
539 format!(
540 "Variable ${} is of type {} but must be non-nullable to be used for OneOf Input Object {}",
541 variable.name(),
542 variable_type.as_ref().display_name(),
543 parent_type_name,
544 ),
545 variable.span().clone(),
546 )),
547 Vec::new(),
548 ),
549 }
550 }
551}