graphql 2.2.17 → 2.5.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
  3. data/lib/generators/graphql/install_generator.rb +46 -0
  4. data/lib/generators/graphql/orm_mutations_base.rb +1 -1
  5. data/lib/generators/graphql/templates/base_resolver.erb +2 -0
  6. data/lib/generators/graphql/templates/schema.erb +3 -0
  7. data/lib/generators/graphql/type_generator.rb +1 -1
  8. data/lib/graphql/analysis/analyzer.rb +90 -0
  9. data/lib/graphql/analysis/field_usage.rb +82 -0
  10. data/lib/graphql/analysis/max_query_complexity.rb +20 -0
  11. data/lib/graphql/analysis/max_query_depth.rb +20 -0
  12. data/lib/graphql/analysis/query_complexity.rb +263 -0
  13. data/lib/graphql/analysis/{ast/query_depth.rb → query_depth.rb} +23 -25
  14. data/lib/graphql/analysis/visitor.rb +280 -0
  15. data/lib/graphql/analysis.rb +95 -1
  16. data/lib/graphql/autoload.rb +38 -0
  17. data/lib/graphql/backtrace/table.rb +118 -55
  18. data/lib/graphql/backtrace.rb +1 -19
  19. data/lib/graphql/current.rb +57 -0
  20. data/lib/graphql/dashboard/detailed_traces.rb +47 -0
  21. data/lib/graphql/dashboard/installable.rb +22 -0
  22. data/lib/graphql/dashboard/limiters.rb +93 -0
  23. data/lib/graphql/dashboard/operation_store.rb +199 -0
  24. data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.css +6 -0
  25. data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.js +7 -0
  26. data/lib/graphql/dashboard/statics/charts.min.css +1 -0
  27. data/lib/graphql/dashboard/statics/dashboard.css +30 -0
  28. data/lib/graphql/dashboard/statics/dashboard.js +143 -0
  29. data/lib/graphql/dashboard/statics/header-icon.png +0 -0
  30. data/lib/graphql/dashboard/statics/icon.png +0 -0
  31. data/lib/graphql/dashboard/subscriptions.rb +96 -0
  32. data/lib/graphql/dashboard/views/graphql/dashboard/detailed_traces/traces/index.html.erb +45 -0
  33. data/lib/graphql/dashboard/views/graphql/dashboard/landings/show.html.erb +18 -0
  34. data/lib/graphql/dashboard/views/graphql/dashboard/limiters/limiters/show.html.erb +62 -0
  35. data/lib/graphql/dashboard/views/graphql/dashboard/not_installed.html.erb +18 -0
  36. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +23 -0
  37. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +21 -0
  38. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +69 -0
  39. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +7 -0
  40. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +39 -0
  41. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/show.html.erb +32 -0
  42. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/index.html.erb +81 -0
  43. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +71 -0
  44. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/subscriptions/show.html.erb +41 -0
  45. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/index.html.erb +55 -0
  46. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +40 -0
  47. data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +108 -0
  48. data/lib/graphql/dashboard.rb +158 -0
  49. data/lib/graphql/dataloader/active_record_association_source.rb +84 -0
  50. data/lib/graphql/dataloader/active_record_source.rb +47 -0
  51. data/lib/graphql/dataloader/async_dataloader.rb +46 -19
  52. data/lib/graphql/dataloader/null_dataloader.rb +51 -10
  53. data/lib/graphql/dataloader/source.rb +20 -9
  54. data/lib/graphql/dataloader.rb +153 -45
  55. data/lib/graphql/date_encoding_error.rb +1 -1
  56. data/lib/graphql/dig.rb +2 -1
  57. data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
  58. data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
  59. data/lib/graphql/execution/interpreter/resolve.rb +23 -25
  60. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +63 -5
  61. data/lib/graphql/execution/interpreter/runtime.rb +321 -222
  62. data/lib/graphql/execution/interpreter.rb +23 -30
  63. data/lib/graphql/execution/lookahead.rb +18 -11
  64. data/lib/graphql/execution/multiplex.rb +6 -5
  65. data/lib/graphql/introspection/directive_location_enum.rb +1 -1
  66. data/lib/graphql/introspection/directive_type.rb +1 -1
  67. data/lib/graphql/introspection/entry_points.rb +2 -2
  68. data/lib/graphql/introspection/field_type.rb +1 -1
  69. data/lib/graphql/introspection/schema_type.rb +6 -11
  70. data/lib/graphql/introspection/type_type.rb +5 -5
  71. data/lib/graphql/invalid_name_error.rb +1 -1
  72. data/lib/graphql/invalid_null_error.rb +20 -17
  73. data/lib/graphql/language/cache.rb +13 -0
  74. data/lib/graphql/language/comment.rb +18 -0
  75. data/lib/graphql/language/document_from_schema_definition.rb +64 -35
  76. data/lib/graphql/language/lexer.rb +72 -42
  77. data/lib/graphql/language/nodes.rb +93 -52
  78. data/lib/graphql/language/parser.rb +168 -61
  79. data/lib/graphql/language/printer.rb +31 -15
  80. data/lib/graphql/language/sanitized_printer.rb +1 -1
  81. data/lib/graphql/language.rb +61 -1
  82. data/lib/graphql/pagination/connection.rb +1 -1
  83. data/lib/graphql/query/context/scoped_context.rb +1 -1
  84. data/lib/graphql/query/context.rb +46 -47
  85. data/lib/graphql/query/null_context.rb +3 -5
  86. data/lib/graphql/query/partial.rb +179 -0
  87. data/lib/graphql/query/validation_pipeline.rb +2 -2
  88. data/lib/graphql/query/variable_validation_error.rb +1 -1
  89. data/lib/graphql/query.rb +123 -69
  90. data/lib/graphql/railtie.rb +7 -0
  91. data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
  92. data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
  93. data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
  94. data/lib/graphql/rubocop.rb +2 -0
  95. data/lib/graphql/schema/addition.rb +26 -13
  96. data/lib/graphql/schema/always_visible.rb +7 -2
  97. data/lib/graphql/schema/argument.rb +57 -8
  98. data/lib/graphql/schema/build_from_definition.rb +116 -49
  99. data/lib/graphql/schema/directive/flagged.rb +4 -2
  100. data/lib/graphql/schema/directive.rb +54 -2
  101. data/lib/graphql/schema/enum.rb +107 -24
  102. data/lib/graphql/schema/enum_value.rb +10 -2
  103. data/lib/graphql/schema/field/connection_extension.rb +1 -1
  104. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  105. data/lib/graphql/schema/field.rb +134 -45
  106. data/lib/graphql/schema/field_extension.rb +1 -1
  107. data/lib/graphql/schema/has_single_input_argument.rb +6 -2
  108. data/lib/graphql/schema/input_object.rb +122 -64
  109. data/lib/graphql/schema/interface.rb +23 -5
  110. data/lib/graphql/schema/introspection_system.rb +6 -17
  111. data/lib/graphql/schema/late_bound_type.rb +4 -0
  112. data/lib/graphql/schema/list.rb +3 -3
  113. data/lib/graphql/schema/loader.rb +3 -2
  114. data/lib/graphql/schema/member/base_dsl_methods.rb +15 -0
  115. data/lib/graphql/schema/member/has_arguments.rb +44 -58
  116. data/lib/graphql/schema/member/has_dataloader.rb +62 -0
  117. data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -0
  118. data/lib/graphql/schema/member/has_directives.rb +4 -4
  119. data/lib/graphql/schema/member/has_fields.rb +26 -6
  120. data/lib/graphql/schema/member/has_interfaces.rb +6 -6
  121. data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
  122. data/lib/graphql/schema/member/has_validators.rb +1 -1
  123. data/lib/graphql/schema/member/relay_shortcuts.rb +1 -1
  124. data/lib/graphql/schema/member/type_system_helpers.rb +17 -4
  125. data/lib/graphql/schema/member.rb +1 -0
  126. data/lib/graphql/schema/mutation.rb +7 -0
  127. data/lib/graphql/schema/object.rb +25 -8
  128. data/lib/graphql/schema/printer.rb +1 -0
  129. data/lib/graphql/schema/ractor_shareable.rb +79 -0
  130. data/lib/graphql/schema/relay_classic_mutation.rb +0 -1
  131. data/lib/graphql/schema/resolver.rb +29 -23
  132. data/lib/graphql/schema/scalar.rb +1 -6
  133. data/lib/graphql/schema/subscription.rb +52 -6
  134. data/lib/graphql/schema/timeout.rb +19 -2
  135. data/lib/graphql/schema/type_expression.rb +2 -2
  136. data/lib/graphql/schema/union.rb +1 -1
  137. data/lib/graphql/schema/validator/all_validator.rb +62 -0
  138. data/lib/graphql/schema/validator/required_validator.rb +92 -11
  139. data/lib/graphql/schema/validator.rb +3 -1
  140. data/lib/graphql/schema/visibility/migration.rb +188 -0
  141. data/lib/graphql/schema/visibility/profile.rb +445 -0
  142. data/lib/graphql/schema/visibility/visit.rb +190 -0
  143. data/lib/graphql/schema/visibility.rb +311 -0
  144. data/lib/graphql/schema/warden.rb +190 -20
  145. data/lib/graphql/schema.rb +695 -167
  146. data/lib/graphql/static_validation/all_rules.rb +2 -2
  147. data/lib/graphql/static_validation/base_visitor.rb +6 -5
  148. data/lib/graphql/static_validation/literal_validator.rb +4 -4
  149. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  150. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
  151. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
  152. data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -3
  153. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
  154. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +12 -2
  155. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +47 -13
  156. data/lib/graphql/static_validation/rules/fields_will_merge.rb +88 -25
  157. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +10 -2
  158. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  159. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
  160. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
  161. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
  162. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
  163. data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +25 -0
  164. data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
  165. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -4
  166. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
  167. data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +26 -0
  168. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +7 -3
  169. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
  170. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
  171. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
  172. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
  173. data/lib/graphql/static_validation/validation_context.rb +18 -2
  174. data/lib/graphql/static_validation/validator.rb +6 -1
  175. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +5 -3
  176. data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
  177. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +12 -10
  178. data/lib/graphql/subscriptions/event.rb +13 -2
  179. data/lib/graphql/subscriptions/serialize.rb +1 -1
  180. data/lib/graphql/subscriptions.rb +7 -5
  181. data/lib/graphql/testing/helpers.rb +48 -16
  182. data/lib/graphql/testing/mock_action_cable.rb +111 -0
  183. data/lib/graphql/testing.rb +1 -0
  184. data/lib/graphql/tracing/active_support_notifications_trace.rb +14 -3
  185. data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
  186. data/lib/graphql/tracing/appoptics_trace.rb +5 -1
  187. data/lib/graphql/tracing/appoptics_tracing.rb +7 -0
  188. data/lib/graphql/tracing/appsignal_trace.rb +32 -59
  189. data/lib/graphql/tracing/appsignal_tracing.rb +2 -0
  190. data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
  191. data/lib/graphql/tracing/data_dog_trace.rb +46 -162
  192. data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
  193. data/lib/graphql/tracing/detailed_trace/memory_backend.rb +60 -0
  194. data/lib/graphql/tracing/detailed_trace/redis_backend.rb +72 -0
  195. data/lib/graphql/tracing/detailed_trace.rb +141 -0
  196. data/lib/graphql/tracing/legacy_hooks_trace.rb +1 -0
  197. data/lib/graphql/tracing/legacy_trace.rb +4 -61
  198. data/lib/graphql/tracing/monitor_trace.rb +283 -0
  199. data/lib/graphql/tracing/new_relic_trace.rb +47 -54
  200. data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
  201. data/lib/graphql/tracing/notifications_trace.rb +183 -37
  202. data/lib/graphql/tracing/notifications_tracing.rb +2 -0
  203. data/lib/graphql/tracing/null_trace.rb +9 -0
  204. data/lib/graphql/tracing/perfetto_trace/trace.proto +141 -0
  205. data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +33 -0
  206. data/lib/graphql/tracing/perfetto_trace.rb +818 -0
  207. data/lib/graphql/tracing/platform_tracing.rb +1 -1
  208. data/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +2 -0
  209. data/lib/graphql/tracing/prometheus_trace.rb +73 -73
  210. data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
  211. data/lib/graphql/tracing/scout_trace.rb +32 -58
  212. data/lib/graphql/tracing/scout_tracing.rb +2 -0
  213. data/lib/graphql/tracing/sentry_trace.rb +64 -98
  214. data/lib/graphql/tracing/statsd_trace.rb +33 -45
  215. data/lib/graphql/tracing/statsd_tracing.rb +2 -0
  216. data/lib/graphql/tracing/trace.rb +111 -1
  217. data/lib/graphql/tracing.rb +31 -30
  218. data/lib/graphql/type_kinds.rb +2 -1
  219. data/lib/graphql/types/relay/connection_behaviors.rb +12 -2
  220. data/lib/graphql/types/relay/edge_behaviors.rb +11 -1
  221. data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
  222. data/lib/graphql/types.rb +18 -11
  223. data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
  224. data/lib/graphql/version.rb +1 -1
  225. data/lib/graphql.rb +64 -54
  226. metadata +197 -22
  227. data/lib/graphql/analysis/ast/analyzer.rb +0 -91
  228. data/lib/graphql/analysis/ast/field_usage.rb +0 -82
  229. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
  230. data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
  231. data/lib/graphql/analysis/ast/query_complexity.rb +0 -182
  232. data/lib/graphql/analysis/ast/visitor.rb +0 -276
  233. data/lib/graphql/analysis/ast.rb +0 -94
  234. data/lib/graphql/backtrace/inspect_result.rb +0 -50
  235. data/lib/graphql/backtrace/trace.rb +0 -93
  236. data/lib/graphql/backtrace/tracer.rb +0 -80
  237. data/lib/graphql/language/token.rb +0 -34
  238. data/lib/graphql/schema/invalid_type_error.rb +0 -7
  239. data/lib/graphql/schema/null_mask.rb +0 -11
  240. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +0 -17
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "strscan"
4
4
  require "graphql/language/nodes"
