Skip to main content

libgraphql_parser/ast/
directive_location.rs

1use crate::ast::ast_node::append_span_source_slice;
2use crate::ast::AstNode;
3use crate::ByteSpan;
4use crate::SourceMap;
5use crate::SourceSpan;
6use crate::token::GraphQLToken;
7use inherent::inherent;
8
9/// A directive location with its own span (unlike
10/// `graphql_parser` which uses a plain enum).
11///
12/// See
13/// [Directive Locations](https://spec.graphql.org/September2025/#DirectiveLocations)
14/// in the spec.
15#[derive(Clone, Debug, PartialEq)]
16pub struct DirectiveLocation<'src> {
17    pub kind: DirectiveLocationKind,
18    pub span: ByteSpan,
19    pub syntax: Option<Box<DirectiveLocationSyntax<'src>>>,
20}
21
22/// The kind of location where a directive may be applied.
23///
24/// See
25/// [Directive Locations](https://spec.graphql.org/September2025/#DirectiveLocations)
26/// in the spec.
27#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
28pub enum DirectiveLocationKind {
29    ArgumentDefinition,
30    Enum,
31    EnumValue,
32    Field,
33    FieldDefinition,
34    FragmentDefinition,
35    FragmentSpread,
36    InlineFragment,
37    InputFieldDefinition,
38    InputObject,
39    Interface,
40    Mutation,
41    Object,
42    Query,
43    Scalar,
44    Schema,
45    Subscription,
46    Union,
47    VariableDefinition,
48}
49
50/// Syntax detail for a [`DirectiveLocation`].
51#[derive(Clone, Debug, PartialEq)]
52pub struct DirectiveLocationSyntax<'src> {
53    /// The `|` pipe token before this location (`None` for
54    /// the first location).
55    pub pipe: Option<GraphQLToken<'src>>,
56    /// The location name token (e.g. `FIELD`, `QUERY`).
57    pub token: GraphQLToken<'src>,
58}
59
60#[inherent]
61impl AstNode for DirectiveLocation<'_> {
62    /// See [`AstNode::append_source()`](crate::ast::AstNode::append_source).
63    pub fn append_source(
64        &self,
65        sink: &mut String,
66        source: Option<&str>,
67    ) {
68        if let Some(src) = source {
69            append_span_source_slice(
70                self.span, sink, src,
71            );
72        }
73    }
74
75    /// Returns this directive location's byte-offset span within the
76    /// source text.
77    ///
78    /// The returned [`ByteSpan`] can be resolved to line/column
79    /// positions via [`source_span()`](Self::source_span) or
80    /// [`ByteSpan::resolve()`].
81    #[inline]
82    pub fn byte_span(&self) -> ByteSpan {
83        self.span
84    }
85
86    /// Resolves this directive location's position to line/column
87    /// coordinates using the given [`SourceMap`].
88    ///
89    /// Returns [`None`] if the byte offsets cannot be resolved
90    /// (e.g. the span was synthetically constructed without
91    /// valid position data).
92    #[inline]
93    pub fn source_span(
94        &self,
95        source_map: &SourceMap,
96    ) -> Option<SourceSpan> {
97        self.byte_span().resolve(source_map)
98    }
99}