graphql 2.0.14 → 2.0.32

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 (118) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/mutation_delete_generator.rb +1 -1
  3. data/lib/generators/graphql/mutation_update_generator.rb +1 -1
  4. data/lib/generators/graphql/relay.rb +18 -1
  5. data/lib/graphql/analysis/ast/visitor.rb +42 -35
  6. data/lib/graphql/analysis/ast.rb +2 -2
  7. data/lib/graphql/backtrace/table.rb +2 -2
  8. data/lib/graphql/backtrace/trace.rb +96 -0
  9. data/lib/graphql/backtrace/tracer.rb +1 -1
  10. data/lib/graphql/backtrace.rb +2 -1
  11. data/lib/graphql/dataloader/source.rb +69 -45
  12. data/lib/graphql/dataloader.rb +8 -5
  13. data/lib/graphql/execution/interpreter/arguments.rb +1 -1
  14. data/lib/graphql/execution/interpreter/arguments_cache.rb +33 -33
  15. data/lib/graphql/execution/interpreter/resolve.rb +19 -0
  16. data/lib/graphql/execution/interpreter/runtime.rb +355 -268
  17. data/lib/graphql/execution/interpreter.rb +19 -15
  18. data/lib/graphql/execution/lazy.rb +6 -12
  19. data/lib/graphql/execution/lookahead.rb +16 -5
  20. data/lib/graphql/execution/multiplex.rb +2 -1
  21. data/lib/graphql/filter.rb +8 -2
  22. data/lib/graphql/introspection/directive_type.rb +2 -2
  23. data/lib/graphql/introspection/entry_points.rb +1 -1
  24. data/lib/graphql/introspection/field_type.rb +1 -1
  25. data/lib/graphql/introspection/schema_type.rb +2 -2
  26. data/lib/graphql/introspection/type_type.rb +5 -5
  27. data/lib/graphql/introspection.rb +1 -1
  28. data/lib/graphql/language/document_from_schema_definition.rb +58 -35
  29. data/lib/graphql/language/lexer.rb +248 -1505
  30. data/lib/graphql/language/nodes.rb +69 -40
  31. data/lib/graphql/language/parser.rb +775 -742
  32. data/lib/graphql/language/parser.y +44 -38
  33. data/lib/graphql/language/printer.rb +48 -25
  34. data/lib/graphql/language/visitor.rb +192 -81
  35. data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
  36. data/lib/graphql/pagination/connection.rb +5 -5
  37. data/lib/graphql/query/context.rb +93 -27
  38. data/lib/graphql/query/null_context.rb +8 -18
  39. data/lib/graphql/query/validation_pipeline.rb +2 -1
  40. data/lib/graphql/query.rb +55 -13
  41. data/lib/graphql/rake_task.rb +28 -1
  42. data/lib/graphql/schema/addition.rb +38 -12
  43. data/lib/graphql/schema/always_visible.rb +10 -0
  44. data/lib/graphql/schema/argument.rb +15 -23
  45. data/lib/graphql/schema/build_from_definition.rb +54 -25
  46. data/lib/graphql/schema/directive/transform.rb +1 -1
  47. data/lib/graphql/schema/directive.rb +12 -2
  48. data/lib/graphql/schema/enum.rb +24 -17
  49. data/lib/graphql/schema/enum_value.rb +3 -4
  50. data/lib/graphql/schema/field/connection_extension.rb +1 -1
  51. data/lib/graphql/schema/field.rb +95 -73
  52. data/lib/graphql/schema/field_extension.rb +1 -4
  53. data/lib/graphql/schema/find_inherited_value.rb +2 -7
  54. data/lib/graphql/schema/input_object.rb +9 -7
  55. data/lib/graphql/schema/interface.rb +5 -11
  56. data/lib/graphql/schema/introspection_system.rb +1 -1
  57. data/lib/graphql/schema/late_bound_type.rb +2 -0
  58. data/lib/graphql/schema/member/base_dsl_methods.rb +17 -14
  59. data/lib/graphql/schema/member/build_type.rb +11 -3
  60. data/lib/graphql/schema/member/has_arguments.rb +114 -65
  61. data/lib/graphql/schema/member/has_ast_node.rb +12 -0
  62. data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
  63. data/lib/graphql/schema/member/has_directives.rb +81 -61
  64. data/lib/graphql/schema/member/has_fields.rb +95 -38
  65. data/lib/graphql/schema/member/has_interfaces.rb +49 -8
  66. data/lib/graphql/schema/member/has_validators.rb +32 -6
  67. data/lib/graphql/schema/member/relay_shortcuts.rb +19 -0
  68. data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
  69. data/lib/graphql/schema/object.rb +8 -5
  70. data/lib/graphql/schema/printer.rb +3 -1
  71. data/lib/graphql/schema/relay_classic_mutation.rb +1 -1
  72. data/lib/graphql/schema/resolver/has_payload_type.rb +9 -9
  73. data/lib/graphql/schema/resolver.rb +16 -14
  74. data/lib/graphql/schema/timeout.rb +25 -29
  75. data/lib/graphql/schema/type_membership.rb +3 -0
  76. data/lib/graphql/schema/union.rb +10 -1
  77. data/lib/graphql/schema/validator.rb +2 -2
  78. data/lib/graphql/schema/warden.rb +64 -7
  79. data/lib/graphql/schema.rb +171 -28
  80. data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
  81. data/lib/graphql/static_validation/literal_validator.rb +15 -1
  82. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
  83. data/lib/graphql/static_validation/rules/fields_will_merge.rb +2 -2
  84. data/lib/graphql/static_validation/validator.rb +1 -1
  85. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -1
  86. data/lib/graphql/subscriptions/event.rb +2 -7
  87. data/lib/graphql/subscriptions.rb +5 -0
  88. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  89. data/lib/graphql/tracing/appoptics_trace.rb +255 -0
  90. data/lib/graphql/tracing/appsignal_trace.rb +81 -0
  91. data/lib/graphql/tracing/data_dog_trace.rb +187 -0
  92. data/lib/graphql/tracing/data_dog_tracing.rb +7 -21
  93. data/lib/graphql/tracing/legacy_trace.rb +69 -0
  94. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  95. data/lib/graphql/tracing/notifications_trace.rb +49 -0
  96. data/lib/graphql/tracing/platform_trace.rb +123 -0
  97. data/lib/graphql/tracing/platform_tracing.rb +15 -3
  98. data/lib/graphql/tracing/prometheus_trace.rb +93 -0
  99. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +1 -1
  100. data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
  101. data/lib/graphql/tracing/scout_trace.rb +75 -0
  102. data/lib/graphql/tracing/statsd_trace.rb +60 -0
  103. data/lib/graphql/tracing/trace.rb +75 -0
  104. data/lib/graphql/tracing.rb +17 -39
  105. data/lib/graphql/type_kinds.rb +6 -3
  106. data/lib/graphql/types/relay/base_connection.rb +1 -1
  107. data/lib/graphql/types/relay/connection_behaviors.rb +28 -6
  108. data/lib/graphql/types/relay/edge_behaviors.rb +16 -5
  109. data/lib/graphql/types/relay/node_behaviors.rb +8 -2
  110. data/lib/graphql/types/relay/page_info_behaviors.rb +7 -2
  111. data/lib/graphql/types/relay.rb +0 -1
  112. data/lib/graphql/types/string.rb +1 -1
  113. data/lib/graphql/version.rb +1 -1
  114. data/lib/graphql.rb +16 -9
  115. data/readme.md +1 -1
  116. metadata +66 -29
  117. data/lib/graphql/language/lexer.rl +0 -280
  118. data/lib/graphql/types/relay/default_relay.rb +0 -21