5
+ require "graphql/tracing/null_trace"
5
6
 
6
7
  module GraphQL
7
8
  module Language
@@ -12,8 +13,8 @@ module GraphQL
12
13
  class << self
13
14
  attr_accessor :cache
14
15
 
15
- def parse(graphql_str, filename: nil, trace: Tracing::NullTrace)
16
- self.new(graphql_str, filename: filename, trace: trace).parse
16
+ def parse(graphql_str, filename: nil, trace: Tracing::NullTrace, max_tokens: nil)
17
+ self.new(graphql_str, filename: filename, trace: trace, max_tokens: max_tokens).parse
17
18
  end
18
19
 
19
20
  def parse_file(filename, trace: Tracing::NullTrace)
@@ -27,14 +28,16 @@ module GraphQL
27
28
  end
28
29
  end
29
30
 
30
- def initialize(graphql_str, filename: nil, trace: Tracing::NullTrace)
31
+ def initialize(graphql_str, filename: nil, trace: Tracing::NullTrace, max_tokens: nil)
31
32
  if graphql_str.nil?
32
33
  raise GraphQL::ParseError.new("No query string was present", nil, nil, nil)
33
34
  end
34
- @lexer = Lexer.new(graphql_str, filename: filename)
35
+ @lexer = Lexer.new(graphql_str, filename: filename, max_tokens: max_tokens)
35
36
  @graphql_str = graphql_str
