graphql 1.8.0.pre2 → 1.8.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql.rb +1 -1
  3. data/lib/graphql/deprecated_dsl.rb +2 -0
  4. data/lib/graphql/enum_type.rb +1 -1
  5. data/lib/graphql/field.rb +10 -1
  6. data/lib/graphql/input_object_type.rb +3 -1
  7. data/lib/graphql/introspection.rb +3 -10
  8. data/lib/graphql/introspection/base_object.rb +15 -0
  9. data/lib/graphql/introspection/directive_location_enum.rb +11 -7
  10. data/lib/graphql/introspection/directive_type.rb +23 -16
  11. data/lib/graphql/introspection/dynamic_fields.rb +11 -0
  12. data/lib/graphql/introspection/entry_points.rb +29 -0
  13. data/lib/graphql/introspection/enum_value_type.rb +16 -11
  14. data/lib/graphql/introspection/field_type.rb +21 -12
  15. data/lib/graphql/introspection/input_value_type.rb +26 -23
  16. data/lib/graphql/introspection/schema_field.rb +7 -2
  17. data/lib/graphql/introspection/schema_type.rb +36 -22
  18. data/lib/graphql/introspection/type_by_name_field.rb +10 -2
  19. data/lib/graphql/introspection/type_kind_enum.rb +10 -6
  20. data/lib/graphql/introspection/type_type.rb +85 -23
  21. data/lib/graphql/introspection/typename_field.rb +1 -0
  22. data/lib/graphql/language.rb +1 -0
  23. data/lib/graphql/language/document_from_schema_definition.rb +129 -37
  24. data/lib/graphql/language/generation.rb +3 -182
  25. data/lib/graphql/language/nodes.rb +12 -2
  26. data/lib/graphql/language/parser.rb +63 -55
  27. data/lib/graphql/language/parser.y +2 -1
  28. data/lib/graphql/language/printer.rb +351 -0
  29. data/lib/graphql/object_type.rb +1 -1
  30. data/lib/graphql/query.rb +1 -1
  31. data/lib/graphql/query/arguments.rb +24 -8
  32. data/lib/graphql/query/context.rb +3 -0
  33. data/lib/graphql/query/literal_input.rb +4 -1
  34. data/lib/graphql/railtie.rb +28 -6
  35. data/lib/graphql/schema.rb +42 -7
  36. data/lib/graphql/schema/enum.rb +1 -0
  37. data/lib/graphql/schema/field.rb +26 -5
  38. data/lib/graphql/schema/field/dynamic_resolve.rb +18 -9
  39. data/lib/graphql/schema/input_object.rb +2 -2
  40. data/lib/graphql/schema/introspection_system.rb +93 -0
  41. data/lib/graphql/schema/late_bound_type.rb +32 -0
  42. data/lib/graphql/schema/member.rb +21 -1
  43. data/lib/graphql/schema/member/build_type.rb +8 -6
  44. data/lib/graphql/schema/member/has_fields.rb +1 -1
  45. data/lib/graphql/schema/member/instrumentation.rb +3 -1
  46. data/lib/graphql/schema/member/list_type_proxy.rb +4 -0
  47. data/lib/graphql/schema/member/non_null_type_proxy.rb +4 -0
  48. data/lib/graphql/schema/object.rb +2 -1
  49. data/lib/graphql/schema/printer.rb +33 -266
  50. data/lib/graphql/schema/traversal.rb +74 -6
  51. data/lib/graphql/schema/validation.rb +3 -2
  52. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +6 -6
  53. data/lib/graphql/tracing/scout_tracing.rb +2 -2
  54. data/lib/graphql/upgrader/member.rb +463 -63
  55. data/lib/graphql/version.rb +1 -1
  56. data/spec/fixtures/upgrader/blame_range.original.rb +43 -0
  57. data/spec/fixtures/upgrader/blame_range.transformed.rb +31 -0
  58. data/spec/fixtures/upgrader/subscribable.original.rb +51 -0
  59. data/spec/fixtures/upgrader/subscribable.transformed.rb +46 -0
  60. data/spec/fixtures/upgrader/type_x.original.rb +35 -0
  61. data/spec/fixtures/upgrader/type_x.transformed.rb +35 -0
  62. data/spec/graphql/language/document_from_schema_definition_spec.rb +729 -296
  63. data/spec/graphql/language/generation_spec.rb +21 -186
  64. data/spec/graphql/language/nodes_spec.rb +21 -0
  65. data/spec/graphql/language/printer_spec.rb +203 -0
  66. data/spec/graphql/query/arguments_spec.rb +14 -4
  67. data/spec/graphql/query/context_spec.rb +17 -0
  68. data/spec/graphql/schema/build_from_definition_spec.rb +13 -4
  69. data/spec/graphql/schema/field_spec.rb +14 -0
  70. data/spec/graphql/schema/introspection_system_spec.rb +39 -0
  71. data/spec/graphql/schema/object_spec.rb +12 -1
  72. data/spec/graphql/schema/printer_spec.rb +14 -14
  73. data/spec/graphql/tracing/platform_tracing_spec.rb +2 -2
  74. data/spec/graphql/upgrader/member_spec.rb +274 -62
  75. data/spec/support/jazz.rb +75 -3
  76. metadata +38 -9
  77. data/lib/graphql/introspection/arguments_field.rb +0 -7
  78. data/lib/graphql/introspection/enum_values_field.rb +0 -18
  79. data/lib/graphql/introspection/fields_field.rb +0 -13
  80. data/lib/graphql/introspection/input_fields_field.rb +0 -12
  81. data/lib/graphql/introspection/interfaces_field.rb +0 -11
  82. data/lib/graphql/introspection/of_type_field.rb +0 -6
  83. data/lib/graphql/introspection/possible_types_field.rb +0 -11
