1use combine::combinator::{eof, many1, optional, position};
2use combine::{parser, ParseResult, Parser};
3
4use crate::common::Directive;
5use crate::common::{arguments, default_value, directives, parse_type};
6use crate::helpers::{ident, name, punct};
7use crate::query::ast::*;
8use crate::query::error::ParseError;
9use crate::tokenizer::TokenStream;
10
11pub fn field<'a>(input: &mut TokenStream<'a>) -> ParseResult<Field, TokenStream<'a>> {
12 (
13 position(),
14 name(),
15 optional(punct(":").with(name())),
16 parser(arguments),
17 parser(directives),
18 optional(parser(selection_set)),
19 )
20 .map(
21 |(position, name_or_alias, opt_name, arguments, directives, sel)| {
22 let (name, alias) = match opt_name {
23 Some(name) => (name, Some(name_or_alias)),
24 None => (name_or_alias, None),
25 };
26 Field {
27 position,
28 name,
29 alias,
30 arguments,
31 directives,
32 selection_set: sel.unwrap_or_else(|| SelectionSet {
33 span: (position, position),
34 items: Vec::new(),
35 }),
36 }
37 },
38 )
39 .parse_stream(input)
40}
41
42pub fn selection<'a>(input: &mut TokenStream<'a>) -> ParseResult<Selection, TokenStream<'a>> {
43 parser(field)
44 .map(Selection::Field)
45 .or(punct("...").with(
46 (
47 position(),
48 optional(ident("on").with(name()).map(TypeCondition::On)),
49 parser(directives),
50 parser(selection_set),
51 )
52 .map(
53 |(position, type_condition, directives, selection_set)| InlineFragment {
54 position,
55 type_condition,
56 selection_set,
57 directives,
58 },
59 )
60 .map(Selection::InlineFragment)
61 .or((position(), name(), parser(directives))
62 .map(|(position, fragment_name, directives)| FragmentSpread {
63 position,
64 fragment_name,
65 directives,
66 })
67 .map(Selection::FragmentSpread)),
68 ))
69 .parse_stream(input)
70}
71
72pub fn selection_set<'a>(
73 input: &mut TokenStream<'a>,
74) -> ParseResult<SelectionSet, TokenStream<'a>> {
75 (
76 position().skip(punct("{")),
77 many1(parser(selection)),
78 position().skip(punct("}")),
79 )
80 .map(|(start, items, end)| SelectionSet {
81 span: (start, end),
82 items,
83 })
84 .parse_stream(input)
85}
86
87pub fn query<'a>(input: &mut TokenStream<'a>) -> ParseResult<Query, TokenStream<'a>> {
88 position()
89 .skip(ident("query"))
90 .and(parser(operation_common))
91 .map(
92 |(position, (name, variable_definitions, directives, selection_set))| Query {
93 position,
94 name,
95 selection_set,
96 variable_definitions,
97 directives,
98 },
99 )
100 .parse_stream(input)
101}
102
103type OperationCommon = (
105 Option<String>,
106 Vec<VariableDefinition>,
107 Vec<Directive>,
108 SelectionSet,
109);
110
111pub fn operation_common<'a>(
112 input: &mut TokenStream<'a>,
113) -> ParseResult<OperationCommon, TokenStream<'a>> {
114 optional(name())
115 .and(
116 optional(
117 punct("(")
118 .with(many1(
119 (
120 position(),
121 punct("$").with(name()).skip(punct(":")),
122 parser(parse_type),
123 optional(punct("=").with(parser(default_value))),
124 )
125 .map(
126 |(position, name, var_type, default_value)| VariableDefinition {
127 position,
128 name,
129 var_type,
130 default_value,
131 },
132 ),
133 ))
134 .skip(punct(")")),
135 )
136 .map(|vars| vars.unwrap_or_else(Vec::new)),
137 )
138 .and(parser(directives))
139 .and(parser(selection_set))
140 .map(|(((a, b), c), d)| (a, b, c, d))
141 .parse_stream(input)
142}
143
144pub fn mutation<'a>(input: &mut TokenStream<'a>) -> ParseResult<Mutation, TokenStream<'a>> {
145 position()
146 .skip(ident("mutation"))
147 .and(parser(operation_common))
148 .map(
149 |(position, (name, variable_definitions, directives, selection_set))| Mutation {
150 position,
151 name,
152 selection_set,
153 variable_definitions,
154 directives,
155 },
156 )
157 .parse_stream(input)
158}
159
160pub fn subscription<'a>(input: &mut TokenStream<'a>) -> ParseResult<Subscription, TokenStream<'a>> {
161 position()
162 .skip(ident("subscription"))
163 .and(parser(operation_common))
164 .map(
165 |(position, (name, variable_definitions, directives, selection_set))| Subscription {
166 position,
167 name,
168 selection_set,
169 variable_definitions,
170 directives,
171 },
172 )
173 .parse_stream(input)
174}
175
176pub fn operation_definition<'a>(
177 input: &mut TokenStream<'a>,
178) -> ParseResult<OperationDefinition, TokenStream<'a>> {
179 parser(selection_set)
180 .map(OperationDefinition::SelectionSet)
181 .or(parser(query).map(OperationDefinition::Query))
182 .or(parser(mutation).map(OperationDefinition::Mutation))
183 .or(parser(subscription).map(OperationDefinition::Subscription))
184 .parse_stream(input)
185}
186
187pub fn fragment_definition<'a>(
188 input: &mut TokenStream<'a>,
189) -> ParseResult<FragmentDefinition, TokenStream<'a>> {
190 (
191 position().skip(ident("fragment")),
192 name(),
193 ident("on").with(name()).map(TypeCondition::On),
194 parser(directives),
195 parser(selection_set),
196 )
197 .map(
198 |(position, name, type_condition, directives, selection_set)| FragmentDefinition {
199 position,
200 name,
201 type_condition,
202 directives,
203 selection_set,
204 },
205 )
206 .parse_stream(input)
207}
208
209pub fn definition<'a>(input: &mut TokenStream<'a>) -> ParseResult<Definition, TokenStream<'a>> {
210 parser(operation_definition)
211 .map(Definition::Operation)
212 .or(parser(fragment_definition).map(Definition::Fragment))
213 .parse_stream(input)
214}
215
216pub fn parse_query(s: &str) -> Result<Document, ParseError> {
218 let mut tokens = TokenStream::new(s);
219 let (doc, _) = many1(parser(definition))
220 .map(|d| Document { definitions: d })
221 .skip(eof())
222 .parse_stream(&mut tokens)
223 .map_err(|e| e.into_inner().error)?;
224
225 Ok(doc)
226}
227
228pub fn consume_definition<'a>(s: &'a str) -> Result<(Definition, &'a str), ParseError> {
231 let tokens = TokenStream::new(s);
232 let (doc, tokens) = parser(definition).parse(tokens)?;
233
234 Ok((doc, &s[tokens.offset()..]))
235}
236
237#[cfg(test)]
238mod test {
239 use super::{consume_definition, parse_query};
240 use crate::position::Pos;
241 use crate::query::grammar::*;
242
243 fn ast(s: &str) -> Document {
244 parse_query(s).unwrap()
245 }
246
247 #[test]
248 fn one_field() {
249 assert_eq!(
250 ast("{ a }"),
251 Document {
252 definitions: vec![Definition::Operation(OperationDefinition::SelectionSet(
253 SelectionSet {
254 span: (Pos { line: 1, column: 1 }, Pos { line: 1, column: 5 }),
255 items: vec![Selection::Field(Field {
256 position: Pos { line: 1, column: 3 },
257 alias: None,
258 name: "a".into(),
259 arguments: Vec::new(),
260 directives: Vec::new(),
261 selection_set: SelectionSet {
262 span: (Pos { line: 1, column: 3 }, Pos { line: 1, column: 3 }),
263 items: Vec::new()
264 },
265 }),],
266 }
267 ))],
268 }
269 );
270 }
271
272 #[test]
273 fn builtin_values() {
274 assert_eq!(
275 ast("{ a(t: true, f: false, n: null) }"),
276 Document {
277 definitions: vec![Definition::Operation(OperationDefinition::SelectionSet(
278 SelectionSet {
279 span: (
280 Pos { line: 1, column: 1 },
281 Pos {
282 line: 1,
283 column: 33
284 }
285 ),
286 items: vec![Selection::Field(Field {
287 position: Pos { line: 1, column: 3 },
288 alias: None,
289 name: "a".into(),
290 arguments: vec![
291 ("t".to_string(), Value::Boolean(true)),
292 ("f".to_string(), Value::Boolean(false)),
293 ("n".to_string(), Value::Null),
294 ],
295 directives: Vec::new(),
296 selection_set: SelectionSet {
297 span: (Pos { line: 1, column: 3 }, Pos { line: 1, column: 3 }),
298 items: Vec::new()
299 },
300 }),],
301 }
302 ))],
303 }
304 );
305 }
306
307 #[test]
308 fn one_field_roundtrip() {
309 assert_eq!(ast("{ a }").to_string(), "{\n a\n}\n");
310 }
311
312 #[test]
313 #[should_panic(expected = "number too large")]
314 fn large_integer() {
315 ast("{ a(x: 10000000000000000000000000000 }");
316 }
317
318 #[test]
319 fn consume_single_query() {
320 let (query, remainder) = consume_definition("query { a } query { b }").unwrap();
321 assert!(matches!(query, Definition::Operation(_)));
322 assert_eq!(remainder, "query { b }");
323 }
324
325 #[test]
326 fn consume_full_text() {
327 let (query, remainder) = consume_definition("query { a }").unwrap();
328 assert!(matches!(query, Definition::Operation(_)));
329 assert_eq!(remainder, "");
330 }
331
332 #[test]
333 fn consume_single_query_preceding_non_graphql() {
334 let (query, remainder) = consume_definition("query { a } where a > 1 => 10.0").unwrap();
335 assert!(matches!(query, Definition::Operation(_)));
336 assert_eq!(remainder, "where a > 1 => 10.0");
337 }
338
339 #[test]
340 fn consume_fails_without_operation() {
341 let err = consume_definition("where a > 1 => 10.0")
342 .expect_err("Expected parse to fail with an error");
343 let err = format!("{}", err);
344 assert_eq!(err, "query parse error: Parse error at 1:1\nUnexpected `where[Name]`\nExpected `{`, `query`, `mutation`, `subscription` or `fragment`\n");
345 }
346
347 #[test]
348 fn recursion_too_deep() {
349 let query = format!(
350 "{}(b: {}{}){}",
351 "{ a".repeat(30),
352 "[".repeat(25),
353 "]".repeat(25),
354 "}".repeat(30)
355 );
356 let result = parse_query(&query);
357 let err = format!("{}", result.unwrap_err());
358 assert_eq!(
359 &err,
360 "query parse error: Parse error at 1:114\nExpected `]`\nRecursion limit exceeded\n"
361 )
362 }
363}