@@ -150,6 +150,7 @@ rule
150
150
  | REPEATABLE
151
151
  | TRUE
152
152
  | FALSE
153
+ | NULL
153
154
  | operation_type
154
155
  | schema_keyword
155
156
 
@@ -162,7 +163,7 @@ rule
162
163
  | schema_keyword
163
164
 
164
165
  enum_value_definition:
165
- description_opt enum_name directives_list_opt { result = make_node(:EnumValueDefinition, name: val[1], directives: val[2], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1]) }
166
+ description_opt enum_name directives_list_opt { result = make_node(:EnumValueDefinition, name: val[1], directives: val[2], description: val[0] || get_description(val[1]), definition_line: val[1][1], position_source: val[0] || val[1]) }
166
167
 
167
168
  enum_value_definitions:
168
169
  enum_value_definition { result = [val[0]] }
@@ -180,9 +181,9 @@ rule
180
181
  name COLON input_value { result = make_node(:Argument, name: val[0], value: val[2], position_source: val[0])}
181
182
 
182
183
  literal_value:
183
- FLOAT { result = val[0].to_f }
184
- | INT { result = val[0].to_i }
185
- | STRING { result = val[0].to_s }
184
+ FLOAT { result = val[0][3].to_f }
185
+ | INT { result = val[0][3].to_i }
186
+ | STRING { result = val[0][3] }
186
187
  | TRUE { result = true }
