graphql 2.3.7 → 2.4.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +46 -0
  3. data/lib/generators/graphql/orm_mutations_base.rb +1 -1
  4. data/lib/generators/graphql/templates/base_resolver.erb +2 -0
  5. data/lib/generators/graphql/type_generator.rb +1 -1
  6. data/lib/graphql/analysis/field_usage.rb +1 -1
  7. data/lib/graphql/analysis/query_complexity.rb +3 -3
  8. data/lib/graphql/analysis/visitor.rb +8 -7
  9. data/lib/graphql/analysis.rb +4 -4
  10. data/lib/graphql/autoload.rb +38 -0
  11. data/lib/graphql/current.rb +52 -0
  12. data/lib/graphql/dataloader/async_dataloader.rb +7 -6
  13. data/lib/graphql/dataloader/source.rb +7 -4
  14. data/lib/graphql/dataloader.rb +40 -19
  15. data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
  16. data/lib/graphql/execution/interpreter/resolve.rb +13 -9
  17. data/lib/graphql/execution/interpreter/runtime.rb +35 -31
  18. data/lib/graphql/execution/interpreter.rb +9 -5
  19. data/lib/graphql/execution/lookahead.rb +18 -11
  20. data/lib/graphql/introspection/directive_type.rb +1 -1
  21. data/lib/graphql/introspection/entry_points.rb +2 -2
  22. data/lib/graphql/introspection/field_type.rb +1 -1
  23. data/lib/graphql/introspection/schema_type.rb +6 -11
  24. data/lib/graphql/introspection/type_type.rb +5 -5
  25. data/lib/graphql/invalid_null_error.rb +1 -1
  26. data/lib/graphql/language/cache.rb +13 -0
  27. data/lib/graphql/language/comment.rb +18 -0
  28. data/lib/graphql/language/document_from_schema_definition.rb +62 -34
  29. data/lib/graphql/language/lexer.rb +18 -15
  30. data/lib/graphql/language/nodes.rb +24 -16
  31. data/lib/graphql/language/parser.rb +14 -1
  32. data/lib/graphql/language/printer.rb +31 -15
  33. data/lib/graphql/language/sanitized_printer.rb +1 -1
  34. data/lib/graphql/language.rb +6 -6
  35. data/lib/graphql/pagination/connection.rb +1 -1
  36. data/lib/graphql/query/context/scoped_context.rb +1 -1
  37. data/lib/graphql/query/context.rb +13 -6
  38. data/lib/graphql/query/null_context.rb +3 -5
  39. data/lib/graphql/query/variable_validation_error.rb +1 -1
  40. data/lib/graphql/query.rb +72 -18
  41. data/lib/graphql/railtie.rb +7 -0
  42. data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
  43. data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
  44. data/lib/graphql/rubocop.rb +2 -0
  45. data/lib/graphql/schema/addition.rb +2 -1
  46. data/lib/graphql/schema/always_visible.rb +6 -2
  47. data/lib/graphql/schema/argument.rb +14 -1
  48. data/lib/graphql/schema/build_from_definition.rb +9 -1
  49. data/lib/graphql/schema/directive/flagged.rb +2 -2
  50. data/lib/graphql/schema/directive.rb +1 -1
  51. data/lib/graphql/schema/enum.rb +71 -23
  52. data/lib/graphql/schema/enum_value.rb +10 -2
  53. data/lib/graphql/schema/field/connection_extension.rb +1 -1
  54. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  55. data/lib/graphql/schema/field.rb +102 -47
  56. data/lib/graphql/schema/field_extension.rb +1 -1
  57. data/lib/graphql/schema/has_single_input_argument.rb +5 -2
  58. data/lib/graphql/schema/input_object.rb +90 -39
  59. data/lib/graphql/schema/interface.rb +22 -5
  60. data/lib/graphql/schema/introspection_system.rb +5 -16
  61. data/lib/graphql/schema/loader.rb +1 -1
  62. data/lib/graphql/schema/member/base_dsl_methods.rb +15 -0
  63. data/lib/graphql/schema/member/has_arguments.rb +36 -23
  64. data/lib/graphql/schema/member/has_directives.rb +3 -3
  65. data/lib/graphql/schema/member/has_fields.rb +26 -6
  66. data/lib/graphql/schema/member/has_interfaces.rb +4 -4
  67. data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
  68. data/lib/graphql/schema/member/has_validators.rb +1 -1
  69. data/lib/graphql/schema/object.rb +8 -0
  70. data/lib/graphql/schema/printer.rb +1 -0
  71. data/lib/graphql/schema/relay_classic_mutation.rb +0 -1
  72. data/lib/graphql/schema/resolver.rb +12 -14
  73. data/lib/graphql/schema/subscription.rb +52 -6
  74. data/lib/graphql/schema/type_expression.rb +2 -2
  75. data/lib/graphql/schema/union.rb +1 -1
  76. data/lib/graphql/schema/validator/all_validator.rb +62 -0
  77. data/lib/graphql/schema/validator/required_validator.rb +28 -4
  78. data/lib/graphql/schema/validator.rb +3 -1
  79. data/lib/graphql/schema/visibility/migration.rb +188 -0
  80. data/lib/graphql/schema/visibility/profile.rb +359 -0
  81. data/lib/graphql/schema/visibility/visit.rb +190 -0
  82. data/lib/graphql/schema/visibility.rb +294 -0
  83. data/lib/graphql/schema/warden.rb +179 -16
  84. data/lib/graphql/schema.rb +348 -94
  85. data/lib/graphql/static_validation/base_visitor.rb +6 -5
  86. data/lib/graphql/static_validation/literal_validator.rb +4 -4
  87. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  88. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
  89. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
  90. data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -3
  91. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
  92. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +12 -2
  93. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +2 -2
  94. data/lib/graphql/static_validation/rules/fields_will_merge.rb +8 -7
  95. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  96. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
  97. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
  98. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
  99. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
  100. data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
  101. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -4
  102. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
  103. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
  104. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
  105. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
  106. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
  107. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
  108. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
  109. data/lib/graphql/static_validation/validation_context.rb +18 -2
  110. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +3 -2
  111. data/lib/graphql/subscriptions/broadcast_analyzer.rb +10 -4
  112. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +12 -10
  113. data/lib/graphql/subscriptions/event.rb +13 -2
  114. data/lib/graphql/subscriptions/serialize.rb +2 -0
  115. data/lib/graphql/subscriptions.rb +6 -4
  116. data/lib/graphql/testing/helpers.rb +10 -6
  117. data/lib/graphql/tracing/active_support_notifications_trace.rb +1 -1
  118. data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
  119. data/lib/graphql/tracing/appoptics_trace.rb +2 -0
  120. data/lib/graphql/tracing/appoptics_tracing.rb +2 -0
  121. data/lib/graphql/tracing/appsignal_trace.rb +2 -0
  122. data/lib/graphql/tracing/appsignal_tracing.rb +2 -0
  123. data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
  124. data/lib/graphql/tracing/data_dog_trace.rb +2 -0
  125. data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
  126. data/lib/graphql/tracing/legacy_hooks_trace.rb +1 -0
  127. data/lib/graphql/tracing/legacy_trace.rb +4 -61
  128. data/lib/graphql/tracing/new_relic_trace.rb +2 -0
  129. data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
  130. data/lib/graphql/tracing/notifications_trace.rb +2 -2
  131. data/lib/graphql/tracing/notifications_tracing.rb +2 -0
  132. data/lib/graphql/tracing/null_trace.rb +9 -0
  133. data/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +2 -0
  134. data/lib/graphql/tracing/prometheus_trace.rb +5 -0
  135. data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
  136. data/lib/graphql/tracing/scout_trace.rb +2 -0
  137. data/lib/graphql/tracing/scout_tracing.rb +2 -0
  138. data/lib/graphql/tracing/sentry_trace.rb +2 -0
  139. data/lib/graphql/tracing/statsd_trace.rb +2 -0
  140. data/lib/graphql/tracing/statsd_tracing.rb +2 -0
  141. data/lib/graphql/tracing/trace.rb +3 -0
  142. data/lib/graphql/tracing.rb +28 -30
  143. data/lib/graphql/types/relay/connection_behaviors.rb +12 -2
  144. data/lib/graphql/types/relay/edge_behaviors.rb +11 -1
  145. data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
  146. data/lib/graphql/types.rb +18 -11
  147. data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
  148. data/lib/graphql/version.rb +1 -1
  149. data/lib/graphql.rb +53 -45
  150. metadata +33 -8
  151. data/lib/graphql/language/token.rb +0 -34
  152. data/lib/graphql/schema/invalid_type_error.rb +0 -7
