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}