graphql_tools/parser/query/
format.rs

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