36
37
  @filename = filename
37
38
  @trace = trace
39
+ @dedup_identifiers = false
40
+ @lines_at = nil
38
41
  end
39
42
 
40
43
  def parse
@@ -47,9 +50,48 @@ module GraphQL
47
50
  end
48
51
  end
49
52
 
53
+ def tokens_count
54
+ parse
55
+ @lexer.tokens_count
56
+ end
57
+
58
+ def line_at(pos)
59
+ line = lines_at.bsearch_index { |l| l >= pos }
60
+ if line.nil?
61
+ @lines_at.size + 1
62
+ else
63
+ line + 1
64
+ end
65
+ end
66
+
67
+ def column_at(pos)
68
+ next_line_idx = lines_at.bsearch_index { |l| l >= pos } || 0
69
+ if next_line_idx > 0
70
+ line_pos = @lines_at[next_line_idx - 1]
71
+ pos - line_pos
72
+ else
73
+ pos + 1
74
+ end
75
+ end
50
76
 
51
77
  private
52
78
 
79
+ # @return [Array<Integer>] Positions of each line break in the original string
80
+ def lines_at
81
+ @lines_at ||= begin
82
+ la = []
83
+ idx = 0
84
+ while idx
85
+ idx = @graphql_str.index("\n", idx)
86
+ if idx
87
+ la << idx
88
+ idx += 1
89
+ end
90
+ end
91
+ la
92
+ end
93
+ end
94
+
53
95
  attr_reader :token_name
54
96
 
55
97
  def advance_token
@@ -69,10 +111,10 @@ module GraphQL
69
111
  # Only ignored characters is not a valid document
70
112
  raise GraphQL::ParseError.new("Unexpected end of document", nil, nil, @graphql_str)
71
113
  end
72
- while !@lexer.eos?
114
+ while !@lexer.finished?
73
115
  defns << definition
