graphql 0.19.3 → 0.19.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/max_query_complexity.rb +1 -1
  3. data/lib/graphql/analysis/max_query_depth.rb +1 -1
  4. data/lib/graphql/boolean_type.rb +2 -2
  5. data/lib/graphql/define/instance_definable.rb +2 -2
  6. data/lib/graphql/enum_type.rb +3 -3
  7. data/lib/graphql/field.rb +6 -6
  8. data/lib/graphql/float_type.rb +2 -2
  9. data/lib/graphql/id_type.rb +2 -2
  10. data/lib/graphql/input_object_type.rb +1 -1
  11. data/lib/graphql/int_type.rb +2 -2
  12. data/lib/graphql/internal_representation/rewrite.rb +12 -12
  13. data/lib/graphql/introspection/arguments_field.rb +1 -1
  14. data/lib/graphql/introspection/enum_value_type.rb +1 -1
  15. data/lib/graphql/introspection/enum_values_field.rb +1 -1
  16. data/lib/graphql/introspection/field_type.rb +1 -1
  17. data/lib/graphql/introspection/fields_field.rb +1 -1
  18. data/lib/graphql/introspection/input_fields_field.rb +1 -1
  19. data/lib/graphql/introspection/input_value_type.rb +2 -2
  20. data/lib/graphql/introspection/interfaces_field.rb +1 -1
  21. data/lib/graphql/introspection/of_type_field.rb +1 -1
  22. data/lib/graphql/introspection/possible_types_field.rb +1 -1
  23. data/lib/graphql/introspection/schema_field.rb +1 -1
  24. data/lib/graphql/introspection/schema_type.rb +5 -5
  25. data/lib/graphql/introspection/type_by_name_field.rb +1 -1
  26. data/lib/graphql/introspection/type_type.rb +6 -6
  27. data/lib/graphql/introspection/typename_field.rb +1 -1
  28. data/lib/graphql/language.rb +1 -0
  29. data/lib/graphql/language/comments.rb +44 -0
  30. data/lib/graphql/language/definition_slice.rb +1 -1
  31. data/lib/graphql/language/generation.rb +35 -12
  32. data/lib/graphql/language/lexer.rb +29 -10
  33. data/lib/graphql/language/lexer.rl +25 -6
  34. data/lib/graphql/language/nodes.rb +30 -23
  35. data/lib/graphql/language/parser.rb +33 -14
  36. data/lib/graphql/language/parser.y +33 -14
  37. data/lib/graphql/language/parser_tests.rb +86 -2
  38. data/lib/graphql/language/token.rb +3 -2
  39. data/lib/graphql/language/visitor.rb +3 -3
  40. data/lib/graphql/object_type.rb +1 -1
  41. data/lib/graphql/query/arguments.rb +23 -2
  42. data/lib/graphql/query/serial_execution/field_resolution.rb +31 -14
  43. data/lib/graphql/relay/base_connection.rb +1 -3
  44. data/lib/graphql/relay/connection_type.rb +1 -1
  45. data/lib/graphql/relay/mutation.rb +1 -1
  46. data/lib/graphql/relay/relation_connection.rb +7 -3
  47. data/lib/graphql/scalar_type.rb +1 -1
  48. data/lib/graphql/schema.rb +19 -8
  49. data/lib/graphql/schema/loader.rb +2 -2
  50. data/lib/graphql/schema/printer.rb +63 -8
  51. data/lib/graphql/schema/timeout_middleware.rb +11 -11
  52. data/lib/graphql/schema/validation.rb +12 -12
  53. data/lib/graphql/static_validation/arguments_validator.rb +1 -1
  54. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
  55. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
  56. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
  57. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -1
  58. data/lib/graphql/static_validation/rules/fields_will_merge.rb +3 -2
  59. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  60. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
  61. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +9 -4
  62. data/lib/graphql/static_validation/rules/fragments_are_named.rb +1 -1
  63. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
  64. data/lib/graphql/static_validation/rules/fragments_are_used.rb +3 -3
  65. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
  66. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +2 -2
  67. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
  68. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
  69. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
  70. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  71. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +6 -6
  72. data/lib/graphql/static_validation/type_stack.rb +2 -2
  73. data/lib/graphql/string_type.rb +2 -2
  74. data/lib/graphql/version.rb +1 -1
  75. data/readme.md +1 -1
  76. data/spec/graphql/analysis/analyze_query_spec.rb +3 -3
  77. data/spec/graphql/analysis/query_complexity_spec.rb +7 -7
  78. data/spec/graphql/introspection/directive_type_spec.rb +2 -2
  79. data/spec/graphql/introspection/introspection_query_spec.rb +26 -26
  80. data/spec/graphql/language/generation_spec.rb +137 -53
  81. data/spec/graphql/language/lexer_spec.rb +22 -0
  82. data/spec/graphql/language/visitor_spec.rb +6 -6
  83. data/spec/graphql/query/arguments_spec.rb +45 -1
  84. data/spec/graphql/query/context_spec.rb +4 -4
  85. data/spec/graphql/query/executor_spec.rb +1 -1
  86. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +1 -1
  87. data/spec/graphql/relay/mutation_spec.rb +2 -2
  88. data/spec/graphql/relay/node_spec.rb +2 -2
  89. data/spec/graphql/relay/relation_connection_spec.rb +16 -0
  90. data/spec/graphql/schema/loader_spec.rb +2 -2
  91. data/spec/graphql/schema/middleware_chain_spec.rb +6 -6
  92. data/spec/graphql/schema/printer_spec.rb +268 -18
  93. data/spec/graphql/schema/rescue_middleware_spec.rb +1 -1
  94. data/spec/graphql/schema/timeout_middleware_spec.rb +2 -2
  95. data/spec/graphql/schema_spec.rb +2 -2
  96. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +13 -0
  97. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -1
  98. data/spec/graphql/static_validation/type_stack_spec.rb +1 -1
  99. data/spec/support/dairy_app.rb +25 -25
  100. data/spec/support/dairy_data.rb +2 -0
  101. data/spec/support/star_wars_data.rb +2 -1
  102. data/spec/support/star_wars_schema.rb +18 -18
  103. metadata +19 -2
