graphql_parser/schema/
format.rs

1use std::fmt;
2
3use crate::common::Text;
4use crate::format::{format_directives, Displayable, Formatter, Style};
5
6use crate::schema::ast::*;
7
8impl<'a, T> Document<'a, T>
9where
10    T: Text<'a>,
11{
12    /// Format a document according to style
13    pub fn format(&self, style: &Style) -> String {
14        let mut formatter = Formatter::new(style);
15        self.display(&mut formatter);
16        formatter.into_string()
17    }
18}
19
20fn to_string<T: Displayable>(v: &T) -> String {
21    let style = Style::default();
22    let mut formatter = Formatter::new(&style);
23    v.display(&mut formatter);
24    formatter.into_string()
25}
26
27fn description(description: &Option<String>, f: &mut Formatter) {
28    if let Some(ref descr) = *description {
29        f.indent();
30        f.write_quoted(descr.as_ref());
31        f.endline();
32    }
33}
34
35impl<'a, T> Displayable for Document<'a, T>
36where
37    T: Text<'a>,
38{
39    fn display(&self, f: &mut Formatter) {
40        for item in &self.definitions {
41            item.display(f);
42        }
43    }
44}
45
46impl<'a, T> Displayable for Definition<'a, T>
47where
48    T: Text<'a>,
49{
50    fn display(&self, f: &mut Formatter) {
51        f.margin();
52        match *self {
53            Definition::SchemaDefinition(ref s) => s.display(f),
54            Definition::TypeDefinition(ref t) => t.display(f),
55            Definition::TypeExtension(ref e) => e.display(f),
56            Definition::DirectiveDefinition(ref d) => d.display(f),
57        }
58    }
59}
60
61impl<'a, T> Displayable for SchemaDefinition<'a, T>
62where
63    T: Text<'a>,
64{
65    fn display(&self, f: &mut Formatter) {
66        f.indent();
67        f.write("schema");
68        format_directives(&self.directives, f);
69        f.write(" ");
70        f.start_block();
71        if let Some(ref q) = self.query {
72            f.indent();
73            f.write("query: ");
74            f.write(q.as_ref());
75            f.endline();
76        }
77        if let Some(ref m) = self.mutation {
78            f.indent();
79            f.write("mutation: ");
80            f.write(m.as_ref());
81            f.endline();
82        }
83        if let Some(ref s) = self.subscription {
84            f.indent();
85            f.write("subscription: ");
86            f.write(s.as_ref());
87            f.endline();
88        }
89        f.end_block();
90    }
91}
92
93impl<'a, T> Displayable for TypeDefinition<'a, T>
94where
95    T: Text<'a>,
96{
97    fn display(&self, f: &mut Formatter) {
98        match *self {
99            TypeDefinition::Scalar(ref s) => s.display(f),
100            TypeDefinition::Object(ref o) => o.display(f),
101            TypeDefinition::Interface(ref i) => i.display(f),
102            TypeDefinition::Union(ref u) => u.display(f),
103            TypeDefinition::Enum(ref e) => e.display(f),
104            TypeDefinition::InputObject(ref i) => i.display(f),
105        }
106    }
107}
108
109impl<'a, T> Displayable for ScalarType<'a, T>
110where
111    T: Text<'a>,
112{
113    fn display(&self, f: &mut Formatter) {
114        description(&self.description, f);
115        f.indent();
116        f.write("scalar ");
117        f.write(self.name.as_ref());
118        format_directives(&self.directives, f);
119        f.endline();
120    }
121}
122
123impl<'a, T> Displayable for ScalarTypeExtension<'a, T>
124where
125    T: Text<'a>,
126{
127    fn display(&self, f: &mut Formatter) {
128        f.indent();
129        f.write("extend scalar ");
130        f.write(self.name.as_ref());
131        format_directives(&self.directives, f);
132        f.endline();
133    }
134}
135
136fn format_fields<'a, T>(fields: &[Field<'a, T>], f: &mut Formatter)
137where
138    T: Text<'a>,
139{
140    if !fields.is_empty() {
141        f.write(" ");
142        f.start_block();
143        for fld in fields {
144            fld.display(f);
145        }
146        f.end_block();
147    } else {
148        f.endline();
149    }
150}
151
152impl<'a, T> Displayable for ObjectType<'a, T>
153where
154    T: Text<'a>,
155{
156    fn display(&self, f: &mut Formatter) {
157        description(&self.description, f);
158        f.indent();
159        f.write("type ");
160        f.write(self.name.as_ref());
161        if !self.implements_interfaces.is_empty() {
162            f.write(" implements ");
163            f.write(self.implements_interfaces[0].as_ref());
164            for name in &self.implements_interfaces[1..] {
165                f.write(" & ");
166                f.write(name.as_ref());
167            }
168        }
169        format_directives(&self.directives, f);
170        format_fields(&self.fields, f);
171    }
172}
173
174impl<'a, T> Displayable for ObjectTypeExtension<'a, T>
175where
176    T: Text<'a>,
177{
178    fn display(&self, f: &mut Formatter) {
179        f.indent();
180        f.write("extend type ");
181        f.write(self.name.as_ref());
182        if !self.implements_interfaces.is_empty() {
183            f.write(" implements ");
184            f.write(self.implements_interfaces[0].as_ref());
185            for name in &self.implements_interfaces[1..] {
186                f.write(" & ");
187                f.write(name.as_ref());
188            }
189        }
190        format_directives(&self.directives, f);
191        format_fields(&self.fields, f);
192    }
193}
194
195impl<'a, T> Displayable for InputValue<'a, T>
196where
197    T: Text<'a>,
198{
199    fn display(&self, f: &mut Formatter) {
200        if let Some(ref descr) = self.description {
201            f.write_quoted(descr.as_ref());
202            f.write(" ");
203        }
204        f.write(self.name.as_ref());
205        f.write(": ");
206        self.value_type.display(f);
207        if let Some(ref def) = self.default_value {
208            f.write(" = ");
209            def.display(f);
210        }
211        format_directives(&self.directives, f);
212    }
213}
214
215fn format_arguments<'a, T>(arguments: &[InputValue<'a, T>], f: &mut Formatter)
216where
217    T: Text<'a>,
218{
219    if !arguments.is_empty() {
220        f.write("(");
221        arguments[0].display(f);
222        for arg in &arguments[1..] {
223            f.write(", ");
224            arg.display(f);
225        }
226        f.write(")");
227    }
228}
229
230impl<'a, T> Displayable for Field<'a, T>
231where
232    T: Text<'a>,
233{
234    fn display(&self, f: &mut Formatter) {
235        description(&self.description, f);
236        f.indent();
237        f.write(self.name.as_ref());
238        format_arguments(&self.arguments, f);
239        f.write(": ");
240        self.field_type.display(f);
241        format_directives(&self.directives, f);
242        f.endline();
243    }
244}
245
246impl<'a, T> Displayable for InterfaceType<'a, T>
247where
248    T: Text<'a>,
249{
250    fn display(&self, f: &mut Formatter) {
251        description(&self.description, f);
252        f.indent();
253        f.write("interface ");
254        f.write(self.name.as_ref());
255        if !self.implements_interfaces.is_empty() {
256            f.write(" implements ");
257            f.write(self.implements_interfaces[0].as_ref());
258            for name in &self.implements_interfaces[1..] {
259                f.write(" & ");
260                f.write(name.as_ref());
261            }
262        }
263        format_directives(&self.directives, f);
264        format_fields(&self.fields, f);
265    }
266}
267
268impl<'a, T> Displayable for InterfaceTypeExtension<'a, T>
269where
270    T: Text<'a>,
271{
272    fn display(&self, f: &mut Formatter) {
273        f.indent();
274        f.write("extend interface ");
275        f.write(self.name.as_ref());
276        if !self.implements_interfaces.is_empty() {
277            f.write(" implements ");
278            f.write(self.implements_interfaces[0].as_ref());
279            for name in &self.implements_interfaces[1..] {
280                f.write(" & ");
281                f.write(name.as_ref());
282            }
283        }
284        format_directives(&self.directives, f);
285        format_fields(&self.fields, f);
286    }
287}
288
289impl<'a, T> Displayable for UnionType<'a, T>
290where
291    T: Text<'a>,
292{
293    fn display(&self, f: &mut Formatter) {
294        description(&self.description, f);
295        f.indent();
296        f.write("union ");
297        f.write(self.name.as_ref());
298        format_directives(&self.directives, f);
299        if !self.types.is_empty() {
300            f.write(" = ");
301            f.write(self.types[0].as_ref());
302            for typ in &self.types[1..] {
303                f.write(" | ");
304                f.write(typ.as_ref());
305            }
306        }
307        f.endline();
308    }
309}
310
311impl<'a, T> Displayable for UnionTypeExtension<'a, T>
312where
313    T: Text<'a>,
314{
315    fn display(&self, f: &mut Formatter) {
316        f.indent();
317        f.write("extend union ");
318        f.write(self.name.as_ref());
319        format_directives(&self.directives, f);
320        if !self.types.is_empty() {
321            f.write(" = ");
322            f.write(self.types[0].as_ref());
323            for typ in &self.types[1..] {
324                f.write(" | ");
325                f.write(typ.as_ref());
326            }
327        }
328        f.endline();
329    }
330}
331
332impl<'a, T> Displayable for EnumType<'a, T>
333where
334    T: Text<'a>,
335{
336    fn display(&self, f: &mut Formatter) {
337        description(&self.description, f);
338        f.indent();
339        f.write("enum ");
340        f.write(self.name.as_ref());
341        format_directives(&self.directives, f);
342        if !self.values.is_empty() {
343            f.write(" ");
344            f.start_block();
345            for val in &self.values {
346                f.indent();
347                if let Some(ref descr) = val.description {
348                    f.write_quoted(descr.as_ref());
349                    f.write(" ");
350                }
351                f.write(val.name.as_ref());
352                format_directives(&val.directives, f);
353                f.endline();
354            }
355            f.end_block();
356        } else {
357            f.endline();
358        }
359    }
360}
361
362impl<'a, T> Displayable for EnumTypeExtension<'a, T>
363where
364    T: Text<'a>,
365{
366    fn display(&self, f: &mut Formatter) {
367        f.indent();
368        f.write("extend enum ");
369        f.write(self.name.as_ref());
370        format_directives(&self.directives, f);
371        if !self.values.is_empty() {
372            f.write(" ");
373            f.start_block();
374            for val in &self.values {
375                f.indent();
376                if let Some(ref descr) = val.description {
377                    f.write_quoted(descr.as_ref());
378                    f.write(" ");
379                }
380                f.write(val.name.as_ref());
381                format_directives(&val.directives, f);
382                f.endline();
383            }
384            f.end_block();
385        } else {
386            f.endline();
387        }
388    }
389}
390
391fn format_inputs<'a, T>(fields: &[InputValue<'a, T>], f: &mut Formatter)
392where
393    T: Text<'a>,
394{
395    if !fields.is_empty() {
396        f.write(" ");
397        f.start_block();
398        for fld in fields {
399            f.indent();
400            fld.display(f);
401            f.endline();
402        }
403        f.end_block();
404    } else {
405        f.endline();
406    }
407}
408
409impl<'a, T> Displayable for InputObjectType<'a, T>
410where
411    T: Text<'a>,
412{
413    fn display(&self, f: &mut Formatter) {
414        description(&self.description, f);
415        f.indent();
416        f.write("input ");
417        f.write(self.name.as_ref());
418        format_directives(&self.directives, f);
419        format_inputs(&self.fields, f);
420    }
421}
422
423impl<'a, T> Displayable for InputObjectTypeExtension<'a, T>
424where
425    T: Text<'a>,
426{
427    fn display(&self, f: &mut Formatter) {
428        f.indent();
429        f.write("extend input ");
430        f.write(self.name.as_ref());
431        format_directives(&self.directives, f);
432        format_inputs(&self.fields, f);
433    }
434}
435
436impl<'a, T> Displayable for TypeExtension<'a, T>
437where
438    T: Text<'a>,
439{
440    fn display(&self, f: &mut Formatter) {
441        match *self {
442            TypeExtension::Scalar(ref s) => s.display(f),
443            TypeExtension::Object(ref o) => o.display(f),
444            TypeExtension::Interface(ref i) => i.display(f),
445            TypeExtension::Union(ref u) => u.display(f),
446            TypeExtension::Enum(ref e) => e.display(f),
447            TypeExtension::InputObject(ref i) => i.display(f),
448        }
449    }
450}
451
452impl<'a, T> Displayable for DirectiveDefinition<'a, T>
453where
454    T: Text<'a>,
455{
456    fn display(&self, f: &mut Formatter) {
457        description(&self.description, f);
458        f.indent();
459        f.write("directive @");
460        f.write(self.name.as_ref());
461        format_arguments(&self.arguments, f);
462        if self.repeatable {
463            f.write(" repeatable");
464        }
465        if !self.locations.is_empty() {
466            f.write(" on ");
467            let mut first = true;
468            for loc in &self.locations {
469                if first {
470                    first = false;
471                } else {
472                    f.write(" | ");
473                }
474                f.write(loc.as_str());
475            }
476        }
477        f.endline();
478    }
479}
480
481impl_display!(
482    'a
483    Document,
484    Definition,
485    SchemaDefinition,
486    TypeDefinition,
487    TypeExtension,
488    ScalarType,
489    ScalarTypeExtension,
490    ObjectType,
491    ObjectTypeExtension,
492    Field,
493    InputValue,
494    InterfaceType,
495    InterfaceTypeExtension,
496    UnionType,
497    UnionTypeExtension,
498    EnumType,
499    EnumTypeExtension,
500    InputObjectType,
501    InputObjectTypeExtension,
502    DirectiveDefinition,
503);