74
116
  end
75
- Document.new(pos: 0, definitions: defns, filename: @filename, source_string: @graphql_str)
117
+ Document.new(pos: 0, definitions: defns, filename: @filename, source: self)
76
118
  end
77
119
 
78
120
  def definition
@@ -94,7 +136,7 @@ module GraphQL
94
136
  directives: directives,
95
137
  selections: selections,
96
138
  filename: @filename,
97
- source_string: @graphql_str
139
+ source: self
98
140
  )
99
141
  when :QUERY, :MUTATION, :SUBSCRIPTION, :LCURLY
100
142
  op_loc = pos
@@ -105,7 +147,12 @@ module GraphQL
105
147
  parse_operation_type
106
148
  end
107
149
 
108
- op_name = at?(:IDENTIFIER) ? parse_name : nil
150
+ op_name = case token_name
151
+ when :LPAREN, :LCURLY, :DIR_SIGN
152
+ nil
153
+ else
154
+ parse_name
155
+ end
109
156
 
110
157
  variable_definitions = if at?(:LPAREN)
111
158
  expect_token(:LPAREN)
@@ -115,7 +162,7 @@ module GraphQL
115
162
  expect_token(:VAR_SIGN)
116
163
  var_name = parse_name
117
164
  expect_token(:COLON)
118
- var_type = self.type
165
+ var_type = self.type || raise_parse_error("Missing type definition for variable: $#{var_name}")
119
166
  default_value = if at?(:EQUALS)
120
167
  advance_token
121
168
  value
@@ -130,7 +177,7 @@ module GraphQL
130
177
  default_value: default_value,
131
178
  directives: directives,
132
179
  filename: @filename,
133
- source_string: @graphql_str
180
+ source: self
134
181
  )
135
182
  end
136
183
  expect_token(:RPAREN)
@@ -149,7 +196,7 @@ module GraphQL
149
196
  directives: directives,
150
197
  selections: selection_set,
151
198
  filename: @filename,
152
- source_string: @graphql_str
199
+ source: self
153
200
  )
154
201
  when :EXTEND
155
202
  loc = pos
@@ -159,7 +206,7 @@ module GraphQL
159
206
  advance_token
160
207
  name = parse_name
161
208
  directives = parse_directives
162
- ScalarTypeExtension.new(pos: loc, name: name, directives: directives, filename: @filename, source_string: @graphql_str)
209
+ ScalarTypeExtension.new(pos: loc, name: name, directives: directives, filename: @filename, source: self)
163
210
  when :TYPE
164
211
  advance_token
165
212
  name = parse_name
@@ -167,32 +214,32 @@ module GraphQL
167
214
  directives = parse_directives
168
215
  field_defns = at?(:LCURLY) ? parse_field_definitions : EMPTY_ARRAY
169
216
 
170
- ObjectTypeExtension.new(pos: loc, name: name, interfaces: implements_interfaces, directives: directives, fields: field_defns, filename: @filename, source_string: @graphql_str)
217
+ ObjectTypeExtension.new(pos: loc, name: name, interfaces: implements_interfaces, directives: directives, fields: field_defns, filename: @filename, source: self)
171
218
  when :INTERFACE
172
219
  advance_token
173
220
  name = parse_name
174
221
  directives = parse_directives
175
222
  interfaces = parse_implements
176
223
  fields_definition = at?(:LCURLY) ? parse_field_definitions : EMPTY_ARRAY
177
- InterfaceTypeExtension.new(pos: loc, name: name, directives: directives, fields: fields_definition, interfaces: interfaces, filename: @filename, source_string: @graphql_str)
224
+ InterfaceTypeExtension.new(pos: loc, name: name, directives: directives, fields: fields_definition, interfaces: interfaces, filename: @filename, source: self)
178
225
  when :UNION
179
226
  advance_token
180
227
  name = parse_name
181
228
  directives = parse_directives
182
229
  union_member_types = parse_union_members
183
- UnionTypeExtension.new(pos: loc, name: name, directives: directives, types: union_member_types, filename: @filename, source_string: @graphql_str)
230
+ UnionTypeExtension.new(pos: loc, name: name, directives: directives, types: union_member_types, filename: @filename, source: self)
184
231
  when :ENUM
185
232
  advance_token
186
233
  name = parse_name
187
234
  directives = parse_directives
188
235
  enum_values_definition = parse_enum_value_definitions
189
- Nodes::EnumTypeExtension.new(pos: loc, name: name, directives: directives, values: enum_values_definition, filename: @filename, source_string: @graphql_str)
236
+ Nodes::EnumTypeExtension.new(pos: loc, name: name, directives: directives, values: enum_values_definition, filename: @filename, source: self)
190
237
  when :INPUT
191
238
  advance_token
192
239
  name = parse_name
193
240
  directives = parse_directives
194
241
  input_fields_definition = parse_input_object_field_definitions
195
- InputObjectTypeExtension.new(pos: loc, name: name, directives: directives, fields: input_fields_definition, filename: @filename, source_string: @graphql_str)
242
+ InputObjectTypeExtension.new(pos: loc, name: name, directives: directives, fields: input_fields_definition, filename: @filename, source: self)
196
243
  when :SCHEMA
197
244
  advance_token
198
245
  directives = parse_directives
@@ -225,7 +272,7 @@ module GraphQL
225
272
  directives: directives,
226
273
  pos: loc,
227
274
  filename: @filename,
228
- source_string: @graphql_str,
275
+ source: self,
229
276
  )
230
277
  else
231
278
  expect_one_of([:SCHEMA, :SCALAR, :TYPE, :ENUM, :INPUT, :UNION, :INTERFACE])
@@ -258,7 +305,7 @@ module GraphQL
258
305
  end
259
306
  end
260
307
  expect_token :RCURLY
