Skip to main content

libgraphql_parser/ast/
directive_annotation.rs

1use crate::ast::Argument;
2use crate::ast::ast_node::append_span_source_slice;
3use crate::ast::AstNode;
4use crate::ast::DelimiterPair;
5use crate::ast::Name;
6use crate::ByteSpan;
7use crate::SourceMap;
8use crate::SourceSpan;
9use crate::token::GraphQLToken;
10use inherent::inherent;
11
12/// A directive annotation applied to a definition or field
13/// (e.g. `@deprecated(reason: "Use newField")`).
14///
15/// See
16/// [Directives](https://spec.graphql.org/September2025/#sec-Language.Directives)
17/// in the spec. Note: this represents an *applied* directive
18/// (an annotation), not a directive *definition*.
19#[derive(Clone, Debug, PartialEq)]
20pub struct DirectiveAnnotation<'src> {
21    pub arguments: Vec<Argument<'src>>,
22    pub name: Name<'src>,
23    pub span: ByteSpan,
24    pub syntax: Option<Box<DirectiveAnnotationSyntax<'src>>>,
25}
26
27/// Syntax detail for a [`DirectiveAnnotation`].
28#[derive(Clone, Debug, PartialEq)]
29pub struct DirectiveAnnotationSyntax<'src> {
30    pub argument_parens: Option<DelimiterPair<'src>>,
31    pub at_sign: GraphQLToken<'src>,
32}
33
34impl<'src> DirectiveAnnotation<'src> {
35    /// Returns the name of this directive annotation as a string
36    /// slice.
37    ///
38    /// Convenience accessor for `self.name.value`.
39    #[inline]
40    pub fn name_value(&self) -> &str {
41        self.name.value.as_ref()
42    }
43}
44
45#[inherent]
46impl AstNode for DirectiveAnnotation<'_> {
47    /// See [`AstNode::append_source()`](crate::ast::AstNode::append_source).
48    pub fn append_source(
49        &self,
50        sink: &mut String,
51        source: Option<&str>,
52    ) {
53        if let Some(src) = source {
54            append_span_source_slice(
55                self.span, sink, src,
56            );
57        }
58    }
59
60    /// Returns this directive annotation's byte-offset span within the
61    /// source text.
62    ///
63    /// The returned [`ByteSpan`] can be resolved to line/column
64    /// positions via [`source_span()`](Self::source_span) or
65    /// [`ByteSpan::resolve()`].
66    #[inline]
67    pub fn byte_span(&self) -> ByteSpan {
68        self.span
69    }
70
71    /// Resolves this directive annotation's position to line/column
72    /// coordinates using the given [`SourceMap`].
73    ///
74    /// Returns [`None`] if the byte offsets cannot be resolved
75    /// (e.g. the span was synthetically constructed without
76    /// valid position data).
77    #[inline]
78    pub fn source_span(
79        &self,
80        source_map: &SourceMap,
81    ) -> Option<SourceSpan> {
82        self.byte_span().resolve(source_map)
83    }
84}