187
188
  | FALSE { result = false }
188
189
  | null_value
@@ -284,14 +285,18 @@ rule
284
285
  | directive_definition
285
286
 
286
287
  schema_definition:
287
- SCHEMA directives_list_opt LCURLY operation_type_definition_list RCURLY { result = make_node(:SchemaDefinition, position_source: val[0], definition_line: val[0].line, directives: val[1], **val[3]) }
288
+ SCHEMA directives_list_opt operation_type_definition_list_opt { result = make_node(:SchemaDefinition, position_source: val[0], definition_line: val[0][1], directives: val[1], **val[2]) }
289
+
290
+ operation_type_definition_list_opt:
291
+ /* none */ { result = {} }
292
+ | LCURLY operation_type_definition_list RCURLY { result = val[1] }
288
293
 
289
294
  operation_type_definition_list:
290
295
  operation_type_definition
291
296
  | operation_type_definition_list operation_type_definition { result = val[0].merge(val[1]) }
292
297
 
293
298
  operation_type_definition:
294
- operation_type COLON name { result = { val[0].to_s.to_sym => val[2] } }
299
+ operation_type COLON name { result = { val[0][3].to_sym => val[2] } }
295
300
 
296
301
  type_definition:
297
302
  scalar_type_definition
@@ -351,12 +356,12 @@ rule
351
356
 
352
357
  scalar_type_definition:
353
358
  description_opt SCALAR name directives_list_opt {
354
- result = make_node(:ScalarTypeDefinition, name: val[2], directives: val[3], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1])
359
+ result = make_node(:ScalarTypeDefinition, name: val[2], directives: val[3], description: val[0] || get_description(val[1]), definition_line: val[1][1], position_source: val[0] || val[1])
355
360
  }
356
361
 
357
362
  object_type_definition:
358
363
  description_opt TYPE name implements_opt directives_list_opt field_definition_list_opt {
359
- result = make_node(:ObjectTypeDefinition, name: val[2], interfaces: val[3], directives: val[4], fields: val[5], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1])
364
+ result = make_node(:ObjectTypeDefinition, name: val[2], interfaces: val[3], directives: val[4], fields: val[5], description: val[0] || get_description(val[1]), definition_line: val[1][1], position_source: val[0] || val[1])
360
365
  }
361
366
 
362
367
  implements_opt:
@@ -378,7 +383,7 @@ rule
378
383
 
379
384
  input_value_definition:
380
385
  description_opt name COLON type default_value_opt directives_list_opt {
381
- result = make_node(:InputValueDefinition, name: val[1], type: val[3], default_value: val[4], directives: val[5], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1])
386
+ result = make_node(:InputValueDefinition, name: val[1], type: val[3], default_value: val[4], directives: val[5], description: val[0] || get_description(val[1]), definition_line: val[1][1], position_source: val[0] || val[1])
382
387
  }
383
388
 
384
389
  input_value_definition_list:
@@ -391,7 +396,7 @@ rule
391
396
 
392
397
  field_definition:
393
398
  description_opt name arguments_definitions_opt COLON type directives_list_opt {
394
- result = make_node(:FieldDefinition, name: val[1], arguments: val[2], type: val[4], directives: val[5], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1])
399
+ result = make_node(:FieldDefinition, name: val[1], arguments: val[2], type: val[4], directives: val[5], description: val[0] || get_description(val[1]), definition_line: val[1][1], position_source: val[0] || val[1])
395
400
  }
396
401
 
397
402
  field_definition_list_opt:
@@ -405,7 +410,7 @@ rule
405
410
 
406
411
  interface_type_definition:
407
412
  description_opt INTERFACE name implements_opt directives_list_opt field_definition_list_opt {
408
- result = make_node(:InterfaceTypeDefinition, name: val[2], interfaces: val[3], directives: val[4], fields: val[5], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1])
413
+ result = make_node(:InterfaceTypeDefinition, name: val[2], interfaces: val[3], directives: val[4], fields: val[5], description: val[0] || get_description(val[1]), definition_line: val[1][1], position_source: val[0] || val[1])
409
414
  }
410
415
 
411
416
  union_members:
@@ -414,22 +419,22 @@ rule
414
419
 
415
420
  union_type_definition:
416
421
  description_opt UNION name directives_list_opt EQUALS union_members {
417
- result = make_node(:UnionTypeDefinition, name: val[2], directives: val[3], types: val[5], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1])
422
+ result = make_node(:UnionTypeDefinition, name: val[2], directives: val[3], types: val[5], description: val[0] || get_description(val[1]), definition_line: val[1][1], position_source: val[0] || val[1])
418
423
  }
419
424
 
420
425
  enum_type_definition:
421
426
  description_opt ENUM name directives_list_opt LCURLY enum_value_definitions RCURLY {
422
- result = make_node(:EnumTypeDefinition, name: val[2], directives: val[3], values: val[5], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1])
427
+ result = make_node(:EnumTypeDefinition, name: val[2], directives: val[3], values: val[5], description: val[0] || get_description(val[1]), definition_line: val[1][1], position_source: val[0] || val[1])
423
428
  }
424
429
 
425
430
  input_object_type_definition:
426
431
  description_opt INPUT name directives_list_opt LCURLY input_value_definition_list RCURLY {
427
- result = make_node(:InputObjectTypeDefinition, name: val[2], directives: val[3], fields: val[5], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1])
432
+ result = make_node(:InputObjectTypeDefinition, name: val[2], directives: val[3], fields: val[5], description: val[0] || get_description(val[1]), definition_line: val[1][1], position_source: val[0] || val[1])
428
433
  }
429
434
 
430
435
  directive_definition:
431
436
  description_opt DIRECTIVE DIR_SIGN name arguments_definitions_opt directive_repeatable_opt ON directive_locations {
432
- result = make_node(:DirectiveDefinition, name: val[3], arguments: val[4], locations: val[7], repeatable: !!val[5], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1])
437
+ result = make_node(:DirectiveDefinition, name: val[3], arguments: val[4], locations: val[7], repeatable: !!val[5], description: val[0] || get_description(val[1]), definition_line: val[1][1], position_source: val[0] || val[1])
433
438
  }
434
439
 
435
440
  directive_repeatable_opt:
@@ -437,8 +442,8 @@ rule
437
442
  | REPEATABLE
438
443
 
439
444
  directive_locations:
440
- name { result = [make_node(:DirectiveLocation, name: val[0].to_s, position_source: val[0])] }
441
- | directive_locations PIPE name { val[0] << make_node(:DirectiveLocation, name: val[2].to_s, position_source: val[2]) }
445
+ name { result = [make_node(:DirectiveLocation, name: val[0][3], position_source: val[0])] }
446
+ | directive_locations PIPE name { val[0] << make_node(:DirectiveLocation, name: val[2][3], position_source: val[2]) }
442
447
  end
443
448
 