261
- SchemaDefinition.new(pos: loc, definition_pos: defn_loc, query: query, mutation: mutation, subscription: subscription, directives: directives, filename: @filename, source_string: @graphql_str)
308
+ SchemaDefinition.new(pos: loc, definition_pos: defn_loc, query: query, mutation: mutation, subscription: subscription, directives: directives, filename: @filename, source: self)
262
309
  when :DIRECTIVE
263
310
  advance_token
264
311
  expect_token :DIR_SIGN
@@ -271,12 +318,12 @@ module GraphQL
271
318
  false
272
319
  end
273
320
  expect_token :ON
274
- directive_locations = [DirectiveLocation.new(pos: pos, name: parse_name, filename: @filename, source_string: @graphql_str)]
321
+ directive_locations = [DirectiveLocation.new(pos: pos, name: parse_name, filename: @filename, source: self)]
275
322
  while at?(:PIPE)
276
323
  advance_token
277
- directive_locations << DirectiveLocation.new(pos: pos, name: parse_name, filename: @filename, source_string: @graphql_str)
324
+ directive_locations << DirectiveLocation.new(pos: pos, name: parse_name, filename: @filename, source: self)
278
325
  end
279
- DirectiveDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, arguments: arguments_definition, locations: directive_locations, repeatable: repeatable, filename: @filename, source_string: @graphql_str)
326
+ DirectiveDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, arguments: arguments_definition, locations: directive_locations, repeatable: repeatable, filename: @filename, source: self)
280
327
  when :TYPE
281
328
  advance_token
282
329
  name = parse_name
@@ -284,37 +331,37 @@ module GraphQL
284
331
  directives = parse_directives
285
332
  field_defns = at?(:LCURLY) ? parse_field_definitions : EMPTY_ARRAY
286
333
 
287
- ObjectTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, interfaces: implements_interfaces, directives: directives, fields: field_defns, filename: @filename, source_string: @graphql_str)
334
+ ObjectTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, interfaces: implements_interfaces, directives: directives, fields: field_defns, filename: @filename, source: self)
288
335
  when :INTERFACE
289
336
  advance_token
290
337
  name = parse_name
291
338
  interfaces = parse_implements
292
339
  directives = parse_directives
293
340
  fields_definition = parse_field_definitions
294
- InterfaceTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, fields: fields_definition, interfaces: interfaces, filename: @filename, source_string: @graphql_str)
341
+ InterfaceTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, fields: fields_definition, interfaces: interfaces, filename: @filename, source: self)
295
342
  when :UNION
296
343
  advance_token
297
344
  name = parse_name
298
345
  directives = parse_directives
299
346
  union_member_types = parse_union_members
300
- UnionTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, types: union_member_types, filename: @filename, source_string: @graphql_str)
347
+ UnionTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, types: union_member_types, filename: @filename, source: self)
301
348
  when :SCALAR
302
349
  advance_token
303
350
  name = parse_name
304
351
  directives = parse_directives
305
- ScalarTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, filename: @filename, source_string: @graphql_str)
352
+ ScalarTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, filename: @filename, source: self)
306
353
  when :ENUM
307
354
  advance_token
308
355
  name = parse_name
309
356
  directives = parse_directives
310
357
  enum_values_definition = parse_enum_value_definitions
311
- Nodes::EnumTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, values: enum_values_definition, filename: @filename, source_string: @graphql_str)
358
+ Nodes::EnumTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, values: enum_values_definition, filename: @filename, source: self)
312
359
  when :INPUT
313
360
  advance_token
314
361
  name = parse_name
315
362
  directives = parse_directives
316
363
  input_fields_definition = parse_input_object_field_definitions
317
- InputObjectTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, fields: input_fields_definition, filename: @filename, source_string: @graphql_str)
364
+ InputObjectTypeDefinition.new(pos: loc, definition_pos: defn_loc, description: desc, name: name, directives: directives, fields: input_fields_definition, filename: @filename, source: self)
318
365
  else
319
366
  expect_one_of([:SCHEMA, :SCALAR, :TYPE, :ENUM, :INPUT, :UNION, :INTERFACE])
320
367
  end
@@ -343,9 +390,14 @@ module GraphQL
343
390
  v_loc = pos
344
391
  description = if at?(:STRING); string_value; end
345
392
  defn_loc = pos
346
- enum_value = parse_enum_name
393
+ # Any identifier, but not true, false, or null
394
+ enum_value = if at?(:TRUE) || at?(:FALSE) || at?(:NULL)
395
+ expect_token(:IDENTIFIER)
396
+ else
397
+ parse_name
398
+ end
347
399
  v_directives = parse_directives
348
- list << EnumValueDefinition.new(pos: v_loc, definition_pos: defn_loc, description: description, name: enum_value, directives: v_directives, filename: @filename, source_string: @graphql_str)
400
+ list << EnumValueDefinition.new(pos: v_loc, definition_pos: defn_loc, description: description, name: enum_value, directives: v_directives, filename: @filename, source: self)
349
401
  end
350
402
  expect_token :RCURLY
351
403
  list
@@ -357,6 +409,9 @@ module GraphQL
357
409
  def parse_union_members
358
410
  if at?(:EQUALS)
359
411
  expect_token :EQUALS
412
+ if at?(:PIPE)
413
+ advance_token
414
+ end
360
415
  list = [parse_type_name]
361
416
  while at?(:PIPE)
362
417
  advance_token
@@ -396,7 +451,7 @@ module GraphQL
396
451
  type = self.type
397
452
  directives = parse_directives
398
453
 
399
- list << FieldDefinition.new(pos: loc, definition_pos: defn_loc, description: description, name: name, arguments: arguments_definition, type: type, directives: directives, filename: @filename, source_string: @graphql_str)
454
+ list << FieldDefinition.new(pos: loc, definition_pos: defn_loc, description: description, name: name, arguments: arguments_definition, type: type, directives: directives, filename: @filename, source: self)
400
455
  end