@@ -18,21 +18,15 @@ module GraphQL
18
18
  include_built_in_directives: false, include_built_in_scalars: false, always_include_schema: false
19
19
  )
20
20
  @schema = schema
21
+ @context = context
21
22
  @always_include_schema = always_include_schema
22
23
  @include_introspection_types = include_introspection_types
23
24
  @include_built_in_scalars = include_built_in_scalars
24
25
  @include_built_in_directives = include_built_in_directives
25
26
  @include_one_of = false
26
27
 
27
- schema_context = schema.context_class.new(query: nil, schema: schema, values: context)
28
-
29
-
30
- @warden = @schema.warden_class.new(
31
- schema: @schema,
32
- context: schema_context,
33
- )
34
-
35
- schema_context.warden = @warden
28
+ dummy_query = @schema.query_class.new(@schema, "{ __typename }", validate: false, context: context)
29
+ @types = dummy_query.types # rubocop:disable Development/ContextIsPassedCop
36
30
  end
37
31
 
38
32
  def document
@@ -44,9 +38,9 @@ module GraphQL
44
38
  def build_schema_node
45
39
  if !schema_respects_root_name_conventions?(@schema)
46
40
  GraphQL::Language::Nodes::SchemaDefinition.new(
47
- query: (q = warden.root_type_for_operation("query")) && q.graphql_name,
48
- mutation: (m = warden.root_type_for_operation("mutation")) && m.graphql_name,
49
- subscription: (s = warden.root_type_for_operation("subscription")) && s.graphql_name,
41
+ query: @types.query_root&.graphql_name,
42
+ mutation: @types.mutation_root&.graphql_name,
43
+ subscription: @types.subscription_root&.graphql_name,
50
44
  directives: definition_directives(@schema, :schema_directives)
51
45
  )