@@ -8,6 +8,7 @@ module GraphQL
8
8
  # - `children` returns all AST nodes attached to this one. Used for tree traversal.
9
9
  # - `scalars` returns all scalar (Ruby) values attached to this one. Used for comparing nodes.
10
10
  # - `to_query_string` turns an AST node into a GraphQL string
11
+
11
12
  class AbstractNode
12
13
  attr_accessor :line, :col, :filename
13
14
 
@@ -77,8 +78,8 @@ module GraphQL
77
78
  [line, col]
78
79
  end
79
80
 
80
- def to_query_string
81
- Generation.generate(self)
81
+ def to_query_string(printer: GraphQL::Language::Printer.new)
82
+ printer.print(self)
82
83
  end
83
84
  end
84
85
 
@@ -164,6 +165,15 @@ module GraphQL
164
165
  # document.to_query_string
165
166
  # # { ... }
166
167
  #
168
+ # @example Creating a custom string from a document
169
+ # class VariableScrubber < GraphQL::Language::Printer
170
+ # def print_argument(arg)
171
+ # "#{arg.name}: <HIDDEN>"
172
+ # end
173
+ # end
174
+ #
175
+ # document.to_query_string(printer: VariableSrubber.new)
176
+ #
167
177
  class Document < AbstractNode
168
178
  attr_accessor :definitions
169
179
  child_attributes :definitions
@@ -12,7 +12,7 @@ module GraphQL
12
12
  module Language
13
13
  class Parser < Racc::Parser
14
14
 
15
- module_eval(<<'...end parser.y/module_eval...', 'parser.y', 372)
15
+ module_eval(<<'...end parser.y/module_eval...', 'parser.y', 373)
16
16
 
17
17
  def initialize(query_string, filename:, tracer: Tracing::NullTracer)
18
18
  @query_string = query_string
@@ -425,30 +425,30 @@ racc_action_pointer = [
425
425
  nil, nil, nil, nil ]
426
426
 
