Skip to main content

libgraphql_parser/ast/
operation_definition.rs

1use crate::ast::ast_node::append_span_source_slice;
2use crate::ast::AstNode;
3use crate::ast::DelimiterPair;
4use crate::ast::DirectiveAnnotation;
5use crate::ast::Name;
6use crate::ast::OperationKind;
7use crate::ast::SelectionSet;
8use crate::ast::StringValue;
9use crate::ast::VariableDefinition;
10use crate::ByteSpan;
11use crate::SourceMap;
12use crate::SourceSpan;
13use crate::token::GraphQLToken;
14use inherent::inherent;
15
16/// An operation definition (query, mutation, or
17/// subscription).
18///
19/// See
20/// [Operations](https://spec.graphql.org/September2025/#sec-Language.Operations)
21/// in the spec.
22#[derive(Clone, Debug, PartialEq)]
23pub struct OperationDefinition<'src> {
24    pub description: Option<StringValue<'src>>,
25    pub directives: Vec<DirectiveAnnotation<'src>>,
26    pub name: Option<Name<'src>>,
27    pub operation_kind: OperationKind,
28    pub selection_set: SelectionSet<'src>,
29    /// `true` for shorthand queries (`{ field }`)
30    /// that omit the `query` keyword.
31    pub shorthand: bool,
32    pub span: ByteSpan,
33    pub syntax:
34        Option<Box<OperationDefinitionSyntax<'src>>>,
35    pub variable_definitions:
36        Vec<VariableDefinition<'src>>,
37}
38
39/// Syntax detail for an [`OperationDefinition`].
40#[derive(Clone, Debug, PartialEq)]
41pub struct OperationDefinitionSyntax<'src> {
42    /// The operation keyword (`query`, `mutation`,
43    /// `subscription`). `None` for shorthand queries.
44    pub operation_keyword: Option<GraphQLToken<'src>>,
45    pub variable_definition_parens:
46        Option<DelimiterPair<'src>>,
47}
48
49impl<'src> OperationDefinition<'src> {
50    /// Returns the operation name as a string slice, or
51    /// [`None`] for anonymous (shorthand) operations.
52    ///
53    /// Convenience accessor for `self.name`.
54    #[inline]
55    pub fn name_value(&self) -> Option<&str> {
56        self.name.as_ref().map(|n| n.value.as_ref())
57    }
58}
59
60#[inherent]
61impl AstNode for OperationDefinition<'_> {
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 operation'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 operation'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}