@@ -44,6 +44,25 @@ def next_token
44
44
  end
45
45
  end
46
46
 
47
+ def get_description(token)
48
+ comments = []
49
+
50
+ loop do
51
+ prev_token = token
52
+ token = token.prev_token
53
+
54
+ break if token.nil?
55
+ break if token.name != :COMMENT
56
+ break if prev_token.line != token.line + 1
57
+
58
+ comments.unshift(token.to_s.sub(/^#\s*/, ""))
59
+ end
60
+
61
+ return nil if comments.empty?
62
+
63
+ comments.join("\n")
64
+ end
65
+
47
66
  def on_error(parser_token_id, lexer_token, vstack)
48
67
  if lexer_token == "$"
49
68
  raise GraphQL::ParseError.new("Unexpected end of document", nil, nil, @query_string)
@@ -1046,21 +1065,21 @@ module_eval(<<'.,.,', 'parser.y', 103)
1046
1065
 
1047
1066
  module_eval(<<'.,.,', 'parser.y', 146)
1048
1067
  def _reduce_58(val, _values, result)
1049
- return [val[0].to_s]
1068
+ return [make_node(:TypeName, name: val[0])]
1050
1069
  result
1051
1070
  end
1052
1071
  .,.,
1053
1072
 
1054
1073
  module_eval(<<'.,.,', 'parser.y', 147)
1055
1074
  def _reduce_59(val, _values, result)
1056
- val[0] << val[1].to_s
1075
+ val[0] << make_node(:TypeName, name: val[1])
1057
1076
  result
1058
1077
  end
1059
1078
  .,.,
1060
1079
 
1061
1080
  module_eval(<<'.,.,', 'parser.y', 150)
1062
1081
  def _reduce_60(val, _values, result)
1063
- return make_node(:EnumValueDefinition, name: val[0], directives: val[1])
1082
+ return make_node(:EnumValueDefinition, name: val[0], directives: val[1], description: get_description(val[0]))
1064
1083
  result
1065
1084
  end
1066
1085
  .,.,
@@ -1371,14 +1390,14 @@ module_eval(<<'.,.,', 'parser.y', 262)
1371
1390
 
1372
1391
  module_eval(<<'.,.,', 'parser.y', 272)
1373
1392
  def _reduce_113(val, _values, result)
1374
- return make_node(:ScalarTypeDefinition, name: val[1], directives: val[2])
1393
+ return make_node(:ScalarTypeDefinition, name: val[1], directives: val[2], description: get_description(val[0]))
1375
1394
  result
1376
1395
  end
1377
1396
  .,.,
1378
1397
 
1379
1398
  module_eval(<<'.,.,', 'parser.y', 276)
1380
1399
  def _reduce_114(val, _values, result)
1381
- return make_node(:ObjectTypeDefinition, name: val[1], interfaces: val[2], directives: val[3], fields: val[5])
1400
+ return make_node(:ObjectTypeDefinition, name: val[1], interfaces: val[2], directives: val[3], fields: val[5], description: get_description(val[0]))
1382
1401
 
1383
1402
  result
1384
1403
  end
@@ -1400,7 +1419,7 @@ module_eval(<<'.,.,', 'parser.y', 281)
1400
1419
 
1401
1420
  module_eval(<<'.,.,', 'parser.y', 285)
1402
1421
  def _reduce_117(val, _values, result)
1403
- return make_node(:InputValueDefinition, name: val[0], type: val[2], default_value: val[3], directives: val[4])
1422
+ return make_node(:InputValueDefinition, name: val[0], type: val[2], default_value: val[3], directives: val[4], description: get_description(val[0]))
1404
1423
 
1405
1424
  result
1406
1425
  end
@@ -1436,7 +1455,7 @@ module_eval(<<'.,.,', 'parser.y', 294)
1436
1455
 
1437
1456
  module_eval(<<'.,.,', 'parser.y', 298)
1438
1457
  def _reduce_122(val, _values, result)
1439
- return make_node(:FieldDefinition, name: val[0], arguments: val[1], type: val[3], directives: val[4])
1458
+ return make_node(:FieldDefinition, name: val[0], arguments: val[1], type: val[3], directives: val[4], description: get_description(val[0]))
1440
1459
 
1441
1460
  result
1442
1461
  end
@@ -1458,7 +1477,7 @@ module_eval(<<'.,.,', 'parser.y', 303)
1458
1477
 
1459
1478
  module_eval(<<'.,.,', 'parser.y', 307)
1460
1479
  def _reduce_125(val, _values, result)
1461
- return make_node(:InterfaceTypeDefinition, name: val[1], directives: val[2], fields: val[4])
1480
+ return make_node(:InterfaceTypeDefinition, name: val[1], directives: val[2], fields: val[4], description: get_description(val[0]))
1462
1481
 
1463
1482
  result
1464
1483
  end
@@ -1466,21 +1485,21 @@ module_eval(<<'.,.,', 'parser.y', 307)
1466
1485
 
1467
1486
  module_eval(<<'.,.,', 'parser.y', 311)
1468
1487
  def _reduce_126(val, _values, result)
1469
- return [val[0].to_s]
1488
+ return [make_node(:TypeName, name: val[0])]
1470
1489
  result
1471
1490
  end
1472
1491
  .,.,
1473
1492
 
1474
1493
  module_eval(<<'.,.,', 'parser.y', 312)
1475
1494
  def _reduce_127(val, _values, result)
1476
- val[0] << val[2].to_s
1495
+ val[0] << make_node(:TypeName, name: val[2])
1477
1496
  result
1478
1497
  end
1479
1498
  .,.,
1480
1499
 
1481
1500
  module_eval(<<'.,.,', 'parser.y', 316)
1482
1501
  def _reduce_128(val, _values, result)
1483
- return make_node(:UnionTypeDefinition, name: val[1], directives: val[2], types: val[4])
1502
+ return make_node(:UnionTypeDefinition, name: val[1], directives: val[2], types: val[4], description: get_description(val[0]))
1484
1503
 
1485
1504
  result
1486
1505
  end
@@ -1488,7 +1507,7 @@ module_eval(<<'.,.,', 'parser.y', 316)
1488
1507
 
1489
1508
  module_eval(<<'.,.,', 'parser.y', 321)
1490
1509
  def _reduce_129(val, _values, result)
1491
- return make_node(:EnumTypeDefinition, name: val[1], directives: val[2], values: val[4])
1510
+ return make_node(:EnumTypeDefinition, name: val[1], directives: val[2], values: val[4], description: get_description(val[0]))
1492
1511
 
1493
1512
  result
1494
1513
  end
@@ -1496,7 +1515,7 @@ module_eval(<<'.,.,', 'parser.y', 321)
1496
1515
 
1497
1516
  module_eval(<<'.,.,', 'parser.y', 326)
1498
1517
  def _reduce_130(val, _values, result)
1499
- return make_node(:InputObjectTypeDefinition, name: val[1], directives: val[2], fields: val[4])
1518
+ return make_node(:InputObjectTypeDefinition, name: val[1], directives: val[2], fields: val[4], description: get_description(val[0]))
1500
1519
 
1501
1520
  result
1502
1521
  end
@@ -1504,7 +1523,7 @@ module_eval(<<'.,.,', 'parser.y', 326)
1504
1523
 
1505
1524
  module_eval(<<'.,.,', 'parser.y', 331)
1506
1525
  def _reduce_131(val, _values, result)
1507
- return make_node(:DirectiveDefinition, name: val[2], arguments: val[3], locations: val[5])
1526
+ return make_node(:DirectiveDefinition, name: val[2], arguments: val[3], locations: val[5], description: get_description(val[0]))
1508
1527
 
1509
1528
  result
1510
1529
  end
@@ -144,11 +144,11 @@ rule
144
144
  | schema_keyword
145
145
 
146
146
  name_list:
147
- name { return [val[0].to_s]}
148
- | name_list name { val[0] << val[1].to_s }
147
+ name { return [make_node(:TypeName, name: val[0])] }
148
+ | name_list name { val[0] << make_node(:TypeName, name: val[1]) }
149
149
 
150
150
  enum_value_definition:
151
- enum_name directives_list_opt { return make_node(:EnumValueDefinition, name: val[0], directives: val[1]) }
151
+ enum_name directives_list_opt { return make_node(:EnumValueDefinition, name: val[0], directives: val[1], description: get_description(val[0])) }
152
152
 
153
153
  enum_value_definitions:
154
154
  enum_value_definition { return [val[0]] }
@@ -270,11 +270,11 @@ rule
270
270
  | enum_type_definition
271
271
  | input_object_type_definition
272
272
 
273
- scalar_type_definition: SCALAR name directives_list_opt { return make_node(:ScalarTypeDefinition, name: val[1], directives: val[2]) }
273
+ scalar_type_definition: SCALAR name directives_list_opt { return make_node(:ScalarTypeDefinition, name: val[1], directives: val[2], description: get_description(val[0])) }
274
274
 
275
275
  object_type_definition:
276
276
  TYPE name implements_opt directives_list_opt LCURLY field_definition_list RCURLY {
277
- return make_node(:ObjectTypeDefinition, name: val[1], interfaces: val[2], directives: val[3], fields: val[5])
277
+ return make_node(:ObjectTypeDefinition, name: val[1], interfaces: val[2], directives: val[3], fields: val[5], description: get_description(val[0]))
278
278
  }
279
279
 
280
280
  implements_opt:
@@ -283,7 +283,7 @@ rule
283
283
 
284
284
  input_value_definition:
285
285
  name COLON type default_value_opt directives_list_opt {
286
- return make_node(:InputValueDefinition, name: val[0], type: val[2], default_value: val[3], directives: val[4])
286
+ return make_node(:InputValueDefinition, name: val[0], type: val[2], default_value: val[3], directives: val[4], description: get_description(val[0]))
287
287
  }
288
288
 
289
289
  input_value_definition_list:
@@ -296,7 +296,7 @@ rule
296
296
 
297
297
  field_definition:
298
298
  name arguments_definitions_opt COLON type directives_list_opt {
299
- return make_node(:FieldDefinition, name: val[0], arguments: val[1], type: val[3], directives: val[4])
299
+ return make_node(:FieldDefinition, name: val[0], arguments: val[1], type: val[3], directives: val[4], description: get_description(val[0]))
300
300
  }
301
301
 
302
302
  field_definition_list:
@@ -305,31 +305,31 @@ rule
305
305
 
306
306
  interface_type_definition:
307
307
  INTERFACE name directives_list_opt LCURLY field_definition_list RCURLY {
308
- return make_node(:InterfaceTypeDefinition, name: val[1], directives: val[2], fields: val[4])
308
+ return make_node(:InterfaceTypeDefinition, name: val[1], directives: val[2], fields: val[4], description: get_description(val[0]))
309
309
  }
310
310
 
311
311
  union_members:
312
- name { return [val[0].to_s]}
313
- | union_members PIPE name { val[0] << val[2].to_s }
312
+ name { return [make_node(:TypeName, name: val[0])]}
313
+ | union_members PIPE name { val[0] << make_node(:TypeName, name: val[2]) }
314
314
 
315
315
  union_type_definition:
316
316
  UNION name directives_list_opt EQUALS union_members {
317
- return make_node(:UnionTypeDefinition, name: val[1], directives: val[2], types: val[4])
317
+ return make_node(:UnionTypeDefinition, name: val[1], directives: val[2], types: val[4], description: get_description(val[0]))
318
318
  }
319
319
 
320
320
  enum_type_definition:
321
321
  ENUM name directives_list_opt LCURLY enum_value_definitions RCURLY {
322
- return make_node(:EnumTypeDefinition, name: val[1], directives: val[2], values: val[4])
322
+ return make_node(:EnumTypeDefinition, name: val[1], directives: val[2], values: val[4], description: get_description(val[0]))
323
323
  }
324
324
 
325
325
  input_object_type_definition:
326
326
  INPUT name directives_list_opt LCURLY input_value_definition_list RCURLY {
327
- return make_node(:InputObjectTypeDefinition, name: val[1], directives: val[2], fields: val[4])
327
+ return make_node(:InputObjectTypeDefinition, name: val[1], directives: val[2], fields: val[4], description: get_description(val[0]))
328
328
  }
329
329
 
330
330
  directive_definition:
331
331
  DIRECTIVE DIR_SIGN name arguments_definitions_opt ON directive_locations {
332
- return make_node(:DirectiveDefinition, name: val[2], arguments: val[3], locations: val[5])
332
+ return make_node(:DirectiveDefinition, name: val[2], arguments: val[3], locations: val[5], description: get_description(val[0]))
333
333
  }
334
334
 
335
335
  directive_locations:
@@ -372,6 +372,25 @@ def next_token
372
372
  end
373
373
  end
374
374
 
375
+ def get_description(token)
376
+ comments = []
377
+
378
+ loop do
379
+ prev_token = token
380
+ token = token.prev_token
381
+
382
+ break if token.nil?
383
+ break if token.name != :COMMENT
384
+ break if prev_token.line != token.line + 1
385
+
386
+ comments.unshift(token.to_s.sub(/^#\s*/, ""))
387
+ end
388
+
389
+ return nil if comments.empty?
390
+
391
+ comments.join("\n")
392
+ end
393
+
375
394
  def on_error(parser_token_id, lexer_token, vstack)
376
395
  if lexer_token == "$"
377
396
  raise GraphQL::ParseError.new("Unexpected end of document", nil, nil, @query_string)
@@ -275,6 +275,90 @@ module GraphQL
275
275
  end
276
276
  end
277
277
 
278
+ describe "schema with comments" do
279
+ let(:query_string) {%|
280
+ # Schema at beginning of file
281
+
282
+ schema {
283
+ query: Hello
284
+ }
285
+
286
+ # Comment between two definitions are omitted
287
+
288
+ # This is a directive
289
+ directive @foo(
290
+ # It has an argument
291
+ arg: Int
292
+ ) on FIELD
293
+
294
+ # Multiline comment
295
+ #
296
+ # With an enum
297
+ enum Color {
298
+ RED
299
+
300
+ # Not a creative color
301
+ GREEN
302
+ BLUE
303
+ }
304
+
305
+ #Comment without preceding space
306
+ type Hello {
307
+ # And a field to boot
308
+ str: String
309
+ }
310
+
311
+ # Comment for input object types
312
+ input Car {
313
+ # Color of the car
314
+ color: String!
315
+ }
316
+
317
+ # Comment for interface definitions
318
+ interface Vehicle {
319
+ # Amount of wheels
320
+ wheels: Int!
321
+ }
322
+
323
+ # Comment at the end of schema
324
+ |}
325
+
326
+ it "parses successfully" do
327
+ document = subject.parse(query_string)
328
+
329
+ assert_equal 6, document.definitions.size
330
+
331
+ schema_definition = document.definitions.shift
332
+ assert_equal GraphQL::Language::Nodes::SchemaDefinition, schema_definition.class
333
+
334
+ directive_definition = document.definitions.shift
335
+ assert_equal GraphQL::Language::Nodes::DirectiveDefinition, directive_definition.class
336
+ assert_equal 'This is a directive', directive_definition.description
337
+
338
+ enum_type_definition = document.definitions.shift
339
+ assert_equal GraphQL::Language::Nodes::EnumTypeDefinition, enum_type_definition.class
340
+ assert_equal "Multiline comment\n\nWith an enum", enum_type_definition.description
341
+
342
+ assert_nil enum_type_definition.values[0].description
343
+ assert_equal 'Not a creative color', enum_type_definition.values[1].description
344
+
345
+ object_type_definition = document.definitions.shift
346
+ assert_equal GraphQL::Language::Nodes::ObjectTypeDefinition, object_type_definition.class
347
+ assert_equal 'Comment without preceding space', object_type_definition.description
348
+ assert_equal 'And a field to boot', object_type_definition.fields[0].description
349
+
350
+ input_object_type_definition = document.definitions.shift
351
+ assert_equal GraphQL::Language::Nodes::InputObjectTypeDefinition, input_object_type_definition.class
352
+ assert_equal 'Comment for input object types', input_object_type_definition.description
353
+ assert_equal 'Color of the car', input_object_type_definition.fields[0].description
354
+
355
+ interface_type_definition = document.definitions.shift
356
+ assert_equal GraphQL::Language::Nodes::InterfaceTypeDefinition, interface_type_definition.class
357
+ assert_equal 'Comment for interface definitions', interface_type_definition.description
358
+ assert_equal 'Amount of wheels', interface_type_definition.fields[0].description
359
+ end
360
+ end
361
+
278
362
  describe "schema" do
279
363
  it "parses the test schema" do
280
364
  schema = DummySchema
@@ -319,7 +403,7 @@ module GraphQL
319
403
  type = document.definitions.first
320
404
  assert_equal GraphQL::Language::Nodes::ObjectTypeDefinition, type.class
321
405
  assert_equal 'Comment', type.name
322
- assert_equal ['Node'], type.interfaces
406
+ assert_equal ['Node'], type.interfaces.map(&:name)
323
407
  assert_equal ['id'], type.fields.map(&:name)
324
408
  assert_equal [], type.fields[0].arguments
325
409
  assert_equal 'ID', type.fields[0].type.of_type.name
@@ -335,7 +419,7 @@ module GraphQL
335
419
  type = document.definitions.first
336
420
  assert_equal GraphQL::Language::Nodes::ObjectTypeDefinition, type.class
337
421
  assert_equal 'Comment', type.name
338
- assert_equal ['Node'], type.interfaces
422
+ assert_equal ['Node'], type.interfaces.map(&:name)
339
423
  assert_equal ['id'], type.fields.map(&:name)
340
424
  assert_equal [], type.fields[0].arguments
341
425
  assert_equal 'ID', type.fields[0].type.of_type.name
@@ -4,13 +4,14 @@ module GraphQL
4
4
  # Contains type, value and position data.
5
5
  class Token
6
6
  # @return [Symbol] The kind of token this is
7
- attr_reader :name
7
+ attr_reader :name, :prev_token, :line
8
8
 
9
- def initialize(value:, name:, line:, col:)
9
+ def initialize(value:, name:, line:, col:, prev_token:)
10
10
  @name = name
11
11
  @value = value
12
12
  @line = line
13
13
  @col = col
14
+ @prev_token = prev_token
14
15
  end
15
16
 
16
17
  def to_s; @value; end
@@ -6,9 +6,9 @@ module GraphQL
6
6
  # total_field_count = 0
7
7
  # visitor = GraphQL::Language::Visitor.new(document)
8
8
  # # Whenever you find a field, increment the field count:
9
- # visitor[GraphQL::Language::Nodes::Field] << -> (node) { total_field_count += 1 }
9
+ # visitor[GraphQL::Language::Nodes::Field] << ->(node) { total_field_count += 1 }
10
10
  # # When we finish, print the field count:
11
- # visitor[GraphQL::Language::Nodes::Document].leave << -> (node) { p total_field_count }
11
+ # visitor[GraphQL::Language::Nodes::Document].leave << ->(node) { p total_field_count }
12
12
  # visitor.visit
13
13
  # # => 6
14
14
  #
@@ -34,7 +34,7 @@ module GraphQL
34
34
  # @return [NodeVisitor]
35
35
  #
36
36
  # @example Run a hook whenever you enter a new Field
37
- # visitor[GraphQL::Language::Nodes::Field] << -> (node, parent) { p "Here's a field" }
37
+ # visitor[GraphQL::Language::Nodes::Field] << ->(node, parent) { p "Here's a field" }
38
38
  def [](node_class)
39
39
  @visitors[node_class] ||= NodeVisitor.new
40
40
  end
@@ -12,7 +12,7 @@ module GraphQL
12
12
  # field :cast, CastType
13
13
  # field :starring, types[PersonType] do
14
14
  # argument :limit, types.Int
15
- # resolve -> (object, args, ctx) {
15
+ # resolve ->(object, args, ctx) {
16
16
  # stars = object.cast.stars
17
17
  # args[:limit] && stars = stars.limit(args[:limit])
18
18
  # stars
@@ -11,7 +11,8 @@ module GraphQL
11
11
  @argument_values = values.inject({}) do |memo, (inner_key, inner_value)|
12
12
  string_key = inner_key.to_s
13
13
  arg_defn = argument_definitions[string_key]
14
- memo[string_key] = wrap_value(inner_value, arg_defn.type)
14
+ arg_value = wrap_value(inner_value, arg_defn.type)
15
+ memo[string_key] = ArgumentValue.new(string_key, arg_value, arg_defn)
15
16
  memo
16
17
  end
17
18
  end
@@ -19,7 +20,7 @@ module GraphQL
19
20
  # @param key [String, Symbol] name or index of value to access
20
21
  # @return [Object] the argument at that key
21
22
  def [](key)
22
- @argument_values[key.to_s]
23
+ @argument_values.fetch(key.to_s, NULL_ARGUMENT_VALUE).value
23
24
  end
24
25
 
25
26
  # @param key [String, Symbol] name of value to access
@@ -36,8 +37,28 @@ module GraphQL
36
37
 
37
38
  def_delegators :string_key_values, :keys, :values, :each
38
39
 
40
+ # Access each key, value and type for the arguments in this set.
41
+ # @yield [argument_value] The {ArgumentValue} for each argument
42
+ # @yieldparam argument_value [ArgumentValue]
43
+ def each_value
44
+ @argument_values.each_value do |argument_value|
45
+ yield(argument_value)
46
+ end
47
+ end
48
+
39
49
  private
40
50
 
51
+ class ArgumentValue
52
+ attr_reader :key, :value, :definition
53
+ def initialize(key, value, definition)
54
+ @key = key
55
+ @value = value
56
+ @definition = definition
57
+ end
58
+ end
59
+
60
+ NULL_ARGUMENT_VALUE = ArgumentValue.new(nil, nil, nil)
61
+
41
62
  def wrap_value(value, arg_defn_type)
42
63
  case value
43
64
  when Array