401
456
  expect_token :RCURLY
402
457
  list
@@ -430,30 +485,37 @@ module GraphQL
430
485
  nil
431
486
  end
432
487
  directives = parse_directives
433
- InputValueDefinition.new(pos: loc, definition_pos: defn_loc, description: description, name: name, type: type, default_value: default_value, directives: directives, filename: @filename, source_string: @graphql_str)
488
+ InputValueDefinition.new(pos: loc, definition_pos: defn_loc, description: description, name: name, type: type, default_value: default_value, directives: directives, filename: @filename, source: self)
434
489
  end
435
490
 
436
491
  def type
437
- type = case token_name
492
+ parsed_type = case token_name
438
493
  when :IDENTIFIER
439
494
  parse_type_name
440
495
  when :LBRACKET
441
496
  list_type
497
+ else
498
+ nil
442
499
  end
443
500
 
444
- if at?(:BANG)
445
- type = Nodes::NonNullType.new(pos: pos, of_type: type)
501
+ if at?(:BANG) && parsed_type
502
+ parsed_type = Nodes::NonNullType.new(pos: pos, of_type: parsed_type, source: self)
446
503
  expect_token(:BANG)
447
504
  end
448
- type
505
+ parsed_type
449
506
  end
450
507
 
451
508
  def list_type
452
509
  loc = pos
453
510
  expect_token(:LBRACKET)
454
- type = Nodes::ListType.new(pos: loc, of_type: self.type)
511
+ inner_type = self.type
512
+ parsed_list_type = if inner_type
513
+ Nodes::ListType.new(pos: loc, of_type: inner_type, source: self)
514
+ else
515
+ nil
516
+ end
455
517
  expect_token(:RBRACKET)
456
- type
518
+ parsed_list_type
457
519
  end
458
520
 
459
521
  def parse_operation_type
@@ -488,7 +550,7 @@ module GraphQL
488
550
 
489
551
  directives = parse_directives
490
552
 
491
- Nodes::InlineFragment.new(pos: loc, type: if_type, directives: directives, selections: selection_set, filename: @filename, source_string: @graphql_str)
553
+ Nodes::InlineFragment.new(pos: loc, type: if_type, directives: directives, selections: selection_set, filename: @filename, source: self)
492
554
  else
493
555
  name = parse_name_without_on
494
556
  directives = parse_directives
@@ -496,7 +558,7 @@ module GraphQL
496
558
  # Can this ever happen?
497
559
  # expect_token(:IDENTIFIER) if at?(:ON)
498
560
 
499
- FragmentSpread.new(pos: loc, name: name, directives: directives, filename: @filename, source_string: @graphql_str)
561
+ FragmentSpread.new(pos: loc, name: name, directives: directives, filename: @filename, source: self)
500
562
  end
501
563
  else
502
564
  loc = pos
@@ -514,7 +576,7 @@ module GraphQL
514
576
  directives = at?(:DIR_SIGN) ? parse_directives : nil
515
577
  selection_set = at?(:LCURLY) ? self.selection_set : nil
516
578
 
517
- Nodes::Field.new(pos: loc, field_alias: field_alias, name: name, arguments: arguments, directives: directives, selections: selection_set, filename: @filename, source_string: @graphql_str)
579
+ Nodes::Field.new(pos: loc, field_alias: field_alias, name: name, arguments: arguments, directives: directives, selections: selection_set, filename: @filename, source: self)
518
580
  end
519
581
  end
520
582
  expect_token(:RCURLY)
@@ -579,9 +641,6 @@ module GraphQL
579
641
  when :ON
580
642
  advance_token
581
643
  "on"
582
- when :DIRECTIVE
583
- advance_token
584
- "directive"
585
644
  when :EXTEND
586
645
  advance_token
587
646
  "extend"
@@ -598,17 +657,8 @@ module GraphQL
598
657
  end
599
658
  end
600
659
 
601
- # Any identifier, but not true, false, or null
602
- def parse_enum_name
603
- if at?(:TRUE) || at?(:FALSE) || at?(:NULL)
604
- expect_token(:IDENTIFIER)
605
- else
606
- parse_name
607
- end
608
- end
609
-
610
660
  def parse_type_name
611
- TypeName.new(pos: pos, name: parse_name, filename: @filename, source_string: @graphql_str)
661
+ TypeName.new(pos: pos, name: parse_name, filename: @filename, source: self)
612
662
  end
613
663
 
614
664
  def parse_directives
@@ -620,7 +670,7 @@ module GraphQL
620
670
  name = parse_name
621
671
  arguments = parse_arguments
622
672
 
623
- dirs << Nodes::Directive.new(pos: loc, name: name, arguments: arguments, filename: @filename, source_string: @graphql_str)
673
+ dirs << Nodes::Directive.new(pos: loc, name: name, arguments: arguments, filename: @filename, source: self)
624
674
  end
625
675
  dirs
626
676
  else
@@ -636,7 +686,7 @@ module GraphQL
636
686
  loc = pos
637
687
  name = parse_name
638
688
  expect_token(:COLON)
639
- args << Nodes::Argument.new(pos: loc, name: name, value: value, filename: @filename, source_string: @graphql_str)
689
+ args << Nodes::Argument.new(pos: loc, name: name, value: value, filename: @filename, source: self)
640
690
  end
641
691
  if args.empty?
642
692
  expect_token(:ARGUMENT_NAME) # At least one argument is required
@@ -670,9 +720,9 @@ module GraphQL
670
720
  false
671
721
  when :NULL
672
722
  advance_token
673
- NullValue.new(pos: pos, name: "null", filename: @filename, source_string: @graphql_str)
723
+ NullValue.new(pos: pos, name: "null", filename: @filename, source: self)
674
724
  when :IDENTIFIER
