|
1 |
| -use crate::ast::{ |
2 |
| - Arguments, Definition, Directive, Field, Fragment, FragmentSpread, InlineFragment, InputValue, |
3 |
| - Operation, OperationType, OwnedDocument, Selection, Type, VariableDefinition, |
4 |
| - VariableDefinitions, |
5 |
| -}; |
| 1 | +use std::borrow::Cow; |
6 | 2 |
|
7 | 3 | use crate::{
|
| 4 | + ast::{ |
| 5 | + Arguments, Definition, Directive, Field, Fragment, FragmentSpread, InlineFragment, |
| 6 | + InputValue, Operation, OperationType, OwnedDocument, Selection, Type, VariableDefinition, |
| 7 | + VariableDefinitions, |
| 8 | + }, |
8 | 9 | parser::{
|
9 |
| - Lexer, OptionParseResult, ParseError, ParseResult, Parser, Spanning, Token, |
| 10 | + Lexer, OptionParseResult, ParseError, ParseResult, Parser, ScalarToken, Spanning, Token, |
10 | 11 | UnlocatedParseResult, value::parse_value_literal,
|
11 | 12 | },
|
12 | 13 | schema::{
|
@@ -54,18 +55,25 @@ fn parse_definition<'a, S>(
|
54 | 55 | where
|
55 | 56 | S: ScalarValue,
|
56 | 57 | {
|
57 |
| - match parser.peek().item { |
| 58 | + let description = parse_description(parser)?; |
| 59 | + |
| 60 | + let mut def = match parser.peek().item { |
| 61 | + // Descriptions are not permitted on query shorthand. |
| 62 | + // See: https://spec.graphql.org/September2025#sel-GAFTRJABAByBz7P |
| 63 | + Token::CurlyOpen if description.is_some() => { |
| 64 | + return Err(parser.next_token()?.map(ParseError::unexpected_token)); |
| 65 | + } |
58 | 66 | Token::CurlyOpen
|
59 | 67 | | Token::Name("query")
|
60 | 68 | | Token::Name("mutation")
|
61 |
| - | Token::Name("subscription") => Ok(Definition::Operation(parse_operation_definition( |
62 |
| - parser, schema, |
63 |
| - )?)), |
64 |
| - Token::Name("fragment") => Ok(Definition::Fragment(parse_fragment_definition( |
65 |
| - parser, schema, |
66 |
| - )?)), |
67 |
| - _ => Err(parser.next_token()?.map(ParseError::unexpected_token)), |
68 |
| - } |
| 69 | + | Token::Name("subscription") => { |
| 70 | + Definition::Operation(parse_operation_definition(parser, schema)?) |
| 71 | + } |
| 72 | + Token::Name("fragment") => Definition::Fragment(parse_fragment_definition(parser, schema)?), |
| 73 | + _ => return Err(parser.next_token()?.map(ParseError::unexpected_token)), |
| 74 | + }; |
| 75 | + def.set_description(description); |
| 76 | + Ok(def) |
69 | 77 | }
|
70 | 78 |
|
71 | 79 | fn parse_operation_definition<'a, S>(
|
|
85 | 93 | Operation {
|
86 | 94 | operation_type: OperationType::Query,
|
87 | 95 | name: None,
|
| 96 | + description: None, |
88 | 97 | variable_definitions: None,
|
89 | 98 | directives: None,
|
90 | 99 | selection_set: selection_set.item,
|
@@ -115,6 +124,7 @@ where
|
115 | 124 | Operation {
|
116 | 125 | operation_type: operation_type.item,
|
117 | 126 | name,
|
| 127 | + description: None, |
118 | 128 | variable_definitions,
|
119 | 129 | directives: directives.map(|s| s.item),
|
120 | 130 | selection_set: selection_set.item,
|
@@ -158,6 +168,7 @@ where
|
158 | 168 | &selection_set.span.end,
|
159 | 169 | Fragment {
|
160 | 170 | name,
|
| 171 | + description: None, |
161 | 172 | type_condition: type_cond,
|
162 | 173 | directives: directives.map(|s| s.item),
|
163 | 174 | selection_set: selection_set.item,
|
@@ -460,6 +471,21 @@ where
|
460 | 471 | ))
|
461 | 472 | }
|
462 | 473 |
|
| 474 | +fn parse_description<'a>(parser: &mut Parser<'a>) -> OptionParseResult<Cow<'a, str>> { |
| 475 | + if !matches!(parser.peek().item, Token::Scalar(ScalarToken::String(_))) { |
| 476 | + Ok(None) |
| 477 | + } else { |
| 478 | + let token = parser.next_token()?; |
| 479 | + let Token::Scalar(ScalarToken::String(lit)) = token.item else { |
| 480 | + unreachable!("already checked to be `ScalarToken::String`") |
| 481 | + }; |
| 482 | + Ok(Some(Spanning::new( |
| 483 | + token.span, |
| 484 | + lit.parse().map_err(|e| Spanning::new(token.span, e))?, |
| 485 | + ))) |
| 486 | + } |
| 487 | +} |
| 488 | + |
463 | 489 | fn parse_directives<'a, S>(
|
464 | 490 | parser: &mut Parser<'a>,
|
465 | 491 | schema: &SchemaType<S>,
|
|
0 commit comments