graphql_parser/query/
format.rs

1use std::fmt;
2
3use crate::format::{format_directives, Displayable, Formatter, Style};
4
5use crate::query::ast::*;
6
7impl<'a, T: Text<'a>> Document<'a, T>
8where
9    T: Text<'a>,
10{
11    /// Format a document according to style
12    pub fn format(&self, style: &Style) -> String {
13        let mut formatter = Formatter::new(style);
14        self.display(&mut formatter);
15        formatter.into_string()
16    }
17}
18
19fn to_string<T: Displayable>(v: &T) -> String {
20    let style = Style::default();
21    let mut formatter = Formatter::new(&style);
22    v.display(&mut formatter);
23    formatter.into_string()
24}
25
26impl<'a, T: Text<'a>> Displayable for Document<'a, T>
27where
28    T: Text<'a>,
29{
30    fn display(&self, f: &mut Formatter) {
31        for item in &self.definitions {
32            item.display(f);
33        }
34    }
35}
36
37impl<'a, T: Text<'a>> Displayable for Definition<'a, T>
38where
39    T: Text<'a>,
40{
41    fn display(&self, f: &mut Formatter) {
42        match *self {
43            Definition::Operation(ref op) => op.display(f),
44            Definition::Fragment(ref frag) => frag.display(f),
45        }
46    }
47}
48
49impl<'a, T: Text<'a>> Displayable for OperationDefinition<'a, T>
50where
51    T: Text<'a>,
52{
53    fn display(&self, f: &mut Formatter) {
54        match *self {
55            OperationDefinition::SelectionSet(ref set) => set.display(f),
56            OperationDefinition::Query(ref q) => q.display(f),
57            OperationDefinition::Mutation(ref m) => m.display(f),
58            OperationDefinition::Subscription(ref s) => s.display(f),
59        }
60    }
61}
62
63impl<'a, T: Text<'a>> Displayable for FragmentDefinition<'a, T>
64where
65    T: Text<'a>,
66{
67    fn display(&self, f: &mut Formatter) {
68        f.margin();
69        f.indent();
70        f.write("fragment ");
71        f.write(self.name.as_ref());
72        f.write(" ");
73        self.type_condition.display(f);
74        format_directives(&self.directives, f);
75        f.write(" ");
76        f.start_block();
77        for item in &self.selection_set.items {
78            item.display(f);
79        }
80        f.end_block();
81    }
82}
83
84impl<'a, T: Text<'a>> Displayable for SelectionSet<'a, T>
85where
86    T: Text<'a>,
87{
88    fn display(&self, f: &mut Formatter) {
89        f.margin();
90        f.indent();
91        f.start_block();
92        for item in &self.items {
93            item.display(f);
94        }
95        f.end_block();
96    }
97}
98
99impl<'a, T: Text<'a>> Displayable for Selection<'a, T>
100where
101    T: Text<'a>,
102{
103    fn display(&self, f: &mut Formatter) {
104        match *self {
105            Selection::Field(ref fld) => fld.display(f),
106            Selection::InlineFragment(ref frag) => frag.display(f),
107            Selection::FragmentSpread(ref frag) => frag.display(f),
108        }
109    }
110}
111
112fn format_arguments<'a, T: Text<'a>>(arguments: &[(T::Value, Value<'a, T>)], f: &mut Formatter)
113where
114    T: Text<'a>,
115{
116    if !arguments.is_empty() {
117        f.start_argument_block('(');
118        f.start_argument();
119        f.write(arguments[0].0.as_ref());
120        f.write(": ");
121        arguments[0].1.display(f);
122        for arg in &arguments[1..] {
123            f.deliniate_argument();
124            f.start_argument();
125            f.write(arg.0.as_ref());
126            f.write(": ");
127            arg.1.display(f);
128        }
129        f.end_argument_block(')');
130    }
131}
132
133impl<'a, T: Text<'a>> Displayable for Field<'a, T>
134where
135    T: Text<'a>,
136{
137    fn display(&self, f: &mut Formatter) {
138        f.indent();
139        if let Some(ref alias) = self.alias {
140            f.write(alias.as_ref());
141            f.write(": ");
142        }
143        f.write(self.name.as_ref());
144        format_arguments(&self.arguments, f);
145        format_directives(&self.directives, f);
146        if !self.selection_set.items.is_empty() {
147            f.write(" ");
148            f.start_block();
149            for item in &self.selection_set.items {
150                item.display(f);
151            }
152            f.end_block();
153        } else {
154            f.endline();
155        }
156    }
157}
158
159impl<'a, T: Text<'a>> Displayable for Query<'a, T>
160where
161    T: Text<'a>,
162{
163    fn display(&self, f: &mut Formatter) {
164        f.margin();
165        f.indent();
166        f.write("query");
167        if let Some(ref name) = self.name {
168            f.write(" ");
169            f.write(name.as_ref());
170        }
171        if !self.variable_definitions.is_empty() {
172            f.write("(");
173            self.variable_definitions[0].display(f);
174            for var in &self.variable_definitions[1..] {
175                f.write(", ");
176                var.display(f);
177            }
178            f.write(")");
179        }
180        format_directives(&self.directives, f);
181        f.write(" ");
182        f.start_block();
183        for item in &self.selection_set.items {
184            item.display(f);
185        }
186        f.end_block();
187    }
188}
189
190impl<'a, T: Text<'a>> Displayable for Mutation<'a, T>
191where
192    T: Text<'a>,
193{
194    fn display(&self, f: &mut Formatter) {
195        f.margin();
196        f.indent();
197        f.write("mutation");
198        if let Some(ref name) = self.name {
199            f.write(" ");
200            f.write(name.as_ref());
201        }
202        if !self.variable_definitions.is_empty() {
203            f.write("(");
204            self.variable_definitions[0].display(f);
205            for var in &self.variable_definitions[1..] {
206                f.write(", ");
207                var.display(f);
208            }
209            f.write(")");
210        }
211        format_directives(&self.directives, f);
212        f.write(" ");
213        f.start_block();
214        for item in &self.selection_set.items {
215            item.display(f);
216        }
217        f.end_block();
218    }
219}
220
221impl<'a, T: Text<'a>> Displayable for Subscription<'a, T>
222where
223    T: Text<'a>,
224{
225    fn display(&self, f: &mut Formatter) {
226        f.margin();
227        f.indent();
228        f.write("subscription");
229        if let Some(ref name) = self.name {
230            f.write(" ");
231            f.write(name.as_ref());
232            if !self.variable_definitions.is_empty() {
233                f.write("(");
234                for var in &self.variable_definitions {
235                    var.display(f);
236                }
237                f.write(")");
238            }
239        }
240        format_directives(&self.directives, f);
241        f.write(" ");
242        f.start_block();
243        for item in &self.selection_set.items {
244            item.display(f);
245        }
246        f.end_block();
247    }
248}
249
250impl<'a, T: Text<'a>> Displayable for VariableDefinition<'a, T>
251where
252    T: Text<'a>,
253{
254    fn display(&self, f: &mut Formatter) {
255        f.write("$");
256        f.write(self.name.as_ref());
257        f.write(": ");
258        self.var_type.display(f);
259        if let Some(ref default) = self.default_value {
260            f.write(" = ");
261            default.display(f);
262        }
263    }
264}
265
266impl<'a, T: Text<'a>> Displayable for Type<'a, T>
267where
268    T: Text<'a>,
269{
270    fn display(&self, f: &mut Formatter) {
271        match *self {
272            Type::NamedType(ref name) => f.write(name.as_ref()),
273            Type::ListType(ref typ) => {
274                f.write("[");
275                typ.display(f);
276                f.write("]");
277            }
278            Type::NonNullType(ref typ) => {
279                typ.display(f);
280                f.write("!");
281            }
282        }
283    }
284}
285
286impl<'a, T: Text<'a>> Displayable for Value<'a, T>
287where
288    T: Text<'a>,
289{
290    fn display(&self, f: &mut Formatter) {
291        match *self {
292            Value::Variable(ref name) => {
293                f.write("$");
294                f.write(name.as_ref());
295            }
296            Value::Int(ref num) => f.write(&format!("{}", num.0)),
297            Value::Float(val) => f.write(&format!("{}", val)),
298            Value::String(ref val) => f.write_quoted(val),
299            Value::Boolean(true) => f.write("true"),
300            Value::Boolean(false) => f.write("false"),
301            Value::Null => f.write("null"),
302            Value::Enum(ref name) => f.write(name.as_ref()),
303            Value::List(ref items) => {
304                f.start_argument_block('[');
305                if !items.is_empty() {
306                    f.start_argument();
307                    items[0].display(f);
308                    for item in &items[1..] {
309                        f.deliniate_argument();
310                        f.start_argument();
311                        item.display(f);
312                    }
313                }
314                f.end_argument_block(']');
315            }
316            Value::Object(ref items) => {
317                f.start_argument_block('{');
318                let mut first = true;
319                for (name, value) in items.iter() {
320                    if first {
321                        first = false;
322                    } else {
323                        f.deliniate_argument();
324                    }
325                    f.start_argument();
326                    f.write(name.as_ref());
327                    f.write(": ");
328                    value.display(f);
329                }
330                f.end_argument_block('}');
331            }
332        }
333    }
334}
335
336impl<'a, T: Text<'a>> Displayable for InlineFragment<'a, T>
337where
338    T: Text<'a>,
339{
340    fn display(&self, f: &mut Formatter) {
341        f.indent();
342        f.write("...");
343        if let Some(ref cond) = self.type_condition {
344            f.write(" ");
345            cond.display(f);
346        }
347        format_directives(&self.directives, f);
348        f.write(" ");
349        f.start_block();
350        for item in &self.selection_set.items {
351            item.display(f);
352        }
353        f.end_block();
354    }
355}
356
357impl<'a, T: Text<'a>> Displayable for TypeCondition<'a, T>
358where
359    T: Text<'a>,
360{
361    fn display(&self, f: &mut Formatter) {
362        match *self {
363            TypeCondition::On(ref name) => {
364                f.write("on ");
365                f.write(name.as_ref());
366            }
367        }
368    }
369}
370
371impl<'a, T: Text<'a>> Displayable for FragmentSpread<'a, T>
372where
373    T: Text<'a>,
374{
375    fn display(&self, f: &mut Formatter) {
376        f.indent();
377        f.write("...");
378        f.write(self.fragment_name.as_ref());
379        format_directives(&self.directives, f);
380        f.endline();
381    }
382}
383
384impl<'a, T: Text<'a>> Displayable for Directive<'a, T>
385where
386    T: Text<'a>,
387{
388    fn display(&self, f: &mut Formatter) {
389        f.write("@");
390        f.write(self.name.as_ref());
391        format_arguments(self.arguments.as_slice(), f);
392    }
393}
394
395impl_display!(
396    'a
397    Document,
398    Definition,
399    OperationDefinition,
400    FragmentDefinition,
401    SelectionSet,
402    Field,
403    Query,
404    Mutation,
405    Subscription,
406    VariableDefinition,
407    Type,
408    Value,
409    InlineFragment,
410    TypeCondition,
411    FragmentSpread,
412    Directive,
413);