444
449
  ---- header ----
@@ -448,22 +453,22 @@ end
448
453
 
449
454
  EMPTY_ARRAY = [].freeze
450
455
 
451
- def initialize(query_string, filename:, tracer: Tracing::NullTracer)
456
+ def initialize(query_string, filename:, trace: Tracing::NullTrace)
452
457
  raise GraphQL::ParseError.new("No query string was present", nil, nil, query_string) if query_string.nil?
453
458
  @query_string = query_string
454
459
  @filename = filename
455
- @tracer = tracer
460
+ @trace = trace
456
461
  @reused_next_token = [nil, nil]
457
462
  end
458
463
 
459
464
  def parse_document
460
465
  @document ||= begin
461
466
  # Break the string into tokens
462
- @tracer.trace("lex", {query_string: @query_string}) do
463
- @tokens ||= GraphQL.scan(@query_string)
467
+ @trace.lex(query_string: @query_string) do
468
+ @tokens ||= GraphQL::Language::Lexer.tokenize(@query_string)
464
469
  end
465
470
  # From the tokens, build an AST
466
- @tracer.trace("parse", {query_string: @query_string}) do
471
+ @trace.parse(query_string: @query_string) do
467
472
  if @tokens.empty?
468
473
  raise GraphQL::ParseError.new("Unexpected end of document", nil, nil, @query_string)
469
474
  else
@@ -476,17 +481,17 @@ end
476
481
  class << self
477
482
  attr_accessor :cache
478
483
 
479
- def parse(query_string, filename: nil, tracer: GraphQL::Tracing::NullTracer)
480
- new(query_string, filename: filename, tracer: tracer).parse_document
484
+ def parse(query_string, filename: nil, trace: GraphQL::Tracing::NullTrace)
485
+ new(query_string, filename: filename, trace: trace).parse_document
481
486
  end
482
487
 
483
- def parse_file(filename, tracer: GraphQL::Tracing::NullTracer)
488
+ def parse_file(filename, trace: GraphQL::Tracing::NullTrace)
484
489
  if cache
485
490
  cache.fetch(filename) do
486
- parse(File.read(filename), filename: filename, tracer: tracer)
491
+ parse(File.read(filename), filename: filename, trace: trace)
487
492
  end
488
493
  else
489
- parse(File.read(filename), filename: filename, tracer: tracer)
494
+ parse(File.read(filename), filename: filename, trace: trace)
490
495
  end
491
496
  end
492
497
  end
@@ -498,7 +503,7 @@ def next_token
498
503
  if lexer_token.nil?
499
504
  nil
500
505
  else
501
- @reused_next_token[0] = lexer_token.name
506
+ @reused_next_token[0] = lexer_token[0]
502
507
  @reused_next_token[1] = lexer_token
503
508
  @reused_next_token
504
509
  end
@@ -509,13 +514,13 @@ def get_description(token)
509
514
 
510
515
  loop do
511
516
  prev_token = token
512
- token = token.prev_token
517
+ token = token[4]
513
518
 
514
519
  break if token.nil?
515
- break if token.name != :COMMENT
516
- break if prev_token.line != token.line + 1
520
+ break if token[0] != :COMMENT
521
+ break if prev_token[1] != token[1] + 1
517
522
 