52
46
  else
@@ -57,16 +51,17 @@ module GraphQL
57
51
  end
58
52
 
59
53
  def build_object_type_node(object_type)
60
- ints = warden.interfaces(object_type)
61
- if ints.any?
54
+ ints = @types.interfaces(object_type)
55
+ if !ints.empty?
62
56
  ints.sort_by!(&:graphql_name)
63
57
  ints.map! { |iface| build_type_name_node(iface) }
64
58
  end
65
59
 
66
60
  GraphQL::Language::Nodes::ObjectTypeDefinition.new(
67
61
  name: object_type.graphql_name,
62
+ comment: object_type.comment,
68
63
  interfaces: ints,
69
- fields: build_field_nodes(warden.fields(object_type)),
64
+ fields: build_field_nodes(@types.fields(object_type)),
70
65
  description: object_type.description,
71
66
  directives: directives(object_type),
72
67
  )
@@ -75,7 +70,8 @@ module GraphQL
75
70
  def build_field_node(field)
76
71
  GraphQL::Language::Nodes::FieldDefinition.new(
77
72
  name: field.graphql_name,
78
- arguments: build_argument_nodes(warden.arguments(field)),
73
+ comment: field.comment,
74
+ arguments: build_argument_nodes(@types.arguments(field)),
79
75
  type: build_type_name_node(field.type),
80
76
  description: field.description,
81
77
  directives: directives(field),
@@ -85,8 +81,9 @@ module GraphQL
85
81
  def build_union_type_node(union_type)
86
82
  GraphQL::Language::Nodes::UnionTypeDefinition.new(
87
83
  name: union_type.graphql_name,
84
+ comment: union_type.comment,
88
85
  description: union_type.description,
89
- types: warden.possible_types(union_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
86
+ types: @types.possible_types(union_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
90
87
  directives: directives(union_type),
91
88
  )
92
89
  end
@@ -94,9 +91,10 @@ module GraphQL
94
91
  def build_interface_type_node(interface_type)
95
92
  GraphQL::Language::Nodes::InterfaceTypeDefinition.new(
96
93
  name: interface_type.graphql_name,
97
- interfaces: warden.interfaces(interface_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
94
+ comment: interface_type.comment,
95
+ interfaces: @types.interfaces(interface_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
98
96
  description: interface_type.description,
99
- fields: build_field_nodes(warden.fields(interface_type)),
97
+ fields: build_field_nodes(@types.fields(interface_type)),
100
98
  directives: directives(interface_type),
101
99
  )
102
100
  end
@@ -104,7 +102,8 @@ module GraphQL
104
102
  def build_enum_type_node(enum_type)
105
103
  GraphQL::Language::Nodes::EnumTypeDefinition.new(
106
104
  name: enum_type.graphql_name,
107
- values: warden.enum_values(enum_type).sort_by(&:graphql_name).map do |enum_value|
105
+ comment: enum_type.comment,
106
+ values: @types.enum_values(enum_type).sort_by(&:graphql_name).map do |enum_value|
108
107
  build_enum_value_node(enum_value)
109
108
  end,
110
109
  description: enum_type.description,
@@ -115,6 +114,7 @@ module GraphQL
115
114
  def build_enum_value_node(enum_value)
116
115
  GraphQL::Language::Nodes::EnumValueDefinition.new(
117
116
  name: enum_value.graphql_name,
117
+ comment: enum_value.comment,
118
118
  description: enum_value.description,
119
119
  directives: directives(enum_value),
120
120
  )
@@ -123,6 +123,7 @@ module GraphQL
123
123
  def build_scalar_type_node(scalar_type)
124
124
  GraphQL::Language::Nodes::ScalarTypeDefinition.new(
125
125
  name: scalar_type.graphql_name,
126
+ comment: scalar_type.comment,
126
127
  description: scalar_type.description,
127
128
  directives: directives(scalar_type),
128
129
  )
@@ -137,6 +138,7 @@ module GraphQL
137
138
 
138
139
  argument_node = GraphQL::Language::Nodes::InputValueDefinition.new(
139
140
  name: argument.graphql_name,
141
+ comment: argument.comment,
140
142
  description: argument.description,
141
143
  type: build_type_name_node(argument.type),
142
144
  default_value: default_value,
@@ -149,7 +151,8 @@ module GraphQL
149
151
  def build_input_object_node(input_object)
150
152
  GraphQL::Language::Nodes::InputObjectTypeDefinition.new(
151
153
  name: input_object.graphql_name,
152
- fields: build_argument_nodes(warden.arguments(input_object)),
154
+ comment: input_object.comment,
155
+ fields: build_argument_nodes(@types.arguments(input_object)),
153
156
  description: input_object.description,
154
157
  directives: directives(input_object),
155
158
  )
@@ -159,7 +162,7 @@ module GraphQL
159
162
  GraphQL::Language::Nodes::DirectiveDefinition.new(
160
163
  name: directive.graphql_name,
161
164
  repeatable: directive.repeatable?,
162
- arguments: build_argument_nodes(warden.arguments(directive)),
165
+ arguments: build_argument_nodes(@types.arguments(directive)),
163
166
  locations: build_directive_location_nodes(directive.locations),
164
167
  description: directive.description,
165
168
  )
@@ -204,7 +207,7 @@ module GraphQL
204
207
  when "INPUT_OBJECT"
205
208
  GraphQL::Language::Nodes::InputObject.new(
206
209
  arguments: default_value.to_h.map do |arg_name, arg_value|
207
- args = @warden.arguments(type)
210
+ args = @types.arguments(type)
208
211
  arg = args.find { |a| a.keyword.to_s == arg_name.to_s }
209
212
  if arg.nil?
210
213
  raise ArgumentError, "No argument definition on #{type.graphql_name} for argument: #{arg_name.inspect} (expected one of: #{args.map(&:keyword)})"
@@ -244,7 +247,7 @@ module GraphQL
244
247
  end
245
248
 
246
249
  def build_argument_nodes(arguments)
247
- if arguments.any?
250
+ if !arguments.empty?
248
251
  nodes = arguments.map { |arg| build_argument_node(arg) }
249
252
  nodes.sort_by!(&:name)
250
253
  nodes
@@ -260,13 +263,39 @@ module GraphQL
260
263
  end
261
264
 
262
265
  def build_definition_nodes
263
- dirs_to_build = warden.directives
266
+ dirs_to_build = @types.directives
264
267
  if !include_built_in_directives
265
268
  dirs_to_build = dirs_to_build.reject { |directive| directive.default_directive? }
266
269
  end
267
270
  definitions = build_directive_nodes(dirs_to_build)
271
+ all_types = @types.all_types
272
+ type_nodes = build_type_definition_nodes(all_types)
273
+
274
+ if !(ex_t = schema.extra_types).empty?
275
+ dummy_query = Class.new(GraphQL::Schema::Object) do
276
+ graphql_name "DummyQuery"
277
+ (all_types + ex_t).each_with_index do |type, idx|
278
+ if !type.kind.input_object? && !type.introspection?
279
+ field "f#{idx}", type
280
+ end
281
+ end
282
+ end
283
+
284
+ extra_types_schema = Class.new(GraphQL::Schema) do
285
+ query(dummy_query)
286
+ end
287
+
288
+ extra_types_types = GraphQL::Query.new(extra_types_schema, "{ __typename }", context: @context).types # rubocop:disable Development/ContextIsPassedCop
289
+ # Temporarily replace `@types` with something from this example schema.
290
+ # It'd be much nicer to pass this in, but that would be a big refactor :S
291
+ prev_types = @types
292
+ @types = extra_types_types
293
+ type_nodes += build_type_definition_nodes(ex_t)
294
+ @types = prev_types
295
+ end
296
+
297
+ type_nodes.sort_by!(&:name)
268
298
 
269
- type_nodes = build_type_definition_nodes(warden.reachable_types + schema.extra_types)
270
299
  if @include_one_of
271
300
  # This may have been set to true when iterating over all types
272
301
  definitions.concat(build_directive_nodes([GraphQL::Schema::Directive::OneOf]))
@@ -289,9 +318,7 @@ module GraphQL
289
318
  types = types.reject { |type| type.kind.scalar? && type.default_scalar? }
290
319
  end
291
320
 
292
- types
293
- .map { |type| build_type_definition_node(type) }
294
- .sort_by(&:name)
321
+ types.map { |type| build_type_definition_node(type) }
295
322
  end
296
323
 
297
324
  def build_field_nodes(fields)
@@ -319,10 +346,11 @@ module GraphQL
319
346
  end
320
347
 
321
348
  def definition_directives(member, directives_method)
322
- dirs = if !member.respond_to?(directives_method) || member.directives.empty?
349
+ if !member.respond_to?(directives_method) || member.directives.empty?
323
350
  EmptyObjects::EMPTY_ARRAY
324
351
  else
325
- member.public_send(directives_method).map do |dir|
352
+ visible_directives = member.public_send(directives_method).select { |dir| @types.directive_exists?(dir.graphql_name) }
353
+ visible_directives.map! do |dir|
326
354
  args = []
327
355
  dir.arguments.argument_values.each_value do |arg_value| # rubocop:disable Development/ContextIsPassedCop -- directive instance method
328
356
  arg_defn = arg_value.definition
@@ -346,12 +374,12 @@ module GraphQL
346
374
  arguments: args
347
375
  )
348
376
  end
349
- end
350
377
 
351
- dirs
378
+ visible_directives
379
+ end
352
380
  end
353
381
 
354
- attr_reader :schema, :warden, :always_include_schema,
382
+ attr_reader :schema, :always_include_schema,
355
383
  :include_introspection_types, :include_built_in_directives, :include_built_in_scalars
356
384
  end
357
385
  end
@@ -19,7 +19,7 @@ module GraphQL
19
19
  @scanner.eos?
20
20
  end
21
21
 
22
- attr_reader :pos
22
+ attr_reader :pos, :tokens_count
23
23
 
24
24
  def advance
25
25
  @scanner.skip(IGNORE_REGEXP)
@@ -57,20 +57,26 @@ module GraphQL
57
57
  @scanner.skip(IDENTIFIER_REGEXP)
58
58
  :IDENTIFIER
59
59
  when ByteFor::NUMBER
60
- @scanner.skip(NUMERIC_REGEXP)
60
+ if len = @scanner.skip(NUMERIC_REGEXP)
61
61
 
62
- if GraphQL.reject_numbers_followed_by_names
63
- new_pos = @scanner.pos
64
- peek_byte = @string.getbyte(new_pos)
65
- next_first_byte = FIRST_BYTES[peek_byte]
66
- if next_first_byte == ByteFor::NAME || next_first_byte == ByteFor::IDENTIFIER
67
- number_part = token_value
68
- name_part = @scanner.scan(IDENTIFIER_REGEXP)
69
- raise_parse_error("Name after number is not allowed (in `#{number_part}#{name_part}`)")
62
+ if GraphQL.reject_numbers_followed_by_names
63
+ new_pos = @scanner.pos
64
+ peek_byte = @string.getbyte(new_pos)
65
+ next_first_byte = FIRST_BYTES[peek_byte]
66
+ if next_first_byte == ByteFor::NAME || next_first_byte == ByteFor::IDENTIFIER
67
+ number_part = token_value
68
+ name_part = @scanner.scan(IDENTIFIER_REGEXP)
69
+ raise_parse_error("Name after number is not allowed (in `#{number_part}#{name_part}`)")
70
+ end
70
71
  end
72
+ # Check for a matched decimal:
73
+ @scanner[1] ? :FLOAT : :INT
74
+ else
75
+ # Attempt to find the part after the `-`
76
+ value = @scanner.scan(/-\s?[a-z0-9]*/i)
77
+ invalid_byte_for_number_error_message = "Expected type 'number', but it was malformed#{value.nil? ? "" : ": #{value.inspect}"}."
78
+ raise_parse_error(invalid_byte_for_number_error_message)
71
79
  end
72
- # Check for a matched decimal:
73
- @scanner[1] ? :FLOAT : :INT
74
80
  when ByteFor::ELLIPSIS
75
81
  if @string.getbyte(@pos + 1) != 46 || @string.getbyte(@pos + 2) != 46
76
82
  raise_parse_error("Expected `...`, actual: #{@string[@pos..@pos + 2].inspect}")
@@ -345,17 +351,14 @@ module GraphQL
345
351
  def self.tokenize(string)
346
352
  lexer = GraphQL::Language::Lexer.new(string)
347
353
  tokens = []
348
- prev_token = nil
349
354
  while (token_name = lexer.advance)
350
355
  new_token = [
351
356
  token_name,
352
357
  lexer.line_number,
353
358
  lexer.column_number,
354
359
  lexer.debug_token_value(token_name),
355
- prev_token,
356
360
  ]
357
361
  tokens << new_token
358
- prev_token = new_token
359
362
  end
360
363
  tokens
361
364
  end
@@ -34,11 +34,11 @@ module GraphQL
34
34
  attr_reader :filename
35
35
 
36
36
  def line
37
- @line ||= @source.line_at(@pos)
37
+ @line ||= @source&.line_at(@pos)
38
38
  end
39
39
 
40
40
  def col
41
- @col ||= @source.column_at(@pos)
41
+ @col ||= @source&.column_at(@pos)
42
42
  end
43
43
 
44
44
  def definition_line
@@ -270,15 +270,17 @@ module GraphQL
270
270
  "col: nil",
271
271
  "pos: nil",
272
272
  "filename: nil",
273
- "source: nil",
273
+ "source: nil"
274
274
  ]
275
275
 
276
+ IGNORED_MARSHALLING_KEYWORDS = [:comment]
277
+
276
278
  def generate_initialize
277
279
  return if method_defined?(:marshal_load, false) # checking for `:initialize` doesn't work right
278
280
 
279
281
  scalar_method_names = @scalar_methods
280
282
  # TODO: These probably should be scalar methods, but `types` returns an array
281
- [:types, :description].each do |extra_method|
283
+ [:types, :description, :comment].each do |extra_method|
282
284
  if method_defined?(extra_method)
283
285
  scalar_method_names += [extra_method]
284
286
  end
@@ -307,6 +309,12 @@ module GraphQL
307
309
  keywords = scalar_method_names.map { |m| "#{m}: #{m}"} +
308
310
  children_method_names.map { |m| "#{m}: #{m}" }
309
311
 
312
+ ignored_keywords = IGNORED_MARSHALLING_KEYWORDS.map do |keyword|
313
+ "#{keyword.to_s}: nil"
314
+ end
315
+
316
+ marshalling_method_names = all_method_names - IGNORED_MARSHALLING_KEYWORDS
317
+
310
318
  module_eval <<-RUBY, __FILE__, __LINE__
311
319
  def initialize(#{arguments.join(", ")})
312
320
  @line = line
@@ -317,7 +325,7 @@ module GraphQL
317
325
  #{assignments.join("\n")}
318
326
  end
319
327
 
320
- def self.from_a(filename, line, col, #{all_method_names.join(", ")})
328
+ def self.from_a(filename, line, col, #{marshalling_method_names.join(", ")}, #{ignored_keywords.join(", ")})
321
329
  self.new(filename: filename, line: line, col: col, #{keywords.join(", ")})
322
330
  end
323
331
 
@@ -325,12 +333,12 @@ module GraphQL
325
333
  [
326
334
  line, col, # use methods here to force them to be calculated
327
335
  @filename,
328
- #{all_method_names.map { |n| "@#{n}," }.join}
336
+ #{marshalling_method_names.map { |n| "@#{n}," }.join}
329
337
  ]
330
338
  end
331
339
 
332
340
  def marshal_load(values)
333
- @line, @col, @filename #{all_method_names.map { |n| ", @#{n}"}.join} = values
341
+ @line, @col, @filename #{marshalling_method_names.map { |n| ", @#{n}"}.join} = values
334
342
  end
335
343
  RUBY
336
344
  end
@@ -635,7 +643,7 @@ module GraphQL
635
643
  end
636
644
 
637
645
  class ScalarTypeDefinition < AbstractNode
638
- attr_reader :description
646
+ attr_reader :description, :comment
639
647
  scalar_methods :name
640
648
  children_methods({
641
649
  directives: GraphQL::Language::Nodes::Directive,
@@ -652,7 +660,7 @@ module GraphQL
652
660
  end
653
661
 
654
662
  class InputValueDefinition < AbstractNode
655
- attr_reader :description
663
+ attr_reader :description, :comment
656
664
  scalar_methods :name, :type, :default_value
657
665
  children_methods({
658
666
  directives: GraphQL::Language::Nodes::Directive,
@@ -661,7 +669,7 @@ module GraphQL
661
669
  end
662
670
 
663
671
  class FieldDefinition < AbstractNode
664
- attr_reader :description
672
+ attr_reader :description, :comment
665
673
  scalar_methods :name, :type
666
674
  children_methods({
667
675
  arguments: GraphQL::Language::Nodes::InputValueDefinition,
@@ -681,7 +689,7 @@ module GraphQL
681
689
  end
682
690
 
683
691
  class ObjectTypeDefinition < AbstractNode
684
- attr_reader :description
692
+ attr_reader :description, :comment
685
693
  scalar_methods :name, :interfaces
686
694
  children_methods({
687
695
  directives: GraphQL::Language::Nodes::Directive,
@@ -700,7 +708,7 @@ module GraphQL
700
708
  end
701
709
 
702
710
  class InterfaceTypeDefinition < AbstractNode
703
- attr_reader :description
711
+ attr_reader :description, :comment
704
712
  scalar_methods :name
705
713
  children_methods({
706
714
  interfaces: GraphQL::Language::Nodes::TypeName,
@@ -721,7 +729,7 @@ module GraphQL
721
729
  end
722
730
 
723
731
  class UnionTypeDefinition < AbstractNode
724
- attr_reader :description, :types
732
+ attr_reader :description, :comment, :types
725
733
  scalar_methods :name
726
734
  children_methods({
727
735
  directives: GraphQL::Language::Nodes::Directive,
@@ -739,7 +747,7 @@ module GraphQL
739
747
  end
740
748
 
741
749
  class EnumValueDefinition < AbstractNode
742
- attr_reader :description
750
+ attr_reader :description, :comment
743
751
  scalar_methods :name
744
752
  children_methods({
745
753
  directives: GraphQL::Language::Nodes::Directive,
@@ -748,7 +756,7 @@ module GraphQL
748
756
  end
749
757
 
750
758
  class EnumTypeDefinition < AbstractNode
751
- attr_reader :description
759
+ attr_reader :description, :comment
752
760
  scalar_methods :name
753
761
  children_methods({
754
762
  directives: GraphQL::Language::Nodes::Directive,
@@ -767,7 +775,7 @@ module GraphQL
767
775
  end
768
776
 
769
777
  class InputObjectTypeDefinition < AbstractNode
770
- attr_reader :description
778
+ attr_reader :description, :comment
771
779
  scalar_methods :name
772
780
  children_methods({
773
781
  directives: GraphQL::Language::Nodes::Directive,
@@ -49,6 +49,11 @@ module GraphQL
49
49
  end
50
50
  end
51
51
 
52
+ def tokens_count
53
+ parse
54
+ @lexer.tokens_count
55
+ end
56
+
52
57
  def line_at(pos)
53
58
  line = lines_at.bsearch_index { |l| l >= pos }
54
59
  if line.nil?
@@ -141,7 +146,12 @@ module GraphQL
141
146
  parse_operation_type
142
147
  end
143
148
 
144
- op_name = at?(:IDENTIFIER) ? parse_name : nil
149
+ op_name = case token_name
150
+ when :LPAREN, :LCURLY, :DIR_SIGN
151
+ nil
152
+ else
153
+ parse_name
154
+ end
145
155
 
146
156
  variable_definitions = if at?(:LPAREN)
147
157
  expect_token(:LPAREN)
@@ -398,6 +408,9 @@ module GraphQL
398
408
  def parse_union_members
399
409
  if at?(:EQUALS)
400
410
  expect_token :EQUALS
411
+ if at?(:PIPE)
412
+ advance_token
413
+ end
401
414
  list = [parse_type_name]
402
415
  while at?(:PIPE)
403
416
  advance_token
@@ -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")
@@ -113,7 +113,7 @@ module GraphQL
113
113
  end
114
114
 
115
115
  def print_field(field, indent: "")
116
- @current_field = query.get_field(@current_type, field.name)
116
+ @current_field = query.types.field(@current_type, field.name)
117
117
  old_type = @current_type
118
118
  @current_type = @current_field.type.unwrap
119
119
  super