fuel_indexer_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>>(
113    arguments: &[(T::Value, Value<'a, T>)],
114    f: &mut Formatter,
115) where
116    T: Text<'a>,
117{
118    if !arguments.is_empty() {
119        f.start_argument_block('(');
120        f.start_argument();
121        f.write(arguments[0].0.as_ref());
122        f.write(": ");
123        arguments[0].1.display(f);
124        for arg in &arguments[1..] {
125            f.deliniate_argument();
126            f.start_argument();
127            f.write(arg.0.as_ref());
128            f.write(": ");
129            arg.1.display(f);
130        }
131        f.end_argument_block(')');
132    }
133}
134
135impl<'a, T: Text<'a>> Displayable for Field<'a, T>
136where
137    T: Text<'a>,
138{
139    fn display(&self, f: &mut Formatter) {
140        f.indent();
141        if let Some(ref alias) = self.alias {
142            f.write(alias.as_ref());
143            f.write(": ");
144        }
145        f.write(self.name.as_ref());
146        format_arguments(&self.arguments, f);
147        format_directives(&self.directives, f);
148        if !self.selection_set.items.is_empty() {
149            f.write(" ");
150            f.start_block();
151            for item in &self.selection_set.items {
152                item.display(f);
153            }
154            f.end_block();
155        } else {
156            f.endline();
157        }
158    }
159}
160
161impl<'a, T: Text<'a>> Displayable for Query<'a, T>
162where
163    T: Text<'a>,
164{
165    fn display(&self, f: &mut Formatter) {
166        f.margin();
167        f.indent();
168        f.write("query");
169        if let Some(ref name) = self.name {
170            f.write(" ");
171            f.write(name.as_ref());
172        }
173        if !self.variable_definitions.is_empty() {
174            f.write("(");
175            self.variable_definitions[0].display(f);
176            for var in &self.variable_definitions[1..] {
177                f.write(", ");
178                var.display(f);
179            }
180            f.write(")");
181        }
182        format_directives(&self.directives, f);
183        f.write(" ");
184        f.start_block();
185        for item in &self.selection_set.items {
186            item.display(f);
187        }
188        f.end_block();
189    }
190}
191
192impl<'a, T: Text<'a>> Displayable for Mutation<'a, T>
193where
194    T: Text<'a>,
195{
196    fn display(&self, f: &mut Formatter) {
197        f.margin();
198        f.indent();
199        f.write("mutation");
200        if let Some(ref name) = self.name {
201            f.write(" ");
202            f.write(name.as_ref());
203        }
204        if !self.variable_definitions.is_empty() {
205            f.write("(");
206            self.variable_definitions[0].display(f);
207            for var in &self.variable_definitions[1..] {
208                f.write(", ");
209                var.display(f);
210            }
211            f.write(")");
212        }
213        format_directives(&self.directives, f);
214        f.write(" ");
215        f.start_block();
216        for item in &self.selection_set.items {
217            item.display(f);
218        }
219        f.end_block();
220    }
221}
222
223impl<'a, T: Text<'a>> Displayable for Subscription<'a, T>
224where
225    T: Text<'a>,
226{
227    fn display(&self, f: &mut Formatter) {
228        f.margin();
229        f.indent();
230        f.write("subscription");
231        if let Some(ref name) = self.name {
232            f.write(" ");
233            f.write(name.as_ref());
234            if !self.variable_definitions.is_empty() {
235                f.write("(");
236                for var in &self.variable_definitions {
237                    var.display(f);
238                }
239                f.write(")");
240            }
241        }
242        format_directives(&self.directives, f);
243        f.write(" ");
244        f.start_block();
245        for item in &self.selection_set.items {
246            item.display(f);
247        }
248        f.end_block();
249    }
250}
251
252impl<'a, T: Text<'a>> Displayable for VariableDefinition<'a, T>
253where
254    T: Text<'a>,
255{
256    fn display(&self, f: &mut Formatter) {
257        f.write("$");
258        f.write(self.name.as_ref());
259        f.write(": ");
260        self.var_type.display(f);
261        if let Some(ref default) = self.default_value {
262            f.write(" = ");
263            default.display(f);
264        }
265    }
266}
267
268impl<'a, T: Text<'a>> Displayable for Type<'a, T>
269where
270    T: Text<'a>,
271{
272    fn display(&self, f: &mut Formatter) {
273        match *self {
274            Type::NamedType(ref name) => f.write(name.as_ref()),
275            Type::ListType(ref typ) => {
276                f.write("[");
277                typ.display(f);
278                f.write("]");
279            }
280            Type::NonNullType(ref typ) => {
281                typ.display(f);
282                f.write("!");
283            }
284        }
285    }
286}
287
288impl<'a, T: Text<'a>> Displayable for Value<'a, T>
289where
290    T: Text<'a>,
291{
292    fn display(&self, f: &mut Formatter) {
293        match *self {
294            Value::Variable(ref name) => {
295                f.write("$");
296                f.write(name.as_ref());
297            }
298            Value::BigInt(ref num) => f.write(&format!("{}", num.0)),
299            Value::Int(ref num) => f.write(&format!("{}", num.0)),
300            Value::Float(val) => f.write(&format!("{}", val)),
301            Value::String(ref val) => f.write_quoted(val),
302            Value::Boolean(true) => f.write("true"),
303            Value::Boolean(false) => f.write("false"),
304            Value::Null => f.write("null"),
305            Value::Enum(ref name) => f.write(name.as_ref()),
306            Value::List(ref items) => {
307                f.start_argument_block('[');
308                if !items.is_empty() {
309                    f.start_argument();
310                    items[0].display(f);
311                    for item in &items[1..] {
312                        f.deliniate_argument();
313                        f.start_argument();
314                        item.display(f);
315                    }
316                }
317                f.end_argument_block(']');
318            }
319            Value::Object(ref items) => {
320                f.start_argument_block('{');
321                let mut first = true;
322                for (name, value) in items.iter() {
323                    if first {
324                        first = false;
325                    } else {
326                        f.deliniate_argument();
327                    }
328                    f.start_argument();
329                    f.write(name.as_ref());
330                    f.write(": ");
331                    value.display(f);
332                }
333                f.end_argument_block('}');
334            }
335        }
336    }
337}
338
339impl<'a, T: Text<'a>> Displayable for InlineFragment<'a, T>
340where
341    T: Text<'a>,
342{
343    fn display(&self, f: &mut Formatter) {
344        f.indent();
345        f.write("...");
346        if let Some(ref cond) = self.type_condition {
347            f.write(" ");
348            cond.display(f);
349        }
350        format_directives(&self.directives, f);
351        f.write(" ");
352        f.start_block();
353        for item in &self.selection_set.items {
354            item.display(f);
355        }
356        f.end_block();
357    }
358}
359
360impl<'a, T: Text<'a>> Displayable for TypeCondition<'a, T>
361where
362    T: Text<'a>,
363{
364    fn display(&self, f: &mut Formatter) {
365        match *self {
366            TypeCondition::On(ref name) => {
367                f.write("on ");
368                f.write(name.as_ref());
369            }
370        }
371    }
372}
373
374impl<'a, T: Text<'a>> Displayable for FragmentSpread<'a, T>
375where
376    T: Text<'a>,
377{
378    fn display(&self, f: &mut Formatter) {
379        f.indent();
380        f.write("...");
381        f.write(self.fragment_name.as_ref());
382        format_directives(&self.directives, f);
383        f.endline();
384    }
385}
386
387impl<'a, T: Text<'a>> Displayable for Directive<'a, T>
388where
389    T: Text<'a>,
390{
391    fn display(&self, f: &mut Formatter) {
392        f.write("@");
393        f.write(self.name.as_ref());
394        format_arguments(self.arguments.as_slice(), f);
395    }
396}
397
398impl_display!(
399    'a
400    Document,
401    Definition,
402    OperationDefinition,
403    FragmentDefinition,
404    SelectionSet,
405    Field,
406    Query,
407    Mutation,
408    Subscription,
409    VariableDefinition,
410    Type,
411    Value,
412    InlineFragment,
413    TypeCondition,
414    FragmentSpread,
415    Directive,
416);