427
427
  racc_action_default = [
428
- -145, -145, -1, -2, -3, -5, -6, -7, -14, -145,
429
- -11, -12, -13, -109, -111, -112, -113, -145, -118, -119,
430
- -120, -121, -122, -123, -145, -145, -145, -145, -145, -145,
431
- -145, -145, -4, -16, -15, -37, -38, -39, -40, -41,
428
+ -146, -146, -1, -2, -3, -5, -6, -7, -14, -146,
429
+ -11, -12, -13, -109, -111, -112, -113, -146, -118, -119,
430
+ -120, -121, -122, -123, -146, -146, -146, -146, -146, -146,
431
+ -146, -146, -4, -16, -15, -37, -38, -39, -40, -41,
432
432
  -42, -43, -44, -45, -46, -47, -48, -49, -50, -51,
433
- -52, -53, -145, -10, -30, -32, -33, -34, -64, -100,
434
- -145, -110, -145, -100, -126, -100, -100, -100, -100, -145,
435
- 244, -100, -145, -9, -31, -100, -145, -145, -101, -102,
436
- -145, -100, -145, -145, -145, -145, -115, -145, -124, -100,
437
- -145, -145, -145, -145, -145, -131, -145, -145, -18, -145,
438
- -28, -64, -65, -145, -67, -145, -103, -64, -105, -21,
439
- -100, -145, -145, -107, -100, -114, -116, -145, -145, -59,
440
- -127, -145, -145, -145, -145, -145, -145, -8, -17, -19,
441
- -145, -29, -35, -100, -66, -68, -79, -104, -22, -145,
442
- -145, -26, -145, -145, -117, -145, -60, -131, -134, -145,
443
- -137, -139, -54, -55, -56, -57, -58, -100, -62, -145,
444
- -145, -129, -145, -145, -145, -145, -28, -69, -70, -71,
433
+ -52, -53, -146, -10, -30, -32, -33, -34, -64, -100,
434
+ -146, -110, -146, -100, -126, -100, -100, -100, -100, -146,
435
+ 244, -100, -146, -9, -31, -100, -146, -146, -101, -102,
436
+ -146, -100, -146, -146, -146, -146, -115, -146, -124, -100,
437
+ -146, -146, -146, -146, -146, -131, -146, -146, -18, -146,
438
+ -28, -64, -65, -146, -67, -146, -103, -64, -105, -21,
439
+ -100, -146, -146, -107, -100, -114, -116, -146, -146, -59,
440
+ -127, -134, -146, -146, -146, -146, -146, -8, -17, -19,
441
+ -146, -29, -35, -100, -66, -68, -79, -104, -22, -146,
442
+ -146, -26, -146, -146, -117, -134, -60, -131, -135, -146,
443
+ -138, -140, -54, -55, -56, -57, -58, -100, -62, -146,
444
+ -146, -129, -146, -146, -146, -146, -28, -69, -70, -71,
445
445
  -72, -73, -74, -75, -76, -77, -78, -80, -81, -82,
446
- -83, -145, -145, -145, -99, -106, -23, -27, -108, -145,
447
- -145, -135, -136, -145, -61, -63, -140, -145, -130, -141,
448
- -132, -142, -143, -24, -36, -84, -85, -145, -87, -89,
449
- -145, -91, -145, -145, -96, -125, -145, -138, -24, -145,
450
- -20, -145, -86, -88, -90, -92, -145, -79, -95, -97,
451
- -145, -100, -100, -144, -25, -145, -79, -80, -93, -145,
446
+ -83, -146, -146, -146, -99, -106, -23, -27, -108, -146,
447
+ -146, -136, -137, -146, -61, -63, -141, -146, -130, -142,
448
+ -132, -143, -144, -24, -36, -84, -85, -146, -87, -89,
449
+ -146, -91, -146, -146, -96, -125, -146, -139, -24, -146,
450
+ -20, -146, -86, -88, -90, -92, -146, -79, -95, -97,
451
+ -146, -100, -100, -145, -25, -146, -79, -80, -93, -146,
452
452
  -133, -128, -94, -98 ]
453
453
 