675
- Nodes::Enum.new(pos: pos, name: expect_token_value(:IDENTIFIER), filename: @filename, source_string: @graphql_str)
725
+ Nodes::Enum.new(pos: pos, name: expect_token_value(:IDENTIFIER), filename: @filename, source: self)
676
726
  when :LBRACKET
677
727
  advance_token
678
728
  list = []
@@ -689,14 +739,62 @@ module GraphQL
689
739
  loc = pos
690
740
  n = parse_name
691
741
  expect_token(:COLON)
692
- args << Argument.new(pos: loc, name: n, value: value, filename: @filename, source_string: @graphql_str)
742
+ args << Argument.new(pos: loc, name: n, value: value, filename: @filename, source: self)
693
743
  end
694
744
  expect_token(:RCURLY)
695
- InputObject.new(pos: start, arguments: args, filename: @filename, source_string: @graphql_str)
745
+ InputObject.new(pos: start, arguments: args, filename: @filename, source: self)
696
746
  when :VAR_SIGN
697
747
  loc = pos
698
748
  advance_token
699
- VariableIdentifier.new(pos: loc, name: parse_name, filename: @filename, source_string: @graphql_str)
749
+ VariableIdentifier.new(pos: loc, name: parse_name, filename: @filename, source: self)
750
+ when :SCHEMA
751
+ advance_token
752
+ Nodes::Enum.new(pos: pos, name: "schema", filename: @filename, source: self)
753
+ when :SCALAR
754
+ advance_token
755
+ Nodes::Enum.new(pos: pos, name: "scalar", filename: @filename, source: self)
756
+ when :IMPLEMENTS
757
+ advance_token
758
+ Nodes::Enum.new(pos: pos, name: "implements", filename: @filename, source: self)
759
+ when :INTERFACE
760
+ advance_token
761
+ Nodes::Enum.new(pos: pos, name: "interface", filename: @filename, source: self)
762
+ when :UNION
763
+ advance_token
764
+ Nodes::Enum.new(pos: pos, name: "union", filename: @filename, source: self)
765
+ when :ENUM
766
+ advance_token
767
+ Nodes::Enum.new(pos: pos, name: "enum", filename: @filename, source: self)
768
+ when :INPUT
769
+ advance_token
770
+ Nodes::Enum.new(pos: pos, name: "input", filename: @filename, source: self)
771
+ when :DIRECTIVE
772
+ advance_token
773
+ Nodes::Enum.new(pos: pos, name: "directive", filename: @filename, source: self)
774
+ when :TYPE
775
+ advance_token
776
+ Nodes::Enum.new(pos: pos, name: "type", filename: @filename, source: self)
777
+ when :QUERY
778
+ advance_token
779
+ Nodes::Enum.new(pos: pos, name: "query", filename: @filename, source: self)
780
+ when :MUTATION
781
+ advance_token
782
+ Nodes::Enum.new(pos: pos, name: "mutation", filename: @filename, source: self)
783
+ when :SUBSCRIPTION
784
+ advance_token
785
+ Nodes::Enum.new(pos: pos, name: "subscription", filename: @filename, source: self)
786
+ when :FRAGMENT
787
+ advance_token
788
+ Nodes::Enum.new(pos: pos, name: "fragment", filename: @filename, source: self)
789
+ when :REPEATABLE
790
+ advance_token
791
+ Nodes::Enum.new(pos: pos, name: "repeatable", filename: @filename, source: self)
792
+ when :ON
793
+ advance_token
794
+ Nodes::Enum.new(pos: pos, name: "on", filename: @filename, source: self)
795
+ when :EXTEND
796
+ advance_token
797
+ Nodes::Enum.new(pos: pos, name: "extend", filename: @filename, source: self)
700
798
  else
701
799
  expect_token(:VALUE)
702
800
  end
@@ -732,6 +830,9 @@ module GraphQL
732
830
  # Only use when we care about the expected token's value
733
831
  def expect_token_value(tok)
734
832
  token_value = @lexer.token_value
833
+ if @dedup_identifiers
834
+ token_value = -token_value
835
+ end
735
836
  expect_token(tok)
736
837
  token_value
737
838
  end
@@ -741,6 +842,12 @@ module GraphQL
741
842
  def debug_token_value
742
843
  @lexer.debug_token_value(token_name)
743
844
  end
845
+ class SchemaParser < Parser
846
+ def initialize(*args, **kwargs)
847
+ super
848
+ @dedup_identifiers = true
849
+ end
850
+ end
744
851
  end
745
852
  end
746
853
  end
@@ -92,7 +92,7 @@ module GraphQL
92
92
  print_string("@")
93
93
  print_string(directive.name)
94
94
 
95
- if directive.arguments.any?
95
+ if !directive.arguments.empty?
96
96
  print_string("(")
97
97
  directive.arguments.each_with_index do |a, i|
98
98
  print_argument(a)
@@ -117,7 +117,7 @@ module GraphQL
117
117
  print_string(": ")
118
118
  end
119
119
  print_string(field.name)
120
- if field.arguments.any?
120
+ if !field.arguments.empty?
121
121
  print_string("(")
122
122
  field.arguments.each_with_index do |a, i|
123
123
  print_argument(a)
@@ -182,7 +182,7 @@ module GraphQL
182
182
  print_string(operation_definition.name)
183
183
  end
184
184
 
185
- if operation_definition.variables.any?
185
+ if !operation_definition.variables.empty?
186
186
  print_string("(")
187
187
  operation_definition.variables.each_with_index do |v, i|
188
188
  print_variable_definition(v)
@@ -230,7 +230,7 @@ module GraphQL
230
230
 
231
231
  extension ? print_string("extend schema") : print_string("schema")
232
232
 
233
- if schema.directives.any?
233
+ if !schema.directives.empty?
234
234
  schema.directives.each do |dir|
235
235
  print_string("\n ")
