Skip to main content

libgraphql_parser/ast/
directive_definition.rs

1use crate::ast::ast_node::append_span_source_slice;
2use crate::ast::AstNode;
3use crate::ast::DelimiterPair;
4use crate::ast::DirectiveLocation;
5use crate::ast::InputValueDefinition;
6use crate::ast::Name;
7use crate::ast::StringValue;
8use crate::ByteSpan;
9use crate::SourceMap;
10use crate::SourceSpan;
11use crate::token::GraphQLToken;
12use inherent::inherent;
13
14/// A directive definition.
15///
16/// See
17/// [Directive Definitions](https://spec.graphql.org/September2025/#sec-Type-System.Directives)
18/// in the spec.
19///
20/// # Spec invariant
21///
22/// The spec grammar requires at least one directive
23/// location. For a spec-valid node, `locations` is
24/// always non-empty.
25#[derive(Clone, Debug, PartialEq)]
26pub struct DirectiveDefinition<'src> {
27    pub arguments: Vec<InputValueDefinition<'src>>,
28    pub description: Option<StringValue<'src>>,
29    pub locations: Vec<DirectiveLocation<'src>>,
30    pub name: Name<'src>,
31    pub repeatable: bool,
32    pub span: ByteSpan,
33    pub syntax: Option<Box<DirectiveDefinitionSyntax<'src>>>,
34}
35
36/// Syntax detail for a [`DirectiveDefinition`].
37#[derive(Clone, Debug, PartialEq)]
38pub struct DirectiveDefinitionSyntax<'src> {
39    pub argument_parens: Option<DelimiterPair<'src>>,
40    pub at_sign: GraphQLToken<'src>,
41    pub directive_keyword: GraphQLToken<'src>,
42    pub on_keyword: GraphQLToken<'src>,
43    pub repeatable_keyword: Option<GraphQLToken<'src>>,
44}
45
46impl<'src> DirectiveDefinition<'src> {
47    /// Returns the name of this directive definition as a string
48    /// slice.
49    ///
50    /// Convenience accessor for `self.name.value`.
51    #[inline]
52    pub fn name_value(&self) -> &str {
53        self.name.value.as_ref()
54    }
55}
56
57#[inherent]
58impl AstNode for DirectiveDefinition<'_> {
59    /// See [`AstNode::append_source()`](crate::ast::AstNode::append_source).
60    pub fn append_source(
61        &self,
62        sink: &mut String,
63        source: Option<&str>,
64    ) {
65        if let Some(src) = source {
66            append_span_source_slice(
67                self.span, sink, src,
68            );
69        }
70    }
71
72    /// Returns this directive definition's byte-offset span within the
73    /// source text.
74    ///
75    /// The returned [`ByteSpan`] can be resolved to line/column
76    /// positions via [`source_span()`](Self::source_span) or
77    /// [`ByteSpan::resolve()`].
78    #[inline]
79    pub fn byte_span(&self) -> ByteSpan {
80        self.span
81    }
82
83    /// Resolves this directive definition's position to line/column
84    /// coordinates using the given [`SourceMap`].
85    ///
86    /// Returns [`None`] if the byte offsets cannot be resolved
87    /// (e.g. the span was synthetically constructed without
88    /// valid position data).
89    #[inline]
90    pub fn source_span(
91        &self,
92        source_map: &SourceMap,
93    ) -> Option<SourceSpan> {
94        self.byte_span().resolve(source_map)
95    }
96}