454
454
  racc_goto_table = [
@@ -656,19 +656,20 @@ racc_reduce_table = [
656
656
  0, 100, :_reduce_131,
657
657
  3, 100, :_reduce_132,
658
658
  5, 101, :_reduce_133,
659
- 1, 97, :_reduce_134,
660
- 2, 97, :_reduce_135,
661
- 6, 92, :_reduce_136,
662
- 1, 102, :_reduce_137,
663
- 3, 102, :_reduce_138,
664
- 5, 93, :_reduce_139,
665
- 6, 94, :_reduce_140,
666
- 6, 95, :_reduce_141,
667
- 6, 87, :_reduce_142,
668
- 1, 103, :_reduce_143,
669
- 3, 103, :_reduce_144 ]
670
-
671
- racc_reduce_n = 145
659
+ 0, 97, :_reduce_134,
660
+ 1, 97, :_reduce_135,
661
+ 2, 97, :_reduce_136,
662
+ 6, 92, :_reduce_137,
663
+ 1, 102, :_reduce_138,
664
+ 3, 102, :_reduce_139,
665
+ 5, 93, :_reduce_140,
666
+ 6, 94, :_reduce_141,
667
+ 6, 95, :_reduce_142,
668
+ 6, 87, :_reduce_143,
669
+ 1, 103, :_reduce_144,
670
+ 3, 103, :_reduce_145 ]
671
+
672
+ racc_reduce_n = 146
672
673
 
673
674
  racc_shift_n = 244
674
675
 
@@ -1582,81 +1583,88 @@ module_eval(<<'.,.,', 'parser.y', 326)
1582
1583
 
1583
1584
  module_eval(<<'.,.,', 'parser.y', 330)
1584
1585
  def _reduce_134(val, _values, result)
1585
- return [val[0]]
1586
+ return []
1586
1587
  result
1587
1588
  end
1588
1589
  .,.,
1589
1590
 
1590
1591
  module_eval(<<'.,.,', 'parser.y', 331)
1591
1592
  def _reduce_135(val, _values, result)
1592
- val[0] << val[1]
1593
+ return [val[0]]
1593
1594
  result
1594
1595
  end
1595
1596
  .,.,
1596
1597
 
1597
- module_eval(<<'.,.,', 'parser.y', 335)
1598
+ module_eval(<<'.,.,', 'parser.y', 332)
1598
1599
  def _reduce_136(val, _values, result)
1599
- return make_node(:InterfaceTypeDefinition, name: val[1], directives: val[2], fields: val[4], description: get_description(val[0]), position_source: val[0])
1600
-
1600
+ val[0] << val[1]
1601
1601
  result
1602
1602
  end
1603
1603
  .,.,
1604
1604
 
1605
- module_eval(<<'.,.,', 'parser.y', 339)
1605
+ module_eval(<<'.,.,', 'parser.y', 336)
1606
1606
  def _reduce_137(val, _values, result)
1607
- return [make_node(:TypeName, name: val[0])]
1607
+ return make_node(:InterfaceTypeDefinition, name: val[1], directives: val[2], fields: val[4], description: get_description(val[0]), position_source: val[0])
1608
+
1608
1609
  result
1609
1610
  end
1610
1611
  .,.,
1611
1612
 
1612
1613
  module_eval(<<'.,.,', 'parser.y', 340)
1613
1614
  def _reduce_138(val, _values, result)
1614
- val[0] << make_node(:TypeName, name: val[2])
1615
+ return [make_node(:TypeName, name: val[0])]
1615
1616
  result
1616
1617
  end
1617
1618
  .,.,
1618
1619
 
1619
- module_eval(<<'.,.,', 'parser.y', 344)
1620
+ module_eval(<<'.,.,', 'parser.y', 341)
1620
1621
  def _reduce_139(val, _values, result)
1621
- return make_node(:UnionTypeDefinition, name: val[1], directives: val[2], types: val[4], description: get_description(val[0]), position_source: val[0])
1622
-
1622
+ val[0] << make_node(:TypeName, name: val[2])
1623
1623
  result
1624
1624
  end
1625
1625
  .,.,
1626
1626
 
1627
- module_eval(<<'.,.,', 'parser.y', 349)
1627
+ module_eval(<<'.,.,', 'parser.y', 345)
1628
1628
  def _reduce_140(val, _values, result)