236
236
  print_node(dir)
@@ -255,14 +255,14 @@ module GraphQL
255
255
 
256
256
 
257
257
  def print_scalar_type_definition(scalar_type, extension: false)
258
- extension ? print_string("extend ") : print_description(scalar_type)
258
+ extension ? print_string("extend ") : print_description_and_comment(scalar_type)
259
259
  print_string("scalar ")
260
260
  print_string(scalar_type.name)
261
261
  print_directives(scalar_type.directives)
262
262
  end
263
263
 
264
264
  def print_object_type_definition(object_type, extension: false)
265
- extension ? print_string("extend ") : print_description(object_type)
265
+ extension ? print_string("extend ") : print_description_and_comment(object_type)
266
266
  print_string("type ")
267
267
  print_string(object_type.name)
268
268
  print_implements(object_type) unless object_type.interfaces.empty?
@@ -294,7 +294,7 @@ module GraphQL
294
294
  end
295
295
 
296
296
  def print_arguments(arguments, indent: "")
297
- if arguments.all? { |arg| !arg.description }
297
+ if arguments.all? { |arg| !arg.description && !arg.comment }
298
298
  print_string("(")
299
299
  arguments.each_with_index do |arg, i|
300
300
  print_input_value_definition(arg)
@@ -306,6 +306,7 @@ module GraphQL
306
306
 
307
307
  print_string("(\n")
308
308
  arguments.each_with_index do |arg, i|
309
+ print_comment(arg, indent: " " + indent, first_in_block: i == 0)
309
310
  print_description(arg, indent: " " + indent, first_in_block: i == 0)
310
311
  print_string(" ")
311
312
  print_string(indent)
@@ -328,20 +329,20 @@ module GraphQL
328
329
  end
329
330
 
330
331
  def print_interface_type_definition(interface_type, extension: false)
331
- extension ? print_string("extend ") : print_description(interface_type)
332
+ extension ? print_string("extend ") : print_description_and_comment(interface_type)
332
333
  print_string("interface ")
333
334
  print_string(interface_type.name)
334
- print_implements(interface_type) if interface_type.interfaces.any?
335
+ print_implements(interface_type) if !interface_type.interfaces.empty?
335
336
  print_directives(interface_type.directives)
336
337
  print_field_definitions(interface_type.fields)
337
338
  end
338
339
 
339
340
  def print_union_type_definition(union_type, extension: false)
340
- extension ? print_string("extend ") : print_description(union_type)
341
+ extension ? print_string("extend ") : print_description_and_comment(union_type)
341
342
  print_string("union ")
342
343
  print_string(union_type.name)
343
344
  print_directives(union_type.directives)
344
- if union_type.types.any?
345
+ if !union_type.types.empty?
345
346
  print_string(" = ")
346
347
  i = 0
347
348
  union_type.types.each do |t|
@@ -355,14 +356,15 @@ module GraphQL
355
356
  end
356
357
 
357
358
  def print_enum_type_definition(enum_type, extension: false)
358
- extension ? print_string("extend ") : print_description(enum_type)
359
+ extension ? print_string("extend ") : print_description_and_comment(enum_type)
359
360
  print_string("enum ")
360
361
  print_string(enum_type.name)
361
362
  print_directives(enum_type.directives)
362
- if enum_type.values.any?
363
+ if !enum_type.values.empty?
363
364
  print_string(" {\n")
364
365
  enum_type.values.each.with_index do |value, i|
365
366
  print_description(value, indent: " ", first_in_block: i == 0)
367
+ print_comment(value, indent: " ", first_in_block: i == 0)
366
368
  print_enum_value_definition(value)
367
369
  end
368
370
  print_string("}")
@@ -377,7 +379,7 @@ module GraphQL
377
379
  end
378
380
 
379
381
  def print_input_object_type_definition(input_object_type, extension: false)
380
- extension ? print_string("extend ") : print_description(input_object_type)
382
+ extension ? print_string("extend ") : print_description_and_comment(input_object_type)
381
383
  print_string("input ")
382
384
  print_string(input_object_type.name)
383
385
  print_directives(input_object_type.directives)
@@ -385,6 +387,7 @@ module GraphQL
385
387
  print_string(" {\n")
386
388
  input_object_type.fields.each.with_index do |field, i|
387
389
  print_description(field, indent: " ", first_in_block: i == 0)
390
+ print_comment(field, indent: " ", first_in_block: i == 0)
388
391
  print_string(" ")
389
392
  print_input_value_definition(field)
390
393
  print_string("\n")
@@ -398,7 +401,7 @@ module GraphQL
398
401
  print_string("directive @")
399
402
  print_string(directive.name)
400
403
 
401
- if directive.arguments.any?
404
+ if !directive.arguments.empty?
402
405
  print_arguments(directive.arguments)
403
406
  end
404
407
 
@@ -424,6 +427,18 @@ module GraphQL
424
427
  print_string(GraphQL::Language::BlockString.print(node.description, indent: indent))
425
428
  end
426
429
 
430
+ def print_comment(node, indent: "", first_in_block: true)
431
+ return unless node.comment
432
+
433
+ print_string("\n") if indent != "" && !first_in_block
434
+ print_string(GraphQL::Language::Comment.print(node.comment, indent: indent))
435
+ end
436
+
437
+ def print_description_and_comment(node)
438
+ print_description(node)
439
+ print_comment(node)
440
+ end
441
+
427
442
  def print_field_definitions(fields)
428
443
  return if fields.empty?
429
444
 
@@ -431,6 +446,7 @@ module GraphQL
431
446
  i = 0
432
447
  fields.each do |field|
433
448
  print_description(field, indent: " ", first_in_block: i == 0)
449
+ print_comment(field, indent: " ", first_in_block: i == 0)
434
450
  print_string(" ")
435
451
  print_field_definition(field)
436
452
  print_string("\n")