bluejay_validator/executable/document/error/
directive_error.rs

1use bluejay_core::definition::{DirectiveDefinition, DirectiveLocation, SchemaDefinition};
2use bluejay_core::executable::ExecutableDocument;
3use bluejay_core::AsIter;
4#[cfg(feature = "parser-integration")]
5use bluejay_parser::{
6    ast::executable::ExecutableDocument as ParserExecutableDocument,
7    error::{Annotation, Error as ParserError},
8    HasSpan,
9};
10use itertools::Itertools;
11
12pub enum DirectiveError<'a, const CONST: bool, E: ExecutableDocument, S: SchemaDefinition> {
13    DirectiveDoesNotExist {
14        directive: &'a E::Directive<CONST>,
15    },
16    DirectiveInInvalidLocation {
17        directive: &'a E::Directive<CONST>,
18        directive_definition: &'a S::DirectiveDefinition,
19        location: DirectiveLocation,
20    },
21    DirectivesNotUniquePerLocation {
22        directives: Vec<&'a E::Directive<CONST>>,
23        directive_definition: &'a S::DirectiveDefinition,
24    },
25}
26
27#[cfg(feature = "parser-integration")]
28impl<'a, const CONST: bool, S: SchemaDefinition>
29    From<DirectiveError<'a, CONST, ParserExecutableDocument<'a>, S>> for ParserError
30{
31    fn from(value: DirectiveError<'a, CONST, ParserExecutableDocument<'a>, S>) -> Self {
32        match value {
33            DirectiveError::DirectiveDoesNotExist { directive } => Self::new(
34                format!(
35                    "No directive definition with name `@{}`",
36                    directive.name().as_ref()
37                ),
38                Some(Annotation::new(
39                    "No directive definition with this name",
40                    directive.name().span().clone(),
41                )),
42                Vec::new(),
43            ),
44            DirectiveError::DirectiveInInvalidLocation {
45                directive,
46                directive_definition,
47                location,
48            } => Self::new(
49                format!(
50                    "Directive @{} cannot be used at location {location}. It is only allowed at the following locations: {}",
51                    directive.name().as_ref(),
52                    directive_definition.locations().iter().join(", "),
53                ),
54                Some(Annotation::new(
55                    format!("Cannot be used at location {location}"),
56                    directive.span().clone(),
57                )),
58                Vec::new(),
59            ),
60            DirectiveError::DirectivesNotUniquePerLocation { directives, directive_definition } => Self::new(
61                format!(
62                    "Directive @{} is not repeatable but was used multiple times in the same location",
63                    directive_definition.name(),
64                ),
65                None,
66                directives.into_iter().map(|directive| Annotation::new(
67                    "Usage of directive",
68                    directive.span().clone(),
69                )).collect(),
70            ),
71        }
72    }
73}