518
- comments.unshift(token.to_s.sub(/^#\s*/, ""))
523
+ comments.unshift(token[3].sub(/^#\s*/, ""))
519
524
  end
520
525
 
521
526
  return nil if comments.empty?
@@ -531,11 +536,12 @@ def on_error(parser_token_id, lexer_token, vstack)
531
536
  if parser_token_name.nil?
532
537
  raise GraphQL::ParseError.new("Parse Error on unknown token: {token_id: #{parser_token_id}, lexer_token: #{lexer_token}} from #{@query_string}", nil, nil, @query_string, filename: @filename)
533
538
  else
534
- line, col = lexer_token.line_and_column
535
- if lexer_token.name == :BAD_UNICODE_ESCAPE
536
- raise GraphQL::ParseError.new("Parse error on bad Unicode escape sequence: #{lexer_token.to_s.inspect} (#{parser_token_name}) at [#{line}, #{col}]", line, col, @query_string, filename: @filename)
539
+ line = lexer_token[1]
540
+ col = lexer_token[2]
541
+ if lexer_token[0] == :BAD_UNICODE_ESCAPE
542
+ raise GraphQL::ParseError.new("Parse error on bad Unicode escape sequence: #{lexer_token[3].inspect} (#{parser_token_name}) at [#{line}, #{col}]", line, col, @query_string, filename: @filename)
537
543
  else
538
- raise GraphQL::ParseError.new("Parse error on #{lexer_token.to_s.inspect} (#{parser_token_name}) at [#{line}, #{col}]", line, col, @query_string, filename: @filename)
544
+ raise GraphQL::ParseError.new("Parse error on #{lexer_token[3].inspect} (#{parser_token_name}) at [#{line}, #{col}]", line, col, @query_string, filename: @filename)
539
545
  end
540
546
  end
541
547
  end
@@ -543,8 +549,8 @@ end
543
549
 
544
550
  def make_node(node_name, assigns)
545
551
  assigns.each do |key, value|
546
- if key != :position_source && value.is_a?(GraphQL::Language::Token)
547
- assigns[key] = value.to_s
552
+ if key != :position_source && value.is_a?(Array) && value[0].is_a?(Symbol)
553
+ assigns[key] = value[3]
548
554
  end
549
555
  end
550
556
 
@@ -131,38 +131,47 @@ module GraphQL
131
131
  "$#{variable_identifier.name}".dup
132
132
  end
133
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
- (schema.directives.empty?)
134
+ def print_schema_definition(schema, extension: false)
135
+ has_conventional_names = (schema.query.nil? || schema.query == 'Query') &&
136
+ (schema.mutation.nil? || schema.mutation == 'Mutation') &&
137
+ (schema.subscription.nil? || schema.subscription == 'Subscription')
138
+
139
+ if has_conventional_names && schema.directives.empty?
139
140
  return
140
141
  end
141
142
 
142
- out = "schema".dup
143
+ out = extension ? "extend schema".dup : "schema".dup
143
144
  if schema.directives.any?
144
145
  schema.directives.each do |dir|
145
146
  out << "\n "
146
147
  out << print_node(dir)
147
148
  end
148
- out << "\n{"
149
- else
150
- out << " {\n"
149
+ if !has_conventional_names
150
+ out << "\n"
151
+ end
151
152
  end
152
- out << " query: #{schema.query}\n" if schema.query
153
- out << " mutation: #{schema.mutation}\n" if schema.mutation
154
- out << " subscription: #{schema.subscription}\n" if schema.subscription
155
- out << "}"
153
+
154
+ if !has_conventional_names
155
+ if schema.directives.empty?
156
+ out << " "
157
+ end
158
+ out << "{\n"
159
+ out << " query: #{schema.query}\n" if schema.query
160
+ out << " mutation: #{schema.mutation}\n" if schema.mutation
161
+ out << " subscription: #{schema.subscription}\n" if schema.subscription
162
+ out << "}"
163
+ end
164
+ out
156
165
  end
157
166
 
158
- def print_scalar_type_definition(scalar_type)
159
- out = print_description(scalar_type)
167
+ def print_scalar_type_definition(scalar_type, extension: false)
168
+ out = extension ? "extend ".dup : print_description(scalar_type)
160
169
  out << "scalar #{scalar_type.name}"
161
170
  out << print_directives(scalar_type.directives)
162
171
  end
163
172
 
164
- def print_object_type_definition(object_type)
165
- out = print_description(object_type)
173
+ def print_object_type_definition(object_type, extension: false)
174
+ out = extension ? "extend ".dup : print_description(object_type)
166
175
  out << "type #{object_type.name}"
167
176
  out << print_implements(object_type) unless object_type.interfaces.empty?
168
177
  out << print_directives(object_type.directives)
@@ -201,23 +210,23 @@ module GraphQL
201
210
  out << print_directives(field.directives)
202
211
  end
203
212
 
204
- def print_interface_type_definition(interface_type)
205
- out = print_description(interface_type)
213
+ def print_interface_type_definition(interface_type, extension: false)
214
+ out = extension ? "extend ".dup : print_description(interface_type)
206
215
  out << "interface #{interface_type.name}"
207
216
  out << print_implements(interface_type) if interface_type.interfaces.any?
208
217
  out << print_directives(interface_type.directives)
209
218
  out << print_field_definitions(interface_type.fields)
210
219
  end
211
220
 
212
- def print_union_type_definition(union_type)
213
- out = print_description(union_type)
221
+ def print_union_type_definition(union_type, extension: false)
222
+ out = extension ? "extend ".dup : print_description(union_type)
214
223
  out << "union #{union_type.name}"
215
224
  out << print_directives(union_type.directives)
216
225
  out << " = " + union_type.types.map(&:name).join(" | ")
217
226
  end
218
227
 
219
- def print_enum_type_definition(enum_type)
220
- out = print_description(enum_type)
228
+ def print_enum_type_definition(enum_type, extension: false)
229
+ out = extension ? "extend ".dup : print_description(enum_type)
221
230
  out << "enum #{enum_type.name}#{print_directives(enum_type.directives)} {\n"
222
231
  enum_type.values.each.with_index do |value, i|
223
232
  out << print_description(value, indent: ' ', first_in_block: i == 0)
@@ -232,8 +241,8 @@ module GraphQL
232
241
  out << "\n"
233
242
  end
234
243
 
235
- def print_input_object_type_definition(input_object_type)
236
- out = print_description(input_object_type)
244
+ def print_input_object_type_definition(input_object_type, extension: false)
245
+ out = extension ? "extend ".dup : print_description(input_object_type)
237
246
  out << "input #{input_object_type.name}"
238
247
  out << print_directives(input_object_type.directives)
239
248
  if !input_object_type.fields.empty?
@@ -338,24 +347,38 @@ module GraphQL
338
347
  print_variable_identifier(node)
339
348
  when Nodes::SchemaDefinition
340
349
  print_schema_definition(node)
350
+ when Nodes::SchemaExtension
351
+ print_schema_definition(node, extension: true)
341
352
  when Nodes::ScalarTypeDefinition
342
353
  print_scalar_type_definition(node)
354
+ when Nodes::ScalarTypeExtension
355
+ print_scalar_type_definition(node, extension: true)
343
356
  when Nodes::ObjectTypeDefinition
344
357
  print_object_type_definition(node)
358
+ when Nodes::ObjectTypeExtension
359
+ print_object_type_definition(node, extension: true)
345
360
  when Nodes::InputValueDefinition
346
361
  print_input_value_definition(node)
347
362
  when Nodes::FieldDefinition
348
363
  print_field_definition(node)
349
364
  when Nodes::InterfaceTypeDefinition
350
365
  print_interface_type_definition(node)
366
+ when Nodes::InterfaceTypeExtension
367
+ print_interface_type_definition(node, extension: true)
351
368
  when Nodes::UnionTypeDefinition
352
369
  print_union_type_definition(node)
370
+ when Nodes::UnionTypeExtension
371
+ print_union_type_definition(node, extension: true)
353
372
  when Nodes::EnumTypeDefinition
354
373
  print_enum_type_definition(node)
374
+ when Nodes::EnumTypeExtension
375
+ print_enum_type_definition(node, extension: true)
355
376
  when Nodes::EnumValueDefinition
356
377
  print_enum_value_definition(node)
357
378
  when Nodes::InputObjectTypeDefinition
358
379
  print_input_object_type_definition(node)
380
+ when Nodes::InputObjectTypeExtension
381
+ print_input_object_type_definition(node, extension: true)
359
382
  when Nodes::DirectiveDefinition
360
383
  print_directive_definition(node)
361
384
  when FalseClass, Float, Integer, NilClass, String, TrueClass, Symbol