1package printer
2
3import (
4 "fmt"
5 "strings"
6
7 "github.com/graphql-go/graphql/language/ast"
8 "github.com/graphql-go/graphql/language/visitor"
9 "reflect"
10)
11
12func getMapValue(m map[string]interface{}, key string) interface{} {
13 tokens := strings.Split(key, ".")
14 valMap := m
15 for _, token := range tokens {
16 v, ok := valMap[token]
17 if !ok {
18 return nil
19 }
20 switch v := v.(type) {
21 case []interface{}:
22 return v
23 case map[string]interface{}:
24 valMap = v
25 continue
26 default:
27 return v
28 }
29 }
30 return valMap
31}
32func getMapSliceValue(m map[string]interface{}, key string) []interface{} {
33 tokens := strings.Split(key, ".")
34 valMap := m
35 for _, token := range tokens {
36 v, ok := valMap[token]
37 if !ok {
38 return []interface{}{}
39 }
40 switch v := v.(type) {
41 case []interface{}:
42 return v
43 default:
44 return []interface{}{}
45 }
46 }
47 return []interface{}{}
48}
49func getMapValueString(m map[string]interface{}, key string) string {
50 tokens := strings.Split(key, ".")
51 valMap := m
52 for _, token := range tokens {
53 v, ok := valMap[token]
54 if !ok {
55 return ""
56 }
57 if v == nil {
58 return ""
59 }
60 switch v := v.(type) {
61 case map[string]interface{}:
62 valMap = v
63 continue
64 case string:
65 return v
66 default:
67 return fmt.Sprintf("%v", v)
68 }
69 }
70 return ""
71}
72
73func toSliceString(slice interface{}) []string {
74 if slice == nil {
75 return []string{}
76 }
77 res := []string{}
78 switch reflect.TypeOf(slice).Kind() {
79 case reflect.Slice:
80 s := reflect.ValueOf(slice)
81 for i := 0; i < s.Len(); i++ {
82 elem := s.Index(i)
83 elemInterface := elem.Interface()
84 if elem, ok := elemInterface.(string); ok {
85 res = append(res, elem)
86 }
87 }
88 return res
89 default:
90 return res
91 }
92}
93
94func join(str []string, sep string) string {
95 ss := []string{}
96 // filter out empty strings
97 for _, s := range str {
98 if s == "" {
99 continue
100 }
101 ss = append(ss, s)
102 }
103 return strings.Join(ss, sep)
104}
105
106func wrap(start, maybeString, end string) string {
107 if maybeString == "" {
108 return maybeString
109 }
110 return start + maybeString + end
111}
112
113// Given array, print each item on its own line, wrapped in an indented "{ }" block.
114func block(maybeArray interface{}) string {
115 s := toSliceString(maybeArray)
116 if len(s) == 0 {
117 return "{}"
118 }
119 return indent("{\n"+join(s, "\n")) + "\n}"
120}
121
122func indent(maybeString interface{}) string {
123 if maybeString == nil {
124 return ""
125 }
126 switch str := maybeString.(type) {
127 case string:
128 return strings.Replace(str, "\n", "\n ", -1)
129 }
130 return ""
131}
132
133var printDocASTReducer = map[string]visitor.VisitFunc{
134 "Name": func(p visitor.VisitFuncParams) (string, interface{}) {
135 switch node := p.Node.(type) {
136 case *ast.Name:
137 return visitor.ActionUpdate, node.Value
138 case map[string]interface{}:
139 return visitor.ActionUpdate, getMapValue(node, "Value")
140 }
141 return visitor.ActionNoChange, nil
142 },
143 "Variable": func(p visitor.VisitFuncParams) (string, interface{}) {
144 switch node := p.Node.(type) {
145 case *ast.Variable:
146 return visitor.ActionUpdate, fmt.Sprintf("$%v", node.Name)
147 case map[string]interface{}:
148 return visitor.ActionUpdate, "$" + getMapValueString(node, "Name")
149 }
150 return visitor.ActionNoChange, nil
151 },
152
153 // Document
154 "Document": func(p visitor.VisitFuncParams) (string, interface{}) {
155 switch node := p.Node.(type) {
156 case *ast.Document:
157 definitions := toSliceString(node.Definitions)
158 return visitor.ActionUpdate, join(definitions, "\n\n") + "\n"
159 case map[string]interface{}:
160 definitions := toSliceString(getMapValue(node, "Definitions"))
161 return visitor.ActionUpdate, join(definitions, "\n\n") + "\n"
162 }
163 return visitor.ActionNoChange, nil
164 },
165 "OperationDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
166 switch node := p.Node.(type) {
167 case *ast.OperationDefinition:
168 op := string(node.Operation)
169 name := fmt.Sprintf("%v", node.Name)
170
171 varDefs := wrap("(", join(toSliceString(node.VariableDefinitions), ", "), ")")
172 directives := join(toSliceString(node.Directives), " ")
173 selectionSet := fmt.Sprintf("%v", node.SelectionSet)
174 // Anonymous queries with no directives or variable definitions can use
175 // the query short form.
176 str := ""
177 if name == "" && directives == "" && varDefs == "" && op == ast.OperationTypeQuery {
178 str = selectionSet
179 } else {
180 str = join([]string{
181 op,
182 join([]string{name, varDefs}, ""),
183 directives,
184 selectionSet,
185 }, " ")
186 }
187 return visitor.ActionUpdate, str
188 case map[string]interface{}:
189
190 op := getMapValueString(node, "Operation")
191 name := getMapValueString(node, "Name")
192
193 varDefs := wrap("(", join(toSliceString(getMapValue(node, "VariableDefinitions")), ", "), ")")
194 directives := join(toSliceString(getMapValue(node, "Directives")), " ")
195 selectionSet := getMapValueString(node, "SelectionSet")
196 str := ""
197 if name == "" && directives == "" && varDefs == "" && op == ast.OperationTypeQuery {
198 str = selectionSet
199 } else {
200 str = join([]string{
201 op,
202 join([]string{name, varDefs}, ""),
203 directives,
204 selectionSet,
205 }, " ")
206 }
207 return visitor.ActionUpdate, str
208 }
209 return visitor.ActionNoChange, nil
210 },
211 "VariableDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
212 switch node := p.Node.(type) {
213 case *ast.VariableDefinition:
214 variable := fmt.Sprintf("%v", node.Variable)
215 ttype := fmt.Sprintf("%v", node.Type)
216 defaultValue := fmt.Sprintf("%v", node.DefaultValue)
217
218 return visitor.ActionUpdate, variable + ": " + ttype + wrap(" = ", defaultValue, "")
219 case map[string]interface{}:
220
221 variable := getMapValueString(node, "Variable")
222 ttype := getMapValueString(node, "Type")
223 defaultValue := getMapValueString(node, "DefaultValue")
224
225 return visitor.ActionUpdate, variable + ": " + ttype + wrap(" = ", defaultValue, "")
226
227 }
228 return visitor.ActionNoChange, nil
229 },
230 "SelectionSet": func(p visitor.VisitFuncParams) (string, interface{}) {
231 switch node := p.Node.(type) {
232 case *ast.SelectionSet:
233 str := block(node.Selections)
234 return visitor.ActionUpdate, str
235 case map[string]interface{}:
236 selections := getMapValue(node, "Selections")
237 str := block(selections)
238 return visitor.ActionUpdate, str
239
240 }
241 return visitor.ActionNoChange, nil
242 },
243 "Field": func(p visitor.VisitFuncParams) (string, interface{}) {
244 switch node := p.Node.(type) {
245 case *ast.Argument:
246 name := fmt.Sprintf("%v", node.Name)
247 value := fmt.Sprintf("%v", node.Value)
248 return visitor.ActionUpdate, name + ": " + value
249 case map[string]interface{}:
250
251 alias := getMapValueString(node, "Alias")
252 name := getMapValueString(node, "Name")
253 args := toSliceString(getMapValue(node, "Arguments"))
254 directives := toSliceString(getMapValue(node, "Directives"))
255 selectionSet := getMapValueString(node, "SelectionSet")
256
257 str := join(
258 []string{
259 wrap("", alias, ": ") + name + wrap("(", join(args, ", "), ")"),
260 join(directives, " "),
261 selectionSet,
262 },
263 " ",
264 )
265 return visitor.ActionUpdate, str
266 }
267 return visitor.ActionNoChange, nil
268 },
269 "Argument": func(p visitor.VisitFuncParams) (string, interface{}) {
270 switch node := p.Node.(type) {
271 case *ast.FragmentSpread:
272 name := fmt.Sprintf("%v", node.Name)
273 directives := toSliceString(node.Directives)
274 return visitor.ActionUpdate, "..." + name + wrap(" ", join(directives, " "), "")
275 case map[string]interface{}:
276 name := getMapValueString(node, "Name")
277 value := getMapValueString(node, "Value")
278 return visitor.ActionUpdate, name + ": " + value
279 }
280 return visitor.ActionNoChange, nil
281 },
282
283 // Fragments
284 "FragmentSpread": func(p visitor.VisitFuncParams) (string, interface{}) {
285 switch node := p.Node.(type) {
286 case *ast.InlineFragment:
287 typeCondition := fmt.Sprintf("%v", node.TypeCondition)
288 directives := toSliceString(node.Directives)
289 selectionSet := fmt.Sprintf("%v", node.SelectionSet)
290 return visitor.ActionUpdate, "... on " + typeCondition + " " + wrap("", join(directives, " "), " ") + selectionSet
291 case map[string]interface{}:
292 name := getMapValueString(node, "Name")
293 directives := toSliceString(getMapValue(node, "Directives"))
294 return visitor.ActionUpdate, "..." + name + wrap(" ", join(directives, " "), "")
295 }
296 return visitor.ActionNoChange, nil
297 },
298 "InlineFragment": func(p visitor.VisitFuncParams) (string, interface{}) {
299 switch node := p.Node.(type) {
300 case map[string]interface{}:
301 typeCondition := getMapValueString(node, "TypeCondition")
302 directives := toSliceString(getMapValue(node, "Directives"))
303 selectionSet := getMapValueString(node, "SelectionSet")
304 return visitor.ActionUpdate,
305 join([]string{
306 "...",
307 wrap("on ", typeCondition, ""),
308 join(directives, " "),
309 selectionSet,
310 }, " ")
311 }
312 return visitor.ActionNoChange, nil
313 },
314 "FragmentDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
315 switch node := p.Node.(type) {
316 case *ast.FragmentDefinition:
317 name := fmt.Sprintf("%v", node.Name)
318 typeCondition := fmt.Sprintf("%v", node.TypeCondition)
319 directives := toSliceString(node.Directives)
320 selectionSet := fmt.Sprintf("%v", node.SelectionSet)
321 return visitor.ActionUpdate, "fragment " + name + " on " + typeCondition + " " + wrap("", join(directives, " "), " ") + selectionSet
322 case map[string]interface{}:
323 name := getMapValueString(node, "Name")
324 typeCondition := getMapValueString(node, "TypeCondition")
325 directives := toSliceString(getMapValue(node, "Directives"))
326 selectionSet := getMapValueString(node, "SelectionSet")
327 return visitor.ActionUpdate, "fragment " + name + " on " + typeCondition + " " + wrap("", join(directives, " "), " ") + selectionSet
328 }
329 return visitor.ActionNoChange, nil
330 },
331
332 // Value
333 "IntValue": func(p visitor.VisitFuncParams) (string, interface{}) {
334 switch node := p.Node.(type) {
335 case *ast.IntValue:
336 return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value)
337 case map[string]interface{}:
338 return visitor.ActionUpdate, getMapValueString(node, "Value")
339 }
340 return visitor.ActionNoChange, nil
341 },
342 "FloatValue": func(p visitor.VisitFuncParams) (string, interface{}) {
343 switch node := p.Node.(type) {
344 case *ast.FloatValue:
345 return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value)
346 case map[string]interface{}:
347 return visitor.ActionUpdate, getMapValueString(node, "Value")
348 }
349 return visitor.ActionNoChange, nil
350 },
351 "StringValue": func(p visitor.VisitFuncParams) (string, interface{}) {
352 switch node := p.Node.(type) {
353 case *ast.StringValue:
354 return visitor.ActionUpdate, `"` + fmt.Sprintf("%v", node.Value) + `"`
355 case map[string]interface{}:
356 return visitor.ActionUpdate, `"` + getMapValueString(node, "Value") + `"`
357 }
358 return visitor.ActionNoChange, nil
359 },
360 "BooleanValue": func(p visitor.VisitFuncParams) (string, interface{}) {
361 switch node := p.Node.(type) {
362 case *ast.BooleanValue:
363 return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value)
364 case map[string]interface{}:
365 return visitor.ActionUpdate, getMapValueString(node, "Value")
366 }
367 return visitor.ActionNoChange, nil
368 },
369 "EnumValue": func(p visitor.VisitFuncParams) (string, interface{}) {
370 switch node := p.Node.(type) {
371 case *ast.EnumValue:
372 return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value)
373 case map[string]interface{}:
374 return visitor.ActionUpdate, getMapValueString(node, "Value")
375 }
376 return visitor.ActionNoChange, nil
377 },
378 "ListValue": func(p visitor.VisitFuncParams) (string, interface{}) {
379 switch node := p.Node.(type) {
380 case *ast.ListValue:
381 return visitor.ActionUpdate, "[" + join(toSliceString(node.Values), ", ") + "]"
382 case map[string]interface{}:
383 return visitor.ActionUpdate, "[" + join(toSliceString(getMapValue(node, "Values")), ", ") + "]"
384 }
385 return visitor.ActionNoChange, nil
386 },
387 "ObjectValue": func(p visitor.VisitFuncParams) (string, interface{}) {
388 switch node := p.Node.(type) {
389 case *ast.ObjectValue:
390 return visitor.ActionUpdate, "{" + join(toSliceString(node.Fields), ", ") + "}"
391 case map[string]interface{}:
392 return visitor.ActionUpdate, "{" + join(toSliceString(getMapValue(node, "Fields")), ", ") + "}"
393 }
394 return visitor.ActionNoChange, nil
395 },
396 "ObjectField": func(p visitor.VisitFuncParams) (string, interface{}) {
397 switch node := p.Node.(type) {
398 case *ast.ObjectField:
399 name := fmt.Sprintf("%v", node.Name)
400 value := fmt.Sprintf("%v", node.Value)
401 return visitor.ActionUpdate, name + ": " + value
402 case map[string]interface{}:
403 name := getMapValueString(node, "Name")
404 value := getMapValueString(node, "Value")
405 return visitor.ActionUpdate, name + ": " + value
406 }
407 return visitor.ActionNoChange, nil
408 },
409
410 // Directive
411 "Directive": func(p visitor.VisitFuncParams) (string, interface{}) {
412 switch node := p.Node.(type) {
413 case *ast.Directive:
414 name := fmt.Sprintf("%v", node.Name)
415 args := toSliceString(node.Arguments)
416 return visitor.ActionUpdate, "@" + name + wrap("(", join(args, ", "), ")")
417 case map[string]interface{}:
418 name := getMapValueString(node, "Name")
419 args := toSliceString(getMapValue(node, "Arguments"))
420 return visitor.ActionUpdate, "@" + name + wrap("(", join(args, ", "), ")")
421 }
422 return visitor.ActionNoChange, nil
423 },
424
425 // Type
426 "Named": func(p visitor.VisitFuncParams) (string, interface{}) {
427 switch node := p.Node.(type) {
428 case *ast.Named:
429 return visitor.ActionUpdate, fmt.Sprintf("%v", node.Name)
430 case map[string]interface{}:
431 return visitor.ActionUpdate, getMapValueString(node, "Name")
432 }
433 return visitor.ActionNoChange, nil
434 },
435 "List": func(p visitor.VisitFuncParams) (string, interface{}) {
436 switch node := p.Node.(type) {
437 case *ast.List:
438 return visitor.ActionUpdate, "[" + fmt.Sprintf("%v", node.Type) + "]"
439 case map[string]interface{}:
440 return visitor.ActionUpdate, "[" + getMapValueString(node, "Type") + "]"
441 }
442 return visitor.ActionNoChange, nil
443 },
444 "NonNull": func(p visitor.VisitFuncParams) (string, interface{}) {
445 switch node := p.Node.(type) {
446 case *ast.NonNull:
447 return visitor.ActionUpdate, fmt.Sprintf("%v", node.Type) + "!"
448 case map[string]interface{}:
449 return visitor.ActionUpdate, getMapValueString(node, "Type") + "!"
450 }
451 return visitor.ActionNoChange, nil
452 },
453
454 // Type System Definitions
455 "SchemaDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
456 switch node := p.Node.(type) {
457 case *ast.SchemaDefinition:
458 directives := []string{}
459 for _, directive := range node.Directives {
460 directives = append(directives, fmt.Sprintf("%v", directive.Name))
461 }
462 str := join([]string{
463 "schema",
464 join(directives, " "),
465 block(node.OperationTypes),
466 }, " ")
467 return visitor.ActionUpdate, str
468 case map[string]interface{}:
469 operationTypes := toSliceString(getMapValue(node, "OperationTypes"))
470 directives := []string{}
471 for _, directive := range getMapSliceValue(node, "Directives") {
472 directives = append(directives, fmt.Sprintf("%v", directive))
473 }
474 str := join([]string{
475 "schema",
476 join(directives, " "),
477 block(operationTypes),
478 }, " ")
479 return visitor.ActionUpdate, str
480 }
481 return visitor.ActionNoChange, nil
482 },
483 "OperationTypeDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
484 switch node := p.Node.(type) {
485 case *ast.OperationTypeDefinition:
486 str := fmt.Sprintf("%v: %v", node.Operation, node.Type)
487 return visitor.ActionUpdate, str
488 case map[string]interface{}:
489 operation := getMapValueString(node, "Operation")
490 ttype := getMapValueString(node, "Type")
491 str := fmt.Sprintf("%v: %v", operation, ttype)
492 return visitor.ActionUpdate, str
493 }
494 return visitor.ActionNoChange, nil
495 },
496 "ScalarDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
497 switch node := p.Node.(type) {
498 case *ast.ScalarDefinition:
499 directives := []string{}
500 for _, directive := range node.Directives {
501 directives = append(directives, fmt.Sprintf("%v", directive.Name))
502 }
503 str := join([]string{
504 "scalar",
505 fmt.Sprintf("%v", node.Name),
506 join(directives, " "),
507 }, " ")
508 return visitor.ActionUpdate, str
509 case map[string]interface{}:
510 name := getMapValueString(node, "Name")
511 directives := []string{}
512 for _, directive := range getMapSliceValue(node, "Directives") {
513 directives = append(directives, fmt.Sprintf("%v", directive))
514 }
515 str := join([]string{
516 "scalar",
517 name,
518 join(directives, " "),
519 }, " ")
520 return visitor.ActionUpdate, str
521 }
522 return visitor.ActionNoChange, nil
523 },
524 "ObjectDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
525 switch node := p.Node.(type) {
526 case *ast.ObjectDefinition:
527 name := fmt.Sprintf("%v", node.Name)
528 interfaces := toSliceString(node.Interfaces)
529 fields := node.Fields
530 directives := []string{}
531 for _, directive := range node.Directives {
532 directives = append(directives, fmt.Sprintf("%v", directive.Name))
533 }
534 str := join([]string{
535 "type",
536 name,
537 wrap("implements ", join(interfaces, ", "), ""),
538 join(directives, " "),
539 block(fields),
540 }, " ")
541 return visitor.ActionUpdate, str
542 case map[string]interface{}:
543 name := getMapValueString(node, "Name")
544 interfaces := toSliceString(getMapValue(node, "Interfaces"))
545 fields := getMapValue(node, "Fields")
546 directives := []string{}
547 for _, directive := range getMapSliceValue(node, "Directives") {
548 directives = append(directives, fmt.Sprintf("%v", directive))
549 }
550 str := join([]string{
551 "type",
552 name,
553 wrap("implements ", join(interfaces, ", "), ""),
554 join(directives, " "),
555 block(fields),
556 }, " ")
557 return visitor.ActionUpdate, str
558 }
559 return visitor.ActionNoChange, nil
560 },
561 "FieldDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
562 switch node := p.Node.(type) {
563 case *ast.FieldDefinition:
564 name := fmt.Sprintf("%v", node.Name)
565 ttype := fmt.Sprintf("%v", node.Type)
566 args := toSliceString(node.Arguments)
567 directives := []string{}
568 for _, directive := range node.Directives {
569 directives = append(directives, fmt.Sprintf("%v", directive.Name))
570 }
571 str := name + wrap("(", join(args, ", "), ")") + ": " + ttype + wrap(" ", join(directives, " "), "")
572 return visitor.ActionUpdate, str
573 case map[string]interface{}:
574 name := getMapValueString(node, "Name")
575 ttype := getMapValueString(node, "Type")
576 args := toSliceString(getMapValue(node, "Arguments"))
577 directives := []string{}
578 for _, directive := range getMapSliceValue(node, "Directives") {
579 directives = append(directives, fmt.Sprintf("%v", directive))
580 }
581 str := name + wrap("(", join(args, ", "), ")") + ": " + ttype + wrap(" ", join(directives, " "), "")
582 return visitor.ActionUpdate, str
583 }
584 return visitor.ActionNoChange, nil
585 },
586 "InputValueDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
587 switch node := p.Node.(type) {
588 case *ast.InputValueDefinition:
589 name := fmt.Sprintf("%v", node.Name)
590 ttype := fmt.Sprintf("%v", node.Type)
591 defaultValue := fmt.Sprintf("%v", node.DefaultValue)
592 directives := []string{}
593 for _, directive := range node.Directives {
594 directives = append(directives, fmt.Sprintf("%v", directive.Name))
595 }
596 str := join([]string{
597 name + ": " + ttype,
598 wrap("= ", defaultValue, ""),
599 join(directives, " "),
600 }, " ")
601
602 return visitor.ActionUpdate, str
603 case map[string]interface{}:
604 name := getMapValueString(node, "Name")
605 ttype := getMapValueString(node, "Type")
606 defaultValue := getMapValueString(node, "DefaultValue")
607 directives := []string{}
608 for _, directive := range getMapSliceValue(node, "Directives") {
609 directives = append(directives, fmt.Sprintf("%v", directive))
610 }
611 str := join([]string{
612 name + ": " + ttype,
613 wrap("= ", defaultValue, ""),
614 join(directives, " "),
615 }, " ")
616 return visitor.ActionUpdate, str
617 }
618 return visitor.ActionNoChange, nil
619 },
620 "InterfaceDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
621 switch node := p.Node.(type) {
622 case *ast.InterfaceDefinition:
623 name := fmt.Sprintf("%v", node.Name)
624 fields := node.Fields
625 directives := []string{}
626 for _, directive := range node.Directives {
627 directives = append(directives, fmt.Sprintf("%v", directive.Name))
628 }
629 str := join([]string{
630 "interface",
631 name,
632 join(directives, " "),
633 block(fields),
634 }, " ")
635 return visitor.ActionUpdate, str
636 case map[string]interface{}:
637 name := getMapValueString(node, "Name")
638 fields := getMapValue(node, "Fields")
639 directives := []string{}
640 for _, directive := range getMapSliceValue(node, "Directives") {
641 directives = append(directives, fmt.Sprintf("%v", directive))
642 }
643 str := join([]string{
644 "interface",
645 name,
646 join(directives, " "),
647 block(fields),
648 }, " ")
649 return visitor.ActionUpdate, str
650 }
651 return visitor.ActionNoChange, nil
652 },
653 "UnionDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
654 switch node := p.Node.(type) {
655 case *ast.UnionDefinition:
656 name := fmt.Sprintf("%v", node.Name)
657 types := toSliceString(node.Types)
658 directives := []string{}
659 for _, directive := range node.Directives {
660 directives = append(directives, fmt.Sprintf("%v", directive.Name))
661 }
662 str := join([]string{
663 "union",
664 name,
665 join(directives, " "),
666 "= " + join(types, " | "),
667 }, " ")
668 return visitor.ActionUpdate, str
669 case map[string]interface{}:
670 name := getMapValueString(node, "Name")
671 types := toSliceString(getMapValue(node, "Types"))
672 directives := []string{}
673 for _, directive := range getMapSliceValue(node, "Directives") {
674 directives = append(directives, fmt.Sprintf("%v", directive))
675 }
676 str := join([]string{
677 "union",
678 name,
679 join(directives, " "),
680 "= " + join(types, " | "),
681 }, " ")
682 return visitor.ActionUpdate, str
683 }
684 return visitor.ActionNoChange, nil
685 },
686 "EnumDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
687 switch node := p.Node.(type) {
688 case *ast.EnumDefinition:
689 name := fmt.Sprintf("%v", node.Name)
690 values := node.Values
691 directives := []string{}
692 for _, directive := range node.Directives {
693 directives = append(directives, fmt.Sprintf("%v", directive.Name))
694 }
695 str := join([]string{
696 "enum",
697 name,
698 join(directives, " "),
699 block(values),
700 }, " ")
701 return visitor.ActionUpdate, str
702 case map[string]interface{}:
703 name := getMapValueString(node, "Name")
704 values := getMapValue(node, "Values")
705 directives := []string{}
706 for _, directive := range getMapSliceValue(node, "Directives") {
707 directives = append(directives, fmt.Sprintf("%v", directive))
708 }
709 str := join([]string{
710 "enum",
711 name,
712 join(directives, " "),
713 block(values),
714 }, " ")
715 return visitor.ActionUpdate, str
716 }
717 return visitor.ActionNoChange, nil
718 },
719 "EnumValueDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
720 switch node := p.Node.(type) {
721 case *ast.EnumValueDefinition:
722 name := fmt.Sprintf("%v", node.Name)
723 directives := []string{}
724 for _, directive := range node.Directives {
725 directives = append(directives, fmt.Sprintf("%v", directive.Name))
726 }
727 str := join([]string{
728 name,
729 join(directives, " "),
730 }, " ")
731 return visitor.ActionUpdate, str
732 case map[string]interface{}:
733 name := getMapValueString(node, "Name")
734 directives := []string{}
735 for _, directive := range getMapSliceValue(node, "Directives") {
736 directives = append(directives, fmt.Sprintf("%v", directive))
737 }
738 str := join([]string{
739 name,
740 join(directives, " "),
741 }, " ")
742 return visitor.ActionUpdate, str
743 }
744 return visitor.ActionNoChange, nil
745 },
746 "InputObjectDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
747 switch node := p.Node.(type) {
748 case *ast.InputObjectDefinition:
749 name := fmt.Sprintf("%v", node.Name)
750 fields := node.Fields
751 directives := []string{}
752 for _, directive := range node.Directives {
753 directives = append(directives, fmt.Sprintf("%v", directive.Name))
754 }
755 str := join([]string{
756 "input",
757 name,
758 join(directives, " "),
759 block(fields),
760 }, " ")
761 return visitor.ActionUpdate, str
762 case map[string]interface{}:
763 name := getMapValueString(node, "Name")
764 fields := getMapValue(node, "Fields")
765 directives := []string{}
766 for _, directive := range getMapSliceValue(node, "Directives") {
767 directives = append(directives, fmt.Sprintf("%v", directive))
768 }
769 str := join([]string{
770 "input",
771 name,
772 join(directives, " "),
773 block(fields),
774 }, " ")
775 return visitor.ActionUpdate, str
776 }
777 return visitor.ActionNoChange, nil
778 },
779 "TypeExtensionDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
780 switch node := p.Node.(type) {
781 case *ast.TypeExtensionDefinition:
782 definition := fmt.Sprintf("%v", node.Definition)
783 str := "extend " + definition
784 return visitor.ActionUpdate, str
785 case map[string]interface{}:
786 definition := getMapValueString(node, "Definition")
787 str := "extend " + definition
788 return visitor.ActionUpdate, str
789 }
790 return visitor.ActionNoChange, nil
791 },
792 "DirectiveDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
793 switch node := p.Node.(type) {
794 case *ast.DirectiveDefinition:
795 args := wrap("(", join(toSliceString(node.Arguments), ", "), ")")
796 str := fmt.Sprintf("directive @%v%v on %v", node.Name, args, join(toSliceString(node.Locations), " | "))
797 return visitor.ActionUpdate, str
798 case map[string]interface{}:
799 name := getMapValueString(node, "Name")
800 locations := toSliceString(getMapValue(node, "Locations"))
801 args := toSliceString(getMapValue(node, "Arguments"))
802 argsStr := wrap("(", join(args, ", "), ")")
803 str := fmt.Sprintf("directive @%v%v on %v", name, argsStr, join(locations, " | "))
804 return visitor.ActionUpdate, str
805 }
806 return visitor.ActionNoChange, nil
807 },
808}
809
810func Print(astNode ast.Node) (printed interface{}) {
811 defer func() interface{} {
812 if r := recover(); r != nil {
813 return fmt.Sprintf("%v", astNode)
814 }
815 return printed
816 }()
817 printed = visitor.Visit(astNode, &visitor.VisitorOptions{
818 LeaveKindMap: printDocASTReducer,
819 }, nil)
820 return printed
821}