Skip to content

Commit 7782f96

Browse files
committed
Add support for extend type to parser
1 parent 7e3711d commit 7782f96

File tree

3 files changed

+117
-1
lines changed

3 files changed

+117
-1
lines changed

lib/graphql/compatibility/schema_parser_specification.rb

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,109 @@ def test_it_parses_scalar_extensions
263263
assert_equal 'somethingElse', scalar_extension.directives.last.name
264264
end
265265

266+
def test_it_parses_object_type_extensions_with_field_definitions
267+
document = parse('
268+
extend type User {
269+
login: String!
270+
}
271+
')
272+
273+
object_type_extension = document.definitions.first
274+
assert_equal GraphQL::Language::Nodes::ObjectTypeExtension, object_type_extension.class
275+
assert_equal 'User', object_type_extension.name
276+
assert_equal [2, 15], object_type_extension.position
277+
278+
assert_equal 1, object_type_extension.fields.length
279+
assert_equal GraphQL::Language::Nodes::FieldDefinition, object_type_extension.fields.first.class
280+
end
281+
282+
def test_it_parses_object_type_extensions_with_field_definitions_and_directives
283+
document = parse('
284+
extend type User @deprecated {
285+
login: String!
286+
}
287+
')
288+
289+
object_type_extension = document.definitions.first
290+
assert_equal GraphQL::Language::Nodes::ObjectTypeExtension, object_type_extension.class
291+
assert_equal 'User', object_type_extension.name
292+
assert_equal [2, 15], object_type_extension.position
293+
294+
assert_equal 1, object_type_extension.fields.length
295+
assert_equal GraphQL::Language::Nodes::FieldDefinition, object_type_extension.fields.first.class
296+
297+
assert_equal 1, object_type_extension.directives.length
298+
assert_equal GraphQL::Language::Nodes::Directive, object_type_extension.directives.first.class
299+
end
300+
301+
def test_it_parses_object_type_extensions_with_field_definitions_and_implements
302+
document = parse('
303+
extend type User implements Node {
304+
login: String!
305+
}
306+
')
307+
308+
object_type_extension = document.definitions.first
309+
assert_equal GraphQL::Language::Nodes::ObjectTypeExtension, object_type_extension.class
310+
assert_equal 'User', object_type_extension.name
311+
assert_equal [2, 15], object_type_extension.position
312+
313+
assert_equal 1, object_type_extension.fields.length
314+
assert_equal GraphQL::Language::Nodes::FieldDefinition, object_type_extension.fields.first.class
315+
316+
assert_equal 1, object_type_extension.interfaces.length
317+
assert_equal GraphQL::Language::Nodes::TypeName, object_type_extension.interfaces.first.class
318+
end
319+
320+
def test_it_parses_object_type_extensions_with_only_directives
321+
document = parse('
322+
extend type User @deprecated
323+
')
324+
325+
object_type_extension = document.definitions.first
326+
assert_equal GraphQL::Language::Nodes::ObjectTypeExtension, object_type_extension.class
327+
assert_equal 'User', object_type_extension.name
328+
assert_equal [2, 15], object_type_extension.position
329+
330+
assert_equal 1, object_type_extension.directives.length
331+
assert_equal GraphQL::Language::Nodes::Directive, object_type_extension.directives.first.class
332+
assert_equal 'deprecated', object_type_extension.directives.first.name
333+
end
334+
335+
def test_it_parses_object_type_extensions_with_implements_and_directives
336+
document = parse('
337+
extend type User implements Node @deprecated
338+
')
339+
340+
object_type_extension = document.definitions.first
341+
assert_equal GraphQL::Language::Nodes::ObjectTypeExtension, object_type_extension.class
342+
assert_equal 'User', object_type_extension.name
343+
assert_equal [2, 15], object_type_extension.position
344+
345+
assert_equal 1, object_type_extension.directives.length
346+
assert_equal GraphQL::Language::Nodes::Directive, object_type_extension.directives.first.class
347+
assert_equal 'deprecated', object_type_extension.directives.first.name
348+
349+
assert_equal 1, object_type_extension.interfaces.length
350+
assert_equal GraphQL::Language::Nodes::TypeName, object_type_extension.interfaces.first.class
351+
assert_equal 'Node', object_type_extension.interfaces.first.name
352+
end
353+
354+
def test_it_parses_object_type_extensions_with_only_implements
355+
document = parse('
356+
extend type User implements Node
357+
')
358+
359+
object_type_extension = document.definitions.first
360+
assert_equal GraphQL::Language::Nodes::ObjectTypeExtension, object_type_extension.class
361+
assert_equal 'User', object_type_extension.name
362+
assert_equal [2, 15], object_type_extension.position
363+
364+
assert_equal 1, object_type_extension.interfaces.length
365+
assert_equal GraphQL::Language::Nodes::TypeName, object_type_extension.interfaces.first.class
366+
assert_equal 'Node', object_type_extension.interfaces.first.name
367+
end
368+
266369
def test_it_parses_whole_definition_with_descriptions
267370
document = parse(SCHEMA_DEFINITION_STRING)
268371

lib/graphql/language/nodes.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@ def children
446446
end
447447
end
448448

449+
class ObjectTypeExtension < ObjectTypeDefinition; end;
450+
449451
class InputValueDefinition < AbstractNode
450452
attr_accessor :name, :type, :default_value, :directives,:description
451453
alias :children :directives

lib/graphql/language/parser.y

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,9 +307,17 @@ rule
307307

308308
type_extension:
309309
scalar_type_extension
310+
| object_type_extension
310311

311312
scalar_type_extension: EXTEND SCALAR name directives_list { return make_node(:ScalarTypeExtension, name: val[2], directives: val[3], position_source: val[0]) }
312313

314+
object_type_extension:
315+
/* TODO - This first one shouldn't be necessary but parser is getting confused */
316+
EXTEND TYPE name implements LCURLY field_definition_list RCURLY { return make_node(:ObjectTypeExtension, name: val[2], interfaces: val[3], directives: [], fields: val[5], position_source: val[0]) }
317+
| EXTEND TYPE name implements_opt directives_list_opt LCURLY field_definition_list RCURLY { return make_node(:ObjectTypeExtension, name: val[2], interfaces: val[3], directives: val[4], fields: val[6], position_source: val[0]) }
318+
| EXTEND TYPE name implements_opt directives_list { return make_node(:ObjectTypeExtension, name: val[2], interfaces: val[3], directives: val[4], fields: [], position_source: val[0]) }
319+
| EXTEND TYPE name implements { return make_node(:ObjectTypeExtension, name: val[2], interfaces: val[3], directives: [], fields: [], position_source: val[0]) }
320+
313321
scalar_type_definition: SCALAR name directives_list_opt { return make_node(:ScalarTypeDefinition, name: val[1], directives: val[2], description: get_description(val[0]), position_source: val[0]) }
314322

315323
object_type_definition:
@@ -319,7 +327,10 @@ rule
319327

320328
implements_opt:
321329
/* none */ { return [] }
322-
| IMPLEMENTS AMP interfaces_list { return val[2] }
330+
| implements
331+
332+
implements:
333+
IMPLEMENTS AMP interfaces_list { return val[2] }
323334
| IMPLEMENTS interfaces_list { return val[1] }
324335
| IMPLEMENTS legacy_interfaces_list { return val[1] }
325336

0 commit comments

Comments
 (0)