1629
- return make_node(:EnumTypeDefinition, name: val[1], directives: val[2], values: val[4], description: get_description(val[0]), position_source: val[0])
1629
+ return make_node(:UnionTypeDefinition, name: val[1], directives: val[2], types: val[4], description: get_description(val[0]), position_source: val[0])
1630
1630
 
1631
1631
  result
1632
1632
  end
1633
1633
  .,.,
1634
1634
 
1635
- module_eval(<<'.,.,', 'parser.y', 354)
1635
+ module_eval(<<'.,.,', 'parser.y', 350)
1636
1636
  def _reduce_141(val, _values, result)
1637
- return make_node(:InputObjectTypeDefinition, name: val[1], directives: val[2], fields: val[4], description: get_description(val[0]), position_source: val[0])
1637
+ return make_node(:EnumTypeDefinition, name: val[1], directives: val[2], values: val[4], description: get_description(val[0]), position_source: val[0])
1638
1638
 
1639
1639
  result
1640
1640
  end
1641
1641
  .,.,
1642
1642
 
1643
- module_eval(<<'.,.,', 'parser.y', 359)
1643
+ module_eval(<<'.,.,', 'parser.y', 355)
1644
1644
  def _reduce_142(val, _values, result)
1645
- return make_node(:DirectiveDefinition, name: val[2], arguments: val[3], locations: val[5], description: get_description(val[0]), position_source: val[0])
1645
+ return make_node(:InputObjectTypeDefinition, name: val[1], directives: val[2], fields: val[4], description: get_description(val[0]), position_source: val[0])
1646
1646
 
1647
1647
  result
1648
1648
  end
1649
1649
  .,.,
1650
1650
 
1651
- module_eval(<<'.,.,', 'parser.y', 363)
1651
+ module_eval(<<'.,.,', 'parser.y', 360)
1652
1652
  def _reduce_143(val, _values, result)
1653
- return [val[0].to_s]
1653
+ return make_node(:DirectiveDefinition, name: val[2], arguments: val[3], locations: val[5], description: get_description(val[0]), position_source: val[0])
1654
+
1654
1655
  result
1655
1656
  end
1656
1657
  .,.,
1657
1658
 
1658
1659
  module_eval(<<'.,.,', 'parser.y', 364)
1659
1660
  def _reduce_144(val, _values, result)
1661
+ return [val[0].to_s]
1662
+ result
1663
+ end
1664
+ .,.,
1665
+
1666
+ module_eval(<<'.,.,', 'parser.y', 365)
1667
+ def _reduce_145(val, _values, result)
1660
1668
  val[0] << val[2].to_s
1661
1669
  result
1662
1670
  end
@@ -328,7 +328,8 @@ rule
328
328
  }
329
329
 
330
330
  field_definition_list:
331
- field_definition { return [val[0]] }
331
+ /* none */ { return [] }
332
+ | field_definition { return [val[0]] }
332
333
  | field_definition_list field_definition { val[0] << val[1] }
333
334
 
334
335
  interface_type_definition:
@@ -0,0 +1,351 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Language
4
+ class Printer
5
+ # Turn an arbitrary AST node back into a string.
6
+ #
7
+ # @example Turning a document into a query string
8
+ # document = GraphQL.parse(query_string)
9
+ # GraphQL::Language::Printer.new.print(document)
10
+ # # => "{ ... }"
11
+ #
12
+ #
13
+ # @example Building a custom printer
14
+ #
15
+ # class MyPrinter < GraphQL::Language::Printer
16
+ # def print_argument(arg)
17
+ # "#{arg.name}: <HIDDEN>"
18
+ # end
19
+ # end
20
+ #
21
+ # MyPrinter.new.print(document)
22
+ # # => "mutation { pay(creditCard: <HIDDEN>) { success } }"
23
+ #
24
+ #
25
+ # @param indent [String] Whitespace to add to the printed node
26
+ # @return [String] Valid GraphQL for `node`
27
+ def print(node, indent: "")
28
+ print_node(node, indent: indent)
29
+ end
30
+
31
+ protected
32
+
33
+ def print_document(document)
34
+ document.definitions.map { |d| print_node(d) }.join("\n\n")
35
+ end
36
+
37
+ def print_argument(argument)
38
+ "#{argument.name}: #{print_node(argument.value)}".dup
39
+ end
40
+
41
+ def print_directive(directive)
42
+ out = "@#{directive.name}".dup
43
+
44
+ if directive.arguments.any?
45
+ out << "(#{directive.arguments.map { |a| print_argument(a) }.join(", ")})"
46
+ end
47
+
48
+ out
49
+ end
50
+
51
+ def print_enum(enum)
52
+ "#{enum.name}".dup
53
+ end
54
+
55
+ def print_null_value
56
+ "null".dup
57
+ end
58
+
59
+ def print_field(field, indent: "")
60
+ out = "#{indent}".dup
61
+ out << "#{field.alias}: " if field.alias
62
+ out << "#{field.name}"
63
+ out << "(#{field.arguments.map { |a| print_argument(a) }.join(", ")})" if field.arguments.any?
64
+ out << print_directives(field.directives)
65
+ out << print_selections(field.selections, indent: indent)
66
+ out
67
+ end
68
+
69
+ def print_fragment_definition(fragment_def, indent: "")
70
+ out = "#{indent}fragment #{fragment_def.name}".dup
71
+ if fragment_def.type
72
+ out << " on #{print_node(fragment_def.type)}"
73
+ end
74
+ out << print_directives(fragment_def.directives)
75
+ out << print_selections(fragment_def.selections, indent: indent)
76
+ out
77
+ end
78
+
79
+ def print_fragment_spread(fragment_spread, indent: "")
80
+ out = "#{indent}...#{fragment_spread.name}".dup
81
+ out << print_directives(fragment_spread.directives)
82
+ out
83
+ end
84
+
85
+ def print_inline_fragment(inline_fragment, indent: "")
86
+ out = "#{indent}...".dup
87
+ if inline_fragment.type
88
+ out << " on #{print_node(inline_fragment.type)}"
89
+ end
90
+ out << print_directives(inline_fragment.directives)
91
+ out << print_selections(inline_fragment.selections, indent: indent)
92
+ out
93
+ end
94
+
95
+ def print_input_object(input_object)
96
+ print_node(input_object.to_h)
97
+ end
98
+
99
+ def print_list_type(list_type)
100
+ "[#{print_node(list_type.of_type)}]".dup
101
+ end
102
+
103
+ def print_non_null_type(non_null_type)
104
+ "#{print_node(non_null_type.of_type)}!".dup
105
+ end
106
+
107
+ def print_operation_definition(operation_definition, indent: "")
108
+ out = "#{indent}#{operation_definition.operation_type}".dup
109
+ out << " #{operation_definition.name}" if operation_definition.name
110
+
111
+ if operation_definition.variables.any?
112
+ out << "(#{operation_definition.variables.map { |v| print_variable_definition(v) }.join(", ")})"
113
+ end
114
+
115
+ out << print_directives(operation_definition.directives)
116
+ out << print_selections(operation_definition.selections, indent: indent)
117
+ out
118
+ end
119
+
120
+ def print_type_name(type_name)
121
+ "#{type_name.name}".dup
122
+ end
123
+
124
+ def print_variable_definition(variable_definition)
125
+ out = "$#{variable_definition.name}: #{print_node(variable_definition.type)}".dup
126
+ out << " = #{print_node(variable_definition.default_value)}" unless variable_definition.default_value.nil?
127
+ out
128
+ end
129
+
130
+ def print_variable_identifier(variable_identifier)
131
+ "$#{variable_identifier.name}".dup
132
+ end
133
+
134
+ def print_schema_definition(schema)
135
+ if (schema.query.nil? || schema.query == 'Query') &&
136
+ (schema.mutation.nil? || schema.mutation == 'Mutation') &&
137
+ (schema.subscription.nil? || schema.subscription == 'Subscription')
138
+ return
139
+ end
140
+
141
+ out = "schema {\n".dup
142
+ out << " query: #{schema.query}\n" if schema.query
143
+ out << " mutation: #{schema.mutation}\n" if schema.mutation
144
+ out << " subscription: #{schema.subscription}\n" if schema.subscription
145
+ out << "}"
146
+ end
147
+
148
+ def print_scalar_type_definition(scalar_type)
149
+ out = print_description(scalar_type)
150
+ out << "scalar #{scalar_type.name}"
151
+ out << print_directives(scalar_type.directives)
152
+ end
153
+
154
+ def print_object_type_definition(object_type)
155
+ out = print_description(object_type)
156
+ out << "type #{object_type.name}"
157
+ out << print_directives(object_type.directives)
158
+ out << " implements " << object_type.interfaces.map(&:name).join(", ") unless object_type.interfaces.empty?
159
+ out << print_field_definitions(object_type.fields)
160
+ end
161
+
162
+ def print_input_value_definition(input_value)
163
+ out = "#{input_value.name}: #{print_node(input_value.type)}".dup
164
+ out << " = #{print_node(input_value.default_value)}" unless input_value.default_value.nil?
165
+ out << print_directives(input_value.directives)
166
+ end
167
+
168
+ def print_arguments(arguments, indent: "")
169
+ if arguments.all?{ |arg| !arg.description }
170
+ return "(#{arguments.map{ |arg| print_input_value_definition(arg) }.join(", ")})"
171
+ end
172
+
173
+ out = "(\n".dup
174
+ out << arguments.map.with_index{ |arg, i|
175
+ "#{print_description(arg, indent: " " + indent, first_in_block: i == 0)} #{indent}"\
176
+ "#{print_input_value_definition(arg)}"
177
+ }.join("\n")
178
+ out << "\n#{indent})"
179
+ end
180
+
181
+ def print_field_definition(field)
182
+ out = field.name.dup
183
+ unless field.arguments.empty?
184
+ out << print_arguments(field.arguments, indent: " ")
185
+ end
186
+ out << ": #{print_node(field.type)}"
187
+ out << print_directives(field.directives)
188
+ end
189
+
190
+ def print_interface_type_definition(interface_type)
191
+ out = print_description(interface_type)
192
+ out << "interface #{interface_type.name}"
193
+ out << print_directives(interface_type.directives)
194
+ out << print_field_definitions(interface_type.fields)
195
+ end
196
+
197
+ def print_union_type_definition(union_type)
198
+ out = print_description(union_type)
199
+ out << "union #{union_type.name}"
200
+ out << print_directives(union_type.directives)
201
+ out << " = " + union_type.types.map(&:name).join(" | ")
202
+ end
203
+
204
+ def print_enum_type_definition(enum_type)
205
+ out = print_description(enum_type)
206
+ out << "enum #{enum_type.name}#{print_directives(enum_type.directives)} {\n"
207
+ enum_type.values.each.with_index do |value, i|
208
+ out << print_description(value, indent: ' ', first_in_block: i == 0)
209
+ out << print_enum_value_definition(value)
210
+ end
211
+ out << "}"
212
+ end
213
+
214
+ def print_enum_value_definition(enum_value)
215
+ out = " #{enum_value.name}".dup
216
+ out << print_directives(enum_value.directives)
217
+ out << "\n"
218
+ end
219
+
220
+ def print_input_object_type_definition(input_object_type)
221
+ out = print_description(input_object_type)
222
+ out << "input #{input_object_type.name}"
223
+ out << print_directives(input_object_type.directives)
224
+ out << " {\n"
225
+ input_object_type.fields.each.with_index do |field, i|
226
+ out << print_description(field, indent: ' ', first_in_block: i == 0)
227
+ out << " #{print_input_value_definition(field)}\n"
228
+ end
229
+ out << "}"
230
+ end
231
+
232
+ def print_directive_definition(directive)
233
+ out = print_description(directive)
234
+ out << "directive @#{directive.name}"
235
+
236
+ if directive.arguments.any?
237
+ out << print_arguments(directive.arguments)
238
+ end
239
+
240
+ out << " on #{directive.locations.join(' | ')}"
241
+ end
242
+
243
+ def print_description(node, indent: "", first_in_block: true)
244
+ return ''.dup unless node.description
245
+
246
+ description = indent != '' && !first_in_block ? "\n".dup : "".dup
247
+ description << GraphQL::Language::Comments.commentize(node.description, indent: indent)
248
+ end
249
+
250
+ def print_field_definitions(fields)
251
+ out = " {\n".dup
252
+ fields.each.with_index do |field, i|
253
+ out << print_description(field, indent: ' ', first_in_block: i == 0)
254
+ out << " #{print_field_definition(field)}\n"
255
+ end
256
+ out << "}"
257
+ end
258
+
259
+ def print_directives(directives)
260
+ if directives.any?
261
+ directives.map { |d| " #{print_directive(d)}" }.join
262
+ else
263
+ ""
264
+ end
265
+ end
266
+
267
+ def print_selections(selections, indent: "")
268
+ if selections.any?
269
+ out = " {\n".dup
270
+ selections.each do |selection|
271
+ out << print_node(selection, indent: indent + " ") << "\n"
272
+ end
273
+ out << "#{indent}}"
274
+ else
275
+ ""
276
+ end
277
+ end
278
+
279
+ def print_node(node, indent: "")
280
+ case node
281
+ when Nodes::Document
282
+ print_document(node)
283
+ when Nodes::Argument
284
+ print_argument(node)
285
+ when Nodes::Directive
286
+ print_directive(node)
287
+ when Nodes::Enum
288
+ print_enum(node)
289
+ when Nodes::NullValue
290
+ print_null_value
291
+ when Nodes::Field
292
+ print_field(node, indent: indent)
293
+ when Nodes::FragmentDefinition
294
+ print_fragment_definition(node, indent: indent)
295
+ when Nodes::FragmentSpread
296
+ print_fragment_spread(node, indent: indent)
297
+ when Nodes::InlineFragment
298
+ print_inline_fragment(node, indent: indent)
299
+ when Nodes::InputObject
300
+ print_input_object(node)
301
+ when Nodes::ListType
302
+ print_list_type(node)
303
+ when Nodes::NonNullType
304
+ print_non_null_type(node)
305
+ when Nodes::OperationDefinition
306
+ print_operation_definition(node, indent: indent)
307
+ when Nodes::TypeName
308
+ print_type_name(node)
309
+ when Nodes::VariableDefinition
310
+ print_variable_definition(node)
311
+ when Nodes::VariableIdentifier
312
+ print_variable_identifier(node)
313
+ when Nodes::SchemaDefinition
314
+ print_schema_definition(node)
315
+ when Nodes::ScalarTypeDefinition
316
+ print_scalar_type_definition(node)
317
+ when Nodes::ObjectTypeDefinition
318
+ print_object_type_definition(node)
319
+ when Nodes::InputValueDefinition
320
+ print_input_value_definition(node)
321
+ when Nodes::FieldDefinition
322
+ print_field_definition(node)
323
+ when Nodes::InterfaceTypeDefinition
324
+ print_interface_type_definition(node)
325
+ when Nodes::UnionTypeDefinition
326
+ print_union_type_definition(node)
327
+ when Nodes::EnumTypeDefinition
328
+ print_enum_type_definition(node)
329
+ when Nodes::EnumValueDefinition
330
+ print_enum_value_definition(node)
331
+ when Nodes::InputObjectTypeDefinition
332
+ print_input_object_type_definition(node)
333
+ when Nodes::DirectiveDefinition
334
+ print_directive_definition(node)
335
+ when FalseClass, Float, Integer, NilClass, String, TrueClass, Symbol
336
+ GraphQL::Language.serialize(node)
337
+ when Array
338
+ "[#{node.map { |v| print_node(v) }.join(", ")}]".dup
339
+ when Hash
340
+ "{#{node.map { |k, v| "#{k}: #{print_node(v)}" }.join(", ")}}".dup
341
+ else
342
+ raise TypeError
343
+ end
344
+ end
345
+
346
+ private
347
+
348
+ attr_reader :node
349
+ end
350
+ end
351
+ end