From 7ddec53e622334c7a8dbe5ada720b7b6277bc4a0 Mon Sep 17 00:00:00 2001 From: Leonard Chin Date: Mon, 26 Jul 2021 23:09:53 +0900 Subject: [PATCH 1/7] Don't pass empty hash as kwargs Since Ruby 3, hash passed as kwargs will be removed if empty. This can result in a value of `{}` being converted to `nil`, ultimately leading to a validation error. --- lib/graphql/define/instance_definable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/graphql/define/instance_definable.rb b/lib/graphql/define/instance_definable.rb index 1c3d1cc696..04dcc41a03 100644 --- a/lib/graphql/define/instance_definable.rb +++ b/lib/graphql/define/instance_definable.rb @@ -76,7 +76,7 @@ def ensure_defined # Apply definition from `define(...)` kwargs defn.define_keywords.each do |keyword, value| # Don't splat string hashes, which blows up on Rubies before 2.7 - if value.is_a?(Hash) && value.each_key.all? { |k| k.is_a?(Symbol) } + if value.is_a?(Hash) && !value.empty? && value.each_key.all? { |k| k.is_a?(Symbol) } defn_proxy.public_send(keyword, **value) else defn_proxy.public_send(keyword, value) From 3e2a5f7b4377c67d755f2c131c8e24aa4483579e Mon Sep 17 00:00:00 2001 From: Sergio Date: Wed, 1 Sep 2021 10:07:34 -0400 Subject: [PATCH 2/7] Fix issue #3604 --- lib/graphql/schema/argument.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/graphql/schema/argument.rb b/lib/graphql/schema/argument.rb index fce25df7f3..181f4e1ad5 100644 --- a/lib/graphql/schema/argument.rb +++ b/lib/graphql/schema/argument.rb @@ -151,7 +151,7 @@ def authorized_as_type?(obj, value, ctx, as_type:) input_obj_arg = input_obj_arg.type_class # TODO: this skips input objects whose values were alread replaced with application objects. # See: https://github.com/rmosolgo/graphql-ruby/issues/2633 - if value.respond_to?(:key?) && value.key?(input_obj_arg.keyword) && !input_obj_arg.authorized?(obj, value[input_obj_arg.keyword], ctx) + if value.is_a?(InputObject) && value.key?(input_obj_arg.keyword) && !input_obj_arg.authorized?(obj, value[input_obj_arg.keyword], ctx) return false end end From cef4b5b80dd2d642a0a6616e445e2b4da520e28e Mon Sep 17 00:00:00 2001 From: Robert Mosolgo Date: Mon, 8 Feb 2021 15:48:13 -0500 Subject: [PATCH 3/7] Sketch out a general-use dataloader API --- lib/graphql/dataloader.rb | 15 +++++++++++++++ spec/graphql/dataloader_spec.rb | 31 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/lib/graphql/dataloader.rb b/lib/graphql/dataloader.rb index b46a4d830d..14728bbde7 100644 --- a/lib/graphql/dataloader.rb +++ b/lib/graphql/dataloader.rb @@ -27,6 +27,21 @@ def self.use(schema) schema.dataloader_class = self end + # Call the block with a Dataloader instance, + # then run all enqueued jobs and return the result of the block. + # + # TODO here: + # - reconsider `#append_job`'s name if that's going to be a public API + def self.with_dataloading(&block) + dataloader = self.new + result = nil + dataloader.append_job { + result = block.call(dataloader) + } + dataloader.run + result + end + def initialize @source_cache = Hash.new { |h, source_class| h[source_class] = Hash.new { |h2, batch_parameters| source = if RUBY_VERSION < "3" diff --git a/spec/graphql/dataloader_spec.rb b/spec/graphql/dataloader_spec.rb index 48f8190f26..3e5e1252fb 100644 --- a/spec/graphql/dataloader_spec.rb +++ b/spec/graphql/dataloader_spec.rb @@ -820,4 +820,35 @@ class Schema < GraphQL::Schema assert_equal expected_result, result.to_h end end + + it "supports general usage" do + a = b = c = nil + + res = GraphQL::Dataloader.with_dataloading { |dataloader| + dataloader.append_job { + a = dataloader.with(FiberSchema::DataObject).load("1") + } + + dataloader.append_job { + b = dataloader.with(FiberSchema::DataObject).load("1") + } + + dataloader.append_job { + r1 = dataloader.with(FiberSchema::DataObject).request("2") + r2 = dataloader.with(FiberSchema::DataObject).request("3") + c = [ + r1.load, + r2.load + ] + } + + :finished + } + + assert_equal :finished, res + assert_equal [[:mget, ["1", "2", "3"]]], database_log + assert_equal "Wheat", a[:name] + assert_equal "Wheat", b[:name] + assert_equal ["Corn", "Butter"], c.map { |d| d[:name] } + end end From 99f129f324eb4109ed4c2ca9ed73c44329df3101 Mon Sep 17 00:00:00 2001 From: Robert Mosolgo Date: Wed, 1 Sep 2021 10:54:56 -0400 Subject: [PATCH 4/7] Add docs for .with_dataloading --- guides/dataloader/testing.md | 73 ++++++++++++++++++++++++++++++++++++ lib/graphql/dataloader.rb | 3 -- 2 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 guides/dataloader/testing.md diff --git a/guides/dataloader/testing.md b/guides/dataloader/testing.md new file mode 100644 index 0000000000..95ddb15094 --- /dev/null +++ b/guides/dataloader/testing.md @@ -0,0 +1,73 @@ +--- +layout: guide +search: true +section: Dataloader +title: Testing +desc: Tips for testing Dataloader implementation +index: 4 +experimental: true +--- + +There are a few techniques for testing your {{ "GraphQL::Dataloader" | api_doc }} setup. + +## Integration Tests + +One important feature of `Dataloader` is how it manages database access while GraphQL runs queries. You can test that by listening for database queries while running queries, for example, with ActiveRecord: + + +```ruby +def test_active_record_queries_are_batched_and_cached + # set up a listener function + database_queries = 0 + callback = lambda {|_name, _started, _finished, _unique_id, _payload| database_queries += 1 } + + query_str = <<-GRAPHQL + { + a1: author(id: 1) { name } + a2: author(id: 2) { name } + b1: book(id: 1) { author { name } } + b2: book(id: 2) { author { name } } + } + GRAPHQL + + # Run the query with the listener + ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do + MySchema.execute(query_str) + end + + # One query for authors, one query for books + assert_equal 2, database_queries +end +``` + +You could also make specific assertions on the queries that are run (see the [`sql.active_record` docs](https://edgeguides.rubyonrails.org/active_support_instrumentation.html#active-record)). For other frameworks and databases, check your ORM or library for instrumentation options. + +## Testing Dataloader Sources + +You can also test `Dataloader` behavior outside of GraphQL using {{ "GraphQL::Dataloader.with_dataloading" | api_doc }}. For example: + +```ruby +def test_it_fetches_objects_by_id + user_1, user_2, user_3 = 3.times { User.create! } + + database_queries = 0 + callback = lambda {|_name, _started, _finished, _unique_id, _payload| database_queries += 1 } + + ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do + GraphQL::Dataloader.with_dataloading do |dataloader| + req1 = dataloader.with(Sources::ActiveRecord).request(user_1.id) + req2 = dataloader.with(Sources::ActiveRecord).request(user_3.id) + req3 = dataloader.with(Sources::ActiveRecord).request(user_2.id) + req4 = dataloader.with(Sources::ActiveRecord).request(-1) + + # Validate source's matching up of records + expect(req1.load).to eq(user_1) + expect(req2.load).to eq(user_3) + expect(req3.load).to eq(user_2) + expect(req4.load).to be_nil + end + end + + assert_equal 1, database_queries, "All users were looked up at once" +end +``` diff --git a/lib/graphql/dataloader.rb b/lib/graphql/dataloader.rb index 14728bbde7..cab900c04d 100644 --- a/lib/graphql/dataloader.rb +++ b/lib/graphql/dataloader.rb @@ -29,9 +29,6 @@ def self.use(schema) # Call the block with a Dataloader instance, # then run all enqueued jobs and return the result of the block. - # - # TODO here: - # - reconsider `#append_job`'s name if that's going to be a public API def self.with_dataloading(&block) dataloader = self.new result = nil From 02ce3d80826f84ca0bdd52b7901f58f91c49034e Mon Sep 17 00:00:00 2001 From: Robert Mosolgo Date: Tue, 7 Sep 2021 09:48:35 -0400 Subject: [PATCH 5/7] remove the push action from CI --- .github/workflows/ci.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e048c57c9e..b7732660d8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,6 +1,5 @@ name: CI Suite on: - - push - pull_request jobs: From eaa1c7d5dc27a3c9c7659e0ef5f528a7b4322941 Mon Sep 17 00:00:00 2001 From: Robert Mosolgo Date: Wed, 8 Sep 2021 14:16:44 -0400 Subject: [PATCH 6/7] Support interfaces implementing other interfaces --- Rakefile | 2 +- .../document_from_schema_definition.rb | 1 + lib/graphql/language/nodes.rb | 2 + lib/graphql/language/parser.rb | 876 +++++++++--------- lib/graphql/language/parser.y | 9 +- lib/graphql/language/printer.rb | 7 +- lib/graphql/schema/addition.rb | 12 +- lib/graphql/schema/build_from_definition.rb | 5 + lib/graphql/schema/interface.rb | 23 +- lib/graphql/schema/member.rb | 1 + .../schema/member/accepts_definition.rb | 9 +- lib/graphql/schema/member/has_fields.rb | 2 +- lib/graphql/schema/member/has_interfaces.rb | 88 ++ lib/graphql/schema/object.rb | 70 +- .../schema/build_from_definition_spec.rb | 24 + spec/graphql/schema/interface_spec.rb | 63 ++ 16 files changed, 661 insertions(+), 533 deletions(-) create mode 100644 lib/graphql/schema/member/has_interfaces.rb diff --git a/Rakefile b/Rakefile index b4ce2045d1..ca7151b2a2 100644 --- a/Rakefile +++ b/Rakefile @@ -62,7 +62,7 @@ ERR end assert_dependency_version("Ragel", "7.0.0.9", "ragel -v") - assert_dependency_version("Racc", "1.4.16", %|ruby -e "require 'racc'; puts Racc::VERSION"|) + assert_dependency_version("Racc", "1.5.2", %|ruby -e "require 'racc'; puts Racc::VERSION"|) `rm -f lib/graphql/language/parser.rb lib/graphql/language/lexer.rb ` `racc lib/graphql/language/parser.y -o lib/graphql/language/parser.rb` diff --git a/lib/graphql/language/document_from_schema_definition.rb b/lib/graphql/language/document_from_schema_definition.rb index 553e15792a..0fe5d3af95 100644 --- a/lib/graphql/language/document_from_schema_definition.rb +++ b/lib/graphql/language/document_from_schema_definition.rb @@ -87,6 +87,7 @@ def build_union_type_node(union_type) def build_interface_type_node(interface_type) GraphQL::Language::Nodes::InterfaceTypeDefinition.new( name: interface_type.graphql_name, + interfaces: warden.interfaces(interface_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) }, description: interface_type.description, fields: build_field_nodes(warden.fields(interface_type)), directives: directives(interface_type), diff --git a/lib/graphql/language/nodes.rb b/lib/graphql/language/nodes.rb index 26028fc13c..a4acc0e17b 100644 --- a/lib/graphql/language/nodes.rb +++ b/lib/graphql/language/nodes.rb @@ -618,6 +618,7 @@ class InterfaceTypeDefinition < AbstractNode attr_reader :description scalar_methods :name children_methods({ + interfaces: GraphQL::Language::Nodes::TypeName, directives: GraphQL::Language::Nodes::Directive, fields: GraphQL::Language::Nodes::FieldDefinition, }) @@ -627,6 +628,7 @@ class InterfaceTypeDefinition < AbstractNode class InterfaceTypeExtension < AbstractNode scalar_methods :name children_methods({ + interfaces: GraphQL::Language::Nodes::TypeName, directives: GraphQL::Language::Nodes::Directive, fields: GraphQL::Language::Nodes::FieldDefinition, }) diff --git a/lib/graphql/language/parser.rb b/lib/graphql/language/parser.rb index 805b4fb3e8..a666353ec0 100644 --- a/lib/graphql/language/parser.rb +++ b/lib/graphql/language/parser.rb @@ -1,6 +1,6 @@ # # DO NOT MODIFY!!!! -# This file is automatically generated by Racc 1.4.16 +# This file is automatically generated by Racc 1.5.2 # from Racc grammar file "". # @@ -12,7 +12,7 @@ module GraphQL module Language class Parser < Racc::Parser -module_eval(<<'...end parser.y/module_eval...', 'parser.y', 437) +module_eval(<<'...end parser.y/module_eval...', 'parser.y', 438) EMPTY_ARRAY = [].freeze @@ -124,64 +124,64 @@ def make_node(node_name, assigns) ##### State transition tables begin ### racc_action_table = [ - -2, 279, 11, -99, 12, 13, 14, 280, 11, -99, - 12, 13, 14, 178, -99, -99, 19, -99, 94, -165, - 194, 93, 19, 12, 13, 14, 15, 196, 71, 35, - 35, 35, 15, 71, 71, 28, -99, 35, 12, 13, - 14, 28, 71, 263, -151, 71, 71, 35, 71, 43, + -2, -166, 11, -99, 12, 13, 14, 281, 11, -99, + 12, 13, 14, 178, -99, -99, 19, -99, 94, 264, + 38, 93, 19, 12, 13, 14, 15, 71, 71, 35, + 35, 35, 15, 87, 71, 28, -99, 35, 12, 13, + 14, 28, 89, -166, -152, 71, 71, 35, 71, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 60, 12, 13, 14, 71, -165, -165, - 181, 35, -165, 160, 120, 43, 44, 45, 46, 47, + 54, 55, 56, 60, 12, 13, 14, 71, -166, 273, + 181, 35, 274, 160, 120, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 90, - 12, 13, 14, 299, 66, 295, 35, 35, -165, 221, + 12, 13, 14, -166, 66, -166, 35, 35, 279, 98, 35, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 223, 12, 13, 14, 273, - 66, 35, 272, 35, 131, 268, 35, 43, 44, 45, + 52, 53, 54, 55, 56, 224, 12, 13, 14, 280, + 66, 35, 296, 35, 71, 101, 35, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 219, 71, 12, 13, 14, 66, 35, 217, 278, - 35, 218, 285, 35, 200, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 198, 199, 207, 208, 204, 205, - 206, 216, 302, 131, 12, 13, 14, 35, 300, 71, - 277, 71, 218, 230, 87, 200, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 198, 199, 207, 208, 204, - 205, 206, 216, 219, 233, 12, 13, 14, 35, 303, - 217, 71, 35, 218, 35, 244, 200, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 198, 199, 207, 208, - 204, 205, 206, 216, 302, 142, 12, 13, 14, 226, - 12, 13, 14, 306, 218, 35, 35, 200, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 198, 199, 207, - 208, 204, 205, 206, 216, 219, 35, 12, 13, 14, - 250, 307, 217, 131, 284, 218, 254, 71, 200, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 198, 199, - 207, 208, 204, 205, 206, 216, 219, 138, 12, 13, - 14, 71, 94, 217, 233, 131, 218, 269, 71, 200, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 198, - 199, 207, 208, 204, 205, 206, 216, 219, 71, 12, - 13, 14, 71, 120, 217, 71, 269, 218, 116, 71, - 200, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 198, 199, 207, 208, 204, 205, 206, 216, 12, 13, - 14, 80, 81, 38, 82, 83, 84, 85, 86, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 12, 13, 14, 284, 101, 66, 174, - 12, 13, 14, 71, 96, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 291, 12, - 13, 14, 71, 12, 13, 14, 290, 98, 194, 71, + 56, 12, 13, 14, 297, 71, 66, 35, 116, 301, + 35, 71, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 220, 120, 12, 13, + 14, 66, 35, 218, 302, 71, 219, 35, 71, 201, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 199, + 200, 208, 209, 205, 206, 207, 217, 220, 131, 12, + 13, 14, 35, 94, 218, 138, 71, 219, 255, 142, + 201, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 199, 200, 208, 209, 205, 206, 207, 217, 220, 142, + 12, 13, 14, 71, 71, 218, 71, 71, 219, 286, + 142, 201, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 199, 200, 208, 209, 205, 206, 207, 217, 305, + 142, 12, 13, 14, 174, 12, 13, 14, 71, 219, + 71, 71, 201, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 199, 200, 208, 209, 205, 206, 207, 217, + 220, 131, 12, 13, 14, 131, 94, 218, 168, 169, + 219, 71, 71, 201, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 199, 200, 208, 209, 205, 206, 207, + 217, 220, 176, 12, 13, 14, 71, 71, 218, 71, + -152, 219, 187, 188, 201, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 199, 200, 208, 209, 205, 206, + 207, 217, 305, 189, 12, 13, 14, 227, 12, 13, + 14, 71, 219, 71, 192, 201, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 199, 200, 208, 209, 205, + 206, 207, 217, 12, 13, 14, 73, 74, 75, 193, + 76, 77, 78, 79, 96, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 258, 12, + 13, 14, 71, 12, 13, 14, 194, 195, 197, 71, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 287, 12, 13, 14, 73, 74, - 75, 71, 76, 77, 78, 79, 43, 44, 45, 46, + 53, 54, 55, 56, 288, 12, 13, 14, 80, 81, + 222, 82, 83, 84, 85, 86, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 310, 12, 13, 14, 131, 94, 298, 168, 169, 89, - 71, 131, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 257, 12, 13, 14, - 71, 176, 71, 71, 71, 71, 71, 185, 43, 44, + 292, 12, 13, 14, 131, 131, 231, 234, 236, 35, + 35, 245, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 313, 12, 13, 14, + 246, 35, 35, 35, 251, 131, 234, 270, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 12, 13, 14, 186, 71, 187, 142, 188, - 129, 71, 190, 43, 44, 45, 46, 47, 48, 49, + 55, 56, 12, 13, 14, 270, 285, 291, 195, 71, + 300, 303, 306, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 12, 13, 14, - 191, 192, 193, nil, nil, nil, nil, nil, 43, 44, + 309, 310, 285, 71, 71, nil, nil, nil, nil, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 12, 13, 14, nil, nil, nil, nil, nil, - nil, nil, nil, nil, 44, 45, 46, 47, 48, 49, + nil, nil, nil, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 12, 13, 14, nil, nil, nil, nil, nil, nil, nil, nil, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, @@ -218,7 +218,7 @@ def make_node(node_name, assigns) 55, 56, 12, 13, 14, nil, nil, nil, nil, nil, nil, nil, nil, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 12, 13, 14, - nil, nil, nil, nil, nil, nil, nil, nil, 43, 44, + nil, nil, nil, nil, nil, 129, nil, nil, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 12, 13, 14, nil, nil, nil, nil, nil, 129, nil, nil, 43, 44, 45, 46, 47, 48, 49, @@ -271,110 +271,110 @@ def make_node(node_name, assigns) nil, nil, nil, nil, nil, 129, nil, nil, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 12, 13, 14, nil, nil, nil, nil, nil, - nil, nil, nil, 200, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 198, 199, -157, nil, nil, nil, -157, - nil, nil, nil, nil, nil, -157, nil, -157, -157 ] + nil, nil, nil, 201, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 199, 200, -158, nil, nil, nil, -158, + nil, nil, nil, nil, nil, -158, nil, -158, -158 ] racc_action_check = [ - 3, 248, 3, 143, 3, 3, 3, 249, 0, 145, - 0, 0, 0, 140, 102, 179, 3, 149, 65, 230, - 158, 65, 0, 138, 138, 138, 3, 162, 145, 248, - 249, 3, 0, 165, 143, 3, 147, 0, 142, 142, - 142, 0, 110, 227, 140, 102, 179, 230, 149, 142, + 3, 178, 3, 102, 3, 3, 3, 250, 0, 145, + 0, 0, 0, 140, 147, 149, 3, 179, 65, 228, + 1, 65, 0, 101, 101, 101, 3, 19, 145, 178, + 250, 3, 0, 38, 102, 3, 185, 0, 142, 142, + 142, 0, 40, 231, 140, 147, 149, 228, 179, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 11, 11, 11, 11, 147, 190, 185, - 142, 227, 178, 118, 118, 11, 11, 11, 11, 11, + 142, 142, 142, 11, 11, 11, 11, 185, 236, 241, + 142, 231, 242, 118, 118, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 59, - 59, 59, 59, 276, 11, 266, 190, 185, 244, 170, - 178, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 172, 172, 172, 172, 241, - 59, 276, 240, 266, 171, 235, 244, 172, 172, 172, + 59, 59, 59, 245, 11, 246, 236, 241, 248, 67, + 242, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 172, 172, 172, 172, 249, + 59, 245, 267, 246, 69, 72, 248, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 255, 109, 255, 255, 255, 172, 241, 255, 247, - 240, 255, 255, 235, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 306, 173, 306, 306, 306, 247, 281, 108, - 245, 107, 306, 180, 38, 306, 306, 306, 306, 306, - 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, - 306, 306, 306, 290, 182, 290, 290, 290, 245, 289, - 290, 106, 187, 290, 188, 189, 290, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 284, 105, 284, 284, 284, 177, - 177, 177, 177, 293, 284, 192, 193, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 218, 194, 218, 218, 218, - 195, 294, 218, 197, 308, 218, 218, 104, 218, 218, - 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, - 218, 218, 218, 218, 218, 218, 303, 103, 303, 303, - 303, 312, 100, 303, 231, 97, 303, 236, 95, 303, - 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, - 303, 303, 303, 303, 303, 303, 303, 168, 92, 168, - 168, 168, 19, 89, 168, 88, 246, 168, 86, 73, + 172, 131, 131, 131, 269, 73, 172, 249, 86, 277, + 267, 88, 131, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 168, 89, 168, 168, + 168, 131, 269, 168, 278, 92, 168, 277, 95, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 131, 131, - 131, 37, 37, 1, 37, 37, 37, 37, 37, 131, - 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, - 131, 131, 131, 66, 66, 66, 251, 72, 131, 135, - 135, 135, 135, 69, 66, 66, 66, 66, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 66, 261, 261, - 261, 261, 66, 101, 101, 101, 260, 67, 265, 313, - 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, - 261, 261, 261, 261, 258, 258, 258, 258, 28, 28, - 28, 270, 28, 28, 28, 28, 258, 258, 258, 258, - 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, - 302, 302, 302, 302, 121, 122, 275, 125, 127, 40, - 130, 117, 302, 302, 302, 302, 302, 302, 302, 302, - 302, 302, 302, 302, 302, 302, 219, 219, 219, 219, - 133, 137, 139, 115, 141, 113, 114, 144, 219, 219, + 168, 168, 168, 168, 168, 168, 168, 219, 97, 219, + 219, 219, 278, 100, 219, 103, 104, 219, 219, 105, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, - 219, 219, 98, 98, 98, 146, 112, 148, 111, 150, - 98, 152, 154, 98, 98, 98, 98, 98, 98, 98, - 98, 98, 98, 98, 98, 98, 98, 10, 10, 10, - 155, 156, 157, nil, nil, nil, nil, nil, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 15, 15, 15, nil, nil, nil, nil, nil, - nil, nil, nil, nil, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 71, 71, 71, - nil, nil, nil, nil, nil, nil, nil, nil, 71, 71, - 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, - 71, 71, 74, 74, 74, nil, nil, nil, nil, nil, - nil, nil, nil, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, - nil, nil, nil, nil, nil, nil, nil, nil, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 76, 76, 76, nil, nil, nil, nil, nil, - nil, nil, nil, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, - nil, nil, nil, nil, nil, nil, nil, nil, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 78, 78, 78, nil, nil, nil, nil, nil, - nil, nil, nil, 78, 78, 78, 78, 78, 78, 78, - 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, - nil, nil, nil, nil, nil, nil, nil, nil, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 80, 80, 80, nil, nil, nil, nil, nil, - nil, nil, nil, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, - nil, nil, nil, nil, nil, nil, nil, nil, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 82, 82, 82, nil, nil, nil, nil, nil, - nil, nil, nil, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, - nil, nil, nil, nil, nil, nil, nil, nil, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 84, 84, 84, nil, nil, nil, nil, nil, - nil, nil, nil, 84, 84, 84, 84, 84, 84, 84, - 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, - nil, nil, nil, nil, nil, nil, nil, nil, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 93, 93, 93, nil, nil, nil, nil, nil, - nil, nil, nil, 93, 93, 93, 93, 93, 93, 93, - 93, 93, 93, 93, 93, 93, 93, 94, 94, 94, - nil, nil, nil, nil, nil, nil, nil, nil, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 96, 96, 96, nil, nil, nil, nil, nil, - 96, nil, nil, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 116, 116, 116, + 219, 219, 219, 219, 219, 219, 219, 219, 256, 106, + 256, 256, 256, 107, 108, 256, 109, 110, 256, 256, + 111, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 256, 256, 256, 256, 256, 256, 256, 256, 256, 285, + 112, 285, 285, 285, 135, 135, 135, 135, 113, 285, + 114, 115, 285, 285, 285, 285, 285, 285, 285, 285, + 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, + 291, 117, 291, 291, 291, 121, 122, 291, 125, 127, + 291, 130, 133, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 306, 137, 306, 306, 306, 139, 141, 306, 143, + 144, 306, 146, 148, 306, 306, 306, 306, 306, 306, + 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, + 306, 306, 309, 150, 309, 309, 309, 177, 177, 177, + 177, 152, 309, 154, 155, 309, 309, 309, 309, 309, + 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, + 309, 309, 309, 66, 66, 66, 28, 28, 28, 156, + 28, 28, 28, 28, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 220, 220, + 220, 220, 66, 138, 138, 138, 157, 158, 162, 165, + 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 259, 259, 259, 259, 37, 37, + 170, 37, 37, 37, 37, 37, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 262, 262, 262, 262, 171, 173, 180, 182, 186, 188, + 189, 190, 262, 262, 262, 262, 262, 262, 262, 262, + 262, 262, 262, 262, 262, 262, 305, 305, 305, 305, + 191, 193, 194, 195, 196, 198, 232, 237, 305, 305, + 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, + 305, 305, 10, 10, 10, 247, 252, 261, 266, 271, + 276, 282, 290, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 15, 15, 15, + 294, 295, 311, 315, 316, nil, nil, nil, nil, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 71, 71, 71, nil, nil, nil, nil, nil, + nil, nil, nil, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 74, 74, 74, + nil, nil, nil, nil, nil, nil, nil, nil, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 75, 75, 75, nil, nil, nil, nil, nil, + nil, nil, nil, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 76, 76, 76, + nil, nil, nil, nil, nil, nil, nil, nil, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 77, 77, 77, nil, nil, nil, nil, nil, + nil, nil, nil, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 78, 78, 78, + nil, nil, nil, nil, nil, nil, nil, nil, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 79, 79, 79, nil, nil, nil, nil, nil, + nil, nil, nil, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 80, 80, 80, + nil, nil, nil, nil, nil, nil, nil, nil, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 81, 81, 81, nil, nil, nil, nil, nil, + nil, nil, nil, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 82, 82, 82, + nil, nil, nil, nil, nil, nil, nil, nil, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 83, 83, 83, nil, nil, nil, nil, nil, + nil, nil, nil, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 84, 84, 84, + nil, nil, nil, nil, nil, nil, nil, nil, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 85, 85, 85, nil, nil, nil, nil, nil, + nil, nil, nil, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 93, 93, 93, + nil, nil, nil, nil, nil, nil, nil, nil, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 94, 94, 94, nil, nil, nil, nil, nil, + nil, nil, nil, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 96, 96, 96, + nil, nil, nil, nil, nil, 96, nil, nil, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 98, 98, 98, nil, nil, nil, nil, nil, + 98, nil, nil, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 116, 116, 116, nil, nil, nil, nil, nil, nil, nil, nil, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 120, 120, 120, nil, nil, nil, nil, nil, @@ -392,218 +392,218 @@ def make_node(node_name, assigns) 181, 181, 181, 181, 181, 181, 181, 183, 183, 183, nil, nil, nil, nil, nil, nil, nil, nil, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, - 183, 183, 186, 186, 186, nil, nil, nil, nil, nil, - nil, nil, nil, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 191, 191, 191, - nil, nil, nil, nil, nil, nil, nil, nil, 191, 191, - 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, - 191, 191, 196, 196, 196, nil, nil, nil, nil, nil, - 196, nil, nil, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 217, 217, 217, - nil, nil, nil, nil, nil, nil, nil, nil, 217, 217, - 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, - 217, 217, 228, 228, 228, nil, nil, nil, nil, nil, - nil, nil, nil, 228, 228, 228, 228, 228, 228, 228, - 228, 228, 228, 228, 228, 228, 228, 233, 233, 233, - nil, nil, nil, nil, nil, nil, nil, nil, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, - 233, 233, 242, 242, 242, nil, nil, nil, nil, nil, - nil, nil, nil, 242, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 242, 250, 250, 250, - nil, nil, nil, nil, nil, nil, nil, nil, 250, 250, - 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, - 250, 250, 269, 269, 269, nil, nil, nil, nil, nil, - nil, nil, nil, 269, 269, 269, 269, 269, 269, 269, - 269, 269, 269, 269, 269, 269, 269, 298, 298, 298, - nil, nil, nil, nil, nil, 298, nil, nil, 298, 298, - 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, - 298, 298, 300, 300, 300, nil, nil, nil, nil, nil, - nil, nil, nil, 300, 300, 300, 300, 300, 300, 300, - 300, 300, 300, 300, 300, 300, 300, 307, 307, 307, - nil, nil, nil, nil, nil, 307, nil, nil, 307, 307, - 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, - 307, 307, 238, 238, 238, nil, nil, nil, nil, nil, - nil, nil, nil, 238, 238, 238, 238, 238, 238, 238, - 238, 238, 238, 238, 238, 184, nil, nil, nil, 184, + 183, 183, 187, 187, 187, nil, nil, nil, nil, nil, + nil, nil, nil, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 192, 192, 192, + nil, nil, nil, nil, nil, nil, nil, nil, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 197, 197, 197, nil, nil, nil, nil, nil, + 197, nil, nil, 197, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 218, 218, 218, + nil, nil, nil, nil, nil, nil, nil, nil, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 229, 229, 229, nil, nil, nil, nil, nil, + nil, nil, nil, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 234, 234, 234, + nil, nil, nil, nil, nil, nil, nil, nil, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 243, 243, 243, nil, nil, nil, nil, nil, + nil, nil, nil, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 251, 251, 251, + nil, nil, nil, nil, nil, nil, nil, nil, 251, 251, + 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, + 251, 251, 270, 270, 270, nil, nil, nil, nil, nil, + nil, nil, nil, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 300, 300, 300, + nil, nil, nil, nil, nil, 300, nil, nil, 300, 300, + 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, + 300, 300, 303, 303, 303, nil, nil, nil, nil, nil, + nil, nil, nil, 303, 303, 303, 303, 303, 303, 303, + 303, 303, 303, 303, 303, 303, 303, 310, 310, 310, + nil, nil, nil, nil, nil, 310, nil, nil, 310, 310, + 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, + 310, 310, 239, 239, 239, nil, nil, nil, nil, nil, + nil, nil, nil, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 239, 239, 239, 184, nil, nil, nil, 184, nil, nil, nil, nil, nil, 184, nil, 184, 184 ] racc_action_pointer = [ - 6, 363, nil, 0, nil, nil, nil, nil, nil, nil, - 533, 60, nil, nil, nil, 558, nil, nil, nil, 299, - nil, nil, nil, nil, nil, nil, nil, nil, 422, nil, - nil, nil, nil, nil, nil, nil, nil, 344, 184, nil, - 462, nil, nil, nil, nil, nil, nil, nil, nil, nil, + 6, 20, nil, 0, nil, nil, nil, nil, nil, nil, + 508, 60, nil, nil, nil, 533, nil, nil, nil, -6, + nil, nil, nil, nil, nil, nil, nil, nil, 370, nil, + nil, nil, nil, nil, nil, nil, nil, 421, 33, nil, + 35, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 86, - nil, nil, nil, nil, nil, 11, 379, 402, nil, 360, - nil, 583, 385, 306, 608, 633, 658, 683, 708, 733, - 758, 783, 808, 833, 858, 883, 305, nil, 302, 324, - nil, nil, 295, 908, 933, 275, 958, 303, 508, nil, - 295, 409, 12, 295, 244, 216, 178, 148, 146, 109, - 9, 499, 483, 462, 463, 460, 983, 469, 65, nil, - 1008, 462, 458, 1033, nil, 457, nil, 457, nil, 1058, - 437, 354, nil, 457, nil, 386, nil, 481, 19, 459, - 11, 461, 34, 1, 495, -5, 501, 34, 515, 15, - 517, nil, 488, nil, 520, 526, 539, 540, 13, nil, - nil, nil, 17, nil, nil, 0, nil, nil, 325, nil, - 86, 122, 112, 171, nil, nil, 1083, 236, 69, 13, - 181, 1108, 168, 1133, 1470, 66, 1158, 181, 183, 213, - 65, 1183, 214, 215, 235, 255, 1208, 271, nil, nil, + nil, nil, nil, nil, nil, 11, 379, 84, nil, 91, + nil, 558, 123, 112, 583, 608, 633, 658, 683, 708, + 733, 758, 783, 808, 833, 858, 115, nil, 118, 158, + nil, nil, 142, 883, 908, 145, 933, 196, 958, nil, + 196, 19, 1, 203, 173, 190, 210, 200, 201, 203, + 204, 221, 241, 235, 237, 238, 983, 289, 65, nil, + 1008, 293, 289, 1033, nil, 288, nil, 288, nil, 1058, + 268, 137, nil, 269, nil, 261, nil, 312, 409, 293, + 11, 294, 34, 296, 297, -5, 318, 12, 331, 13, + 351, nil, 328, nil, 330, 350, 387, 414, 410, nil, + nil, nil, 408, nil, nil, 386, nil, nil, 164, nil, + 427, 462, 112, 463, nil, nil, 1083, 354, -2, 15, + 464, 1108, 431, 1133, 1470, 34, 466, 1158, 438, 439, + 469, 488, 1183, 460, 461, 462, 479, 1208, 493, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, 1233, 263, 483, - nil, nil, nil, nil, nil, nil, nil, 40, 1258, nil, - 16, 268, nil, 1283, nil, 122, 270, nil, 1458, nil, - 119, 116, 1308, nil, 95, 177, 299, 146, -2, -1, - 1333, 372, nil, nil, nil, 139, nil, nil, 431, nil, - 406, 405, nil, nil, nil, 411, 92, nil, nil, 1358, - 408, nil, nil, nil, nil, 456, 90, nil, nil, nil, - nil, 141, nil, nil, 232, nil, nil, nil, nil, 199, - 201, nil, nil, 233, 261, nil, nil, nil, 1383, nil, - 1408, nil, 457, 294, nil, nil, 170, 1433, 260, nil, - nil, nil, 268, 386, nil, nil ] + nil, nil, nil, nil, nil, nil, nil, nil, 1233, 195, + 405, nil, nil, nil, nil, nil, nil, nil, 16, 1258, + nil, 40, 460, nil, 1283, nil, 65, 460, nil, 1458, + nil, 66, 69, 1308, nil, 90, 92, 478, 95, 116, + -1, 1333, 502, nil, nil, nil, 226, nil, nil, 431, + nil, 507, 457, nil, nil, nil, 511, 119, nil, 141, + 1358, 486, nil, nil, nil, nil, 510, 146, 171, nil, + nil, nil, 484, nil, nil, 257, nil, nil, nil, nil, + 512, 288, nil, nil, 530, 531, nil, nil, nil, nil, + 1383, nil, nil, 1408, nil, 483, 319, nil, nil, 350, + 1433, 528, nil, nil, nil, 510, 511, nil, nil ] racc_action_default = [ - -146, -177, -1, -146, -3, -5, -6, -7, -8, -9, - -16, -177, -13, -14, -15, -107, -109, -110, -111, -98, - -116, -117, -118, -119, -120, -121, -122, -123, -177, -126, - -127, -128, -129, -130, -131, -145, -147, -177, -177, -4, + -147, -178, -1, -147, -3, -5, -6, -7, -8, -9, + -16, -178, -13, -14, -15, -107, -109, -110, -111, -98, + -116, -117, -118, -119, -120, -121, -122, -123, -178, -126, + -127, -128, -129, -130, -131, -146, -148, -178, -178, -4, -18, -17, -39, -40, -41, -42, -43, -44, -45, -46, - -47, -48, -49, -50, -51, -52, -53, -54, -55, -177, - -12, -32, -34, -35, -36, -64, -98, -177, -108, -99, - -100, -177, -177, -98, -177, -177, -177, -177, -177, -177, - -177, -177, -177, -177, -177, -177, -177, 316, -98, -177, - -11, -33, -98, -177, -177, -98, -177, -177, -177, -101, - -64, -177, -125, -177, -177, -150, -98, -98, -98, -98, - -98, -150, -98, -98, -98, -98, -177, -177, -177, -20, - -177, -30, -64, -177, -66, -177, -103, -23, -25, -177, - -98, -177, -105, -98, -102, -177, -113, -177, -177, -132, - -136, -98, -177, -138, -177, -140, -177, -142, -177, -144, - -177, -148, -98, -151, -177, -177, -177, -177, -162, -10, - -19, -21, -177, -31, -37, -98, -65, -67, -177, -24, - -177, -177, -177, -177, -112, -114, -177, -177, -146, -135, - -177, -177, -153, -154, -155, -146, -177, -146, -146, -177, - -146, -177, -146, -146, -146, -177, -177, -30, -56, -57, - -58, -59, -60, -68, -69, -70, -71, -72, -73, -74, - -75, -76, -77, -78, -79, -80, -81, -177, -177, -177, - -97, -26, -104, -29, -106, -115, -124, -146, -177, -166, - -146, -152, -155, -177, -158, -146, -139, -169, -177, -62, - -146, -146, -177, -160, -146, -146, -171, -146, -146, -146, - -177, -27, -38, -82, -83, -177, -85, -87, -177, -89, - -177, -177, -94, -133, -167, -162, -146, -156, -137, -177, - -98, -63, -141, -143, -161, -177, -146, -168, -172, -173, - -163, -174, -175, -22, -177, -84, -86, -88, -90, -177, - -177, -93, -95, -177, -177, -134, -170, -61, -177, -149, - -177, -28, -177, -177, -78, -91, -177, -177, -27, -176, - -92, -96, -98, -98, -164, -159 ] + -47, -48, -49, -50, -51, -52, -53, -54, -55, -178, + -12, -32, -34, -35, -36, -64, -98, -178, -108, -99, + -100, -178, -178, -98, -178, -178, -178, -178, -178, -178, + -178, -178, -178, -178, -178, -178, -178, 319, -98, -178, + -11, -33, -98, -178, -178, -98, -178, -178, -178, -101, + -64, -178, -125, -178, -178, -151, -151, -98, -98, -98, + -98, -151, -151, -98, -98, -98, -178, -178, -178, -20, + -178, -30, -64, -178, -66, -178, -103, -23, -25, -178, + -98, -178, -105, -98, -102, -178, -113, -178, -178, -132, + -136, -98, -178, -98, -139, -141, -178, -143, -178, -145, + -178, -149, -98, -152, -98, -178, -178, -178, -163, -10, + -19, -21, -178, -31, -37, -98, -65, -67, -178, -24, + -178, -178, -178, -178, -112, -114, -178, -178, -147, -135, + -178, -178, -154, -155, -156, -138, -178, -178, -147, -147, + -178, -178, -178, -147, -147, -147, -178, -178, -30, -56, + -57, -58, -59, -60, -68, -69, -70, -71, -72, -73, + -74, -75, -76, -77, -78, -79, -80, -81, -178, -178, + -178, -97, -26, -104, -29, -106, -115, -124, -147, -178, + -167, -147, -153, -156, -178, -159, -147, -140, -170, -178, + -62, -147, -147, -178, -161, -147, -147, -172, -147, -147, + -147, -178, -27, -38, -82, -83, -178, -85, -87, -178, + -89, -178, -178, -94, -133, -168, -163, -147, -157, -147, + -178, -98, -63, -142, -144, -162, -178, -147, -147, -173, + -174, -164, -175, -176, -22, -178, -84, -86, -88, -90, + -178, -178, -93, -95, -178, -178, -134, -137, -171, -61, + -178, -150, -169, -178, -28, -178, -178, -78, -91, -178, + -178, -27, -177, -92, -96, -98, -98, -165, -160 ] racc_goto_table = [ - 10, 72, 59, 10, 91, 132, 130, 195, 133, 68, - 164, 203, 283, 270, 227, 202, 102, 175, 92, 37, - 135, 235, 37, 274, 264, 159, 245, 124, 259, 99, - 274, 274, 264, 182, 271, 119, 118, 2, 241, 170, - 140, 271, 264, 248, 249, 88, 153, 139, 97, 143, - 145, 147, 149, 134, 281, 103, 167, 177, 1, 175, - 95, 256, 99, 264, 161, 202, 266, 288, 4, 313, - 117, 39, 231, 264, 121, 165, 141, 126, 236, 222, - 276, 224, 152, 246, 179, 202, 252, 40, 144, 146, - 148, 150, 151, 183, 154, 155, 156, 157, 286, 99, - 3, 137, 202, 99, 258, 99, 251, 99, 240, 99, - 301, 292, 171, 247, 294, 173, 304, 91, 255, 123, - 67, nil, 172, 180, nil, nil, 41, 65, nil, nil, - nil, 202, 311, nil, 189, 137, nil, 202, 137, 99, - nil, nil, nil, nil, nil, nil, nil, 197, nil, nil, - 202, nil, nil, 202, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, nil, 201, nil, - nil, nil, nil, nil, nil, 65, nil, 137, nil, nil, - nil, nil, nil, nil, nil, nil, nil, 100, nil, nil, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, nil, nil, nil, nil, 238, 242, 308, 122, - 125, 238, 242, 242, nil, nil, nil, 312, 201, nil, - nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, 158, nil, nil, nil, 162, nil, 201, 125, - nil, nil, nil, nil, nil, nil, nil, 65, nil, nil, - nil, nil, 297, nil, nil, 201, nil, nil, 184, 238, - 242, nil, nil, nil, nil, nil, 238, 242, 242, nil, + 10, 72, 130, 10, 133, 203, 59, 91, 196, 37, + 204, 164, 37, 228, 284, 175, 102, 68, 92, 260, + 182, 304, 1, 135, 275, 119, 132, 307, 2, 99, + 272, 275, 275, 242, 124, 170, 241, 272, 249, 250, + 4, 248, 3, 39, 237, 314, 159, 139, 97, 247, + 145, 147, 149, 134, 161, 103, 203, 175, 289, 232, + 177, 257, 99, 167, 140, 144, 267, 40, 95, 88, + 117, 269, 118, 316, 121, 165, 203, 126, 271, 123, + 277, 278, 256, 259, 179, 293, 185, 67, 253, 146, + 148, 150, 151, 203, 183, 155, 156, 157, 287, 99, + 223, 137, 225, 252, 282, 99, nil, 99, nil, 99, + 265, nil, 171, nil, nil, 173, 295, 41, 65, nil, + 91, nil, 203, 180, nil, 186, 172, nil, 203, nil, + nil, nil, nil, nil, 190, 137, 191, nil, 137, 99, + nil, nil, nil, 203, nil, 99, 203, 198, nil, 265, + nil, 265, nil, nil, nil, 141, 143, nil, nil, 265, + 265, 152, 154, nil, nil, nil, 65, nil, 202, nil, + nil, nil, nil, nil, nil, nil, nil, 137, 100, nil, + nil, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, nil, nil, nil, nil, 239, 243, nil, + 122, 125, 239, 243, 243, nil, 311, nil, nil, nil, + nil, nil, nil, nil, nil, nil, 315, nil, nil, 202, + nil, nil, nil, 158, nil, nil, nil, 162, nil, nil, + 125, nil, nil, nil, nil, nil, nil, nil, 65, 202, + nil, nil, nil, nil, nil, nil, nil, nil, nil, 184, + 239, 243, nil, 299, nil, nil, 202, 239, 243, 243, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, 201, nil, nil, nil, 65, nil, - 201, nil, 225, nil, 314, 315, nil, 232, nil, 234, - nil, nil, 237, 201, nil, nil, 201, 237, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, 65, + nil, nil, nil, 226, nil, 202, nil, nil, 233, nil, + 235, 202, nil, nil, 238, nil, nil, 317, 318, 238, + nil, nil, nil, nil, nil, nil, 202, nil, nil, 202, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, 254, nil, 261, nil, nil, + nil, nil, nil, nil, nil, nil, 266, nil, nil, nil, + nil, 268, nil, nil, nil, nil, nil, nil, nil, nil, + 276, nil, nil, nil, nil, nil, nil, nil, 283, nil, + nil, nil, nil, nil, nil, nil, 290, nil, nil, 294, + nil, nil, nil, nil, nil, nil, nil, 298, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, 253, nil, 260, nil, nil, nil, nil, - nil, nil, nil, nil, 265, nil, nil, nil, nil, 267, - nil, nil, nil, nil, nil, nil, nil, nil, 275, nil, - nil, nil, nil, nil, nil, nil, 282, nil, nil, nil, - nil, nil, nil, nil, 289, nil, nil, 293, nil, nil, - nil, nil, nil, nil, nil, 296, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, 309, nil, 293 ] + 312, nil, 294 ] racc_goto_check = [ - 10, 13, 15, 10, 24, 14, 19, 80, 19, 29, - 23, 37, 20, 31, 72, 30, 49, 56, 28, 33, - 55, 72, 33, 79, 81, 14, 72, 36, 46, 50, - 79, 79, 81, 77, 32, 18, 17, 2, 75, 19, - 71, 32, 81, 75, 75, 12, 71, 49, 13, 49, - 49, 49, 49, 28, 82, 13, 36, 55, 1, 56, - 29, 37, 50, 81, 18, 30, 72, 46, 4, 20, - 13, 4, 77, 81, 13, 28, 73, 13, 74, 14, - 72, 14, 73, 74, 49, 30, 23, 11, 13, 13, - 13, 13, 13, 78, 13, 13, 13, 13, 37, 50, - 3, 10, 30, 50, 45, 50, 19, 50, 34, 50, - 22, 48, 13, 34, 80, 13, 22, 24, 44, 35, - 51, nil, 15, 13, nil, nil, 16, 16, nil, nil, - nil, 30, 22, nil, 13, 10, nil, 30, 10, 50, - nil, nil, nil, nil, nil, nil, nil, 13, nil, nil, - 30, nil, nil, 30, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, nil, 10, nil, - nil, nil, nil, nil, nil, 16, nil, 10, nil, nil, - nil, nil, nil, nil, nil, nil, nil, 16, nil, nil, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, nil, nil, nil, nil, 33, 33, 19, 16, - 16, 33, 33, 33, nil, nil, nil, 19, 10, nil, - nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, 16, nil, nil, nil, 16, nil, 10, 16, - nil, nil, nil, nil, nil, nil, nil, 16, nil, nil, - nil, nil, 13, nil, nil, 10, nil, nil, 16, 33, - 33, nil, nil, nil, nil, nil, 33, 33, 33, nil, + 10, 13, 19, 10, 19, 30, 15, 24, 80, 33, + 37, 23, 33, 72, 20, 56, 49, 29, 28, 46, + 77, 22, 1, 55, 79, 18, 14, 22, 2, 50, + 32, 79, 79, 75, 36, 19, 34, 32, 75, 75, + 4, 34, 3, 4, 74, 22, 14, 49, 13, 74, + 49, 49, 49, 28, 18, 13, 30, 56, 46, 77, + 55, 37, 50, 36, 71, 71, 72, 11, 29, 12, + 13, 72, 17, 20, 13, 28, 30, 13, 31, 35, + 72, 72, 44, 45, 49, 48, 49, 51, 23, 13, + 13, 13, 13, 30, 78, 13, 13, 13, 37, 50, + 14, 10, 14, 19, 82, 50, nil, 50, nil, 50, + 81, nil, 13, nil, nil, 13, 80, 16, 16, nil, + 24, nil, 30, 13, nil, 13, 15, nil, 30, nil, + nil, nil, nil, nil, 13, 10, 13, nil, 10, 50, + nil, nil, nil, 30, nil, 50, 30, 13, nil, 81, + nil, 81, nil, nil, nil, 73, 73, nil, nil, 81, + 81, 73, 73, nil, nil, nil, 16, nil, 10, nil, + nil, nil, nil, nil, nil, nil, nil, 10, 16, nil, + nil, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, nil, nil, nil, nil, 33, 33, nil, + 16, 16, 33, 33, 33, nil, 19, nil, nil, nil, + nil, nil, nil, nil, nil, nil, 19, nil, nil, 10, + nil, nil, nil, 16, nil, nil, nil, 16, nil, nil, + 16, nil, nil, nil, nil, nil, nil, nil, 16, 10, + nil, nil, nil, nil, nil, nil, nil, nil, nil, 16, + 33, 33, nil, 13, nil, nil, 10, 33, 33, 33, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, 10, nil, nil, nil, 16, nil, - 10, nil, 16, nil, 13, 13, nil, 16, nil, 16, - nil, nil, 16, 10, nil, nil, 10, 16, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, 16, + nil, nil, nil, 16, nil, 10, nil, nil, 16, nil, + 16, 10, nil, nil, 16, nil, nil, 13, 13, 16, + nil, nil, nil, nil, nil, nil, 10, nil, nil, 10, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, 16, nil, 16, nil, nil, nil, nil, - nil, nil, nil, nil, 16, nil, nil, nil, nil, 16, - nil, nil, nil, nil, nil, nil, nil, nil, 16, nil, + nil, nil, nil, nil, nil, 16, nil, 16, nil, nil, nil, nil, nil, nil, nil, nil, 16, nil, nil, nil, - nil, nil, nil, nil, 16, nil, nil, 16, nil, nil, - nil, nil, nil, nil, nil, 16, nil, nil, nil, nil, + nil, 16, nil, nil, nil, nil, nil, nil, nil, nil, + 16, nil, nil, nil, nil, nil, nil, nil, 16, nil, + nil, nil, nil, nil, nil, nil, 16, nil, nil, 16, + nil, nil, nil, nil, nil, nil, nil, 16, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, 16, nil, 16 ] + 16, nil, 16 ] racc_goto_pointer = [ - nil, 58, 37, 100, 68, nil, nil, nil, nil, nil, - 0, 77, 5, -18, -92, -9, 116, -53, -54, -90, - -239, nil, -174, -111, -55, nil, nil, nil, -47, -6, - -153, -225, -206, 19, -79, 25, -67, -157, nil, nil, - nil, nil, nil, nil, -100, -115, -191, nil, -150, -57, - -40, 105, nil, nil, nil, -81, -118, nil, nil, nil, + nil, 22, 28, 42, 40, nil, nil, nil, nil, nil, + 0, 57, 29, -18, -71, -5, 107, -17, -64, -94, + -238, nil, -264, -110, -52, nil, nil, nil, -47, 2, + -163, -161, -211, 9, -152, -15, -60, -158, nil, nil, + nil, nil, nil, nil, -137, -137, -201, nil, -177, -57, + -40, 72, nil, nil, nil, -78, -120, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, -65, -164, -29, -108, -150, nil, -109, -49, -218, - -151, -203, -196 ] + nil, -41, -165, 50, -143, -156, nil, -122, -48, -218, + -150, -118, -147 ] racc_goto_default = [ nil, nil, nil, nil, nil, 5, 6, 7, 8, 9, 57, nil, nil, nil, 163, nil, 128, nil, nil, nil, - nil, 127, 213, nil, 61, 62, 63, 64, nil, 42, - 58, 220, 239, 228, nil, nil, nil, 305, 209, 210, - 211, 212, 214, 215, nil, nil, nil, 261, 262, 69, + nil, 127, 214, nil, 61, 62, 63, 64, nil, 42, + 58, 221, 240, 229, nil, nil, nil, 308, 210, 211, + 212, 213, 215, 216, nil, nil, nil, 262, 263, 69, 70, nil, 16, 17, 18, nil, 136, 20, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, - 34, nil, nil, nil, nil, nil, 36, nil, nil, 243, - nil, 229, nil ] + 34, 153, nil, nil, nil, nil, 36, nil, nil, 244, + nil, 230, nil ] racc_reduce_table = [ 0, 0, :racc_error, @@ -743,50 +743,51 @@ def make_node(node_name, assigns) 8, 104, :_reduce_134, 5, 104, :_reduce_135, 4, 104, :_reduce_136, - 7, 105, :_reduce_137, - 4, 105, :_reduce_138, - 6, 106, :_reduce_139, - 4, 106, :_reduce_140, - 7, 107, :_reduce_141, - 4, 107, :_reduce_142, - 7, 108, :_reduce_143, - 4, 108, :_reduce_144, + 8, 105, :_reduce_137, + 5, 105, :_reduce_138, + 4, 105, :_reduce_139, + 6, 106, :_reduce_140, + 4, 106, :_reduce_141, + 7, 107, :_reduce_142, + 4, 107, :_reduce_143, + 7, 108, :_reduce_144, + 4, 108, :_reduce_145, 1, 114, :_reduce_none, 0, 71, :_reduce_none, 1, 71, :_reduce_none, - 4, 95, :_reduce_148, - 8, 96, :_reduce_149, - 0, 111, :_reduce_150, + 4, 95, :_reduce_149, + 8, 96, :_reduce_150, + 0, 111, :_reduce_151, 1, 111, :_reduce_none, - 3, 109, :_reduce_152, - 2, 109, :_reduce_153, + 3, 109, :_reduce_153, 2, 109, :_reduce_154, - 1, 115, :_reduce_155, - 3, 115, :_reduce_156, - 1, 116, :_reduce_157, - 2, 116, :_reduce_158, - 6, 117, :_reduce_159, - 1, 113, :_reduce_160, - 2, 113, :_reduce_161, - 0, 118, :_reduce_162, - 3, 118, :_reduce_163, - 6, 119, :_reduce_164, - 0, 110, :_reduce_165, - 1, 110, :_reduce_166, - 2, 110, :_reduce_167, - 7, 97, :_reduce_168, - 1, 112, :_reduce_169, - 3, 112, :_reduce_170, - 6, 98, :_reduce_171, - 7, 99, :_reduce_172, - 7, 100, :_reduce_173, - 7, 92, :_reduce_174, - 1, 120, :_reduce_175, - 3, 120, :_reduce_176 ] - -racc_reduce_n = 177 - -racc_shift_n = 316 + 2, 109, :_reduce_155, + 1, 115, :_reduce_156, + 3, 115, :_reduce_157, + 1, 116, :_reduce_158, + 2, 116, :_reduce_159, + 6, 117, :_reduce_160, + 1, 113, :_reduce_161, + 2, 113, :_reduce_162, + 0, 118, :_reduce_163, + 3, 118, :_reduce_164, + 6, 119, :_reduce_165, + 0, 110, :_reduce_166, + 1, 110, :_reduce_167, + 2, 110, :_reduce_168, + 8, 97, :_reduce_169, + 1, 112, :_reduce_170, + 3, 112, :_reduce_171, + 6, 98, :_reduce_172, + 7, 99, :_reduce_173, + 7, 100, :_reduce_174, + 7, 92, :_reduce_175, + 1, 120, :_reduce_176, + 3, 120, :_reduce_177 ] + +racc_reduce_n = 178 + +racc_shift_n = 319 racc_token_table = { false => 0, @@ -1690,101 +1691,101 @@ def _reduce_136(val, _values, result) module_eval(<<'.,.,', 'parser.y', 327) def _reduce_137(val, _values, result) - result = make_node(:InterfaceTypeExtension, name: val[2], directives: val[3], fields: val[5], position_source: val[0]) + result = make_node(:InterfaceTypeExtension, name: val[2], interfaces: val[3], directives: val[4], fields: val[6], position_source: val[0]) result end .,., module_eval(<<'.,.,', 'parser.y', 328) def _reduce_138(val, _values, result) - result = make_node(:InterfaceTypeExtension, name: val[2], directives: val[3], fields: [], position_source: val[0]) + result = make_node(:InterfaceTypeExtension, name: val[2], interfaces: val[3], directives: val[4], fields: [], position_source: val[0]) result end .,., -module_eval(<<'.,.,', 'parser.y', 331) +module_eval(<<'.,.,', 'parser.y', 329) def _reduce_139(val, _values, result) - result = make_node(:UnionTypeExtension, name: val[2], directives: val[3], types: val[5], position_source: val[0]) + result = make_node(:InterfaceTypeExtension, name: val[2], interfaces: val[3], directives: [], fields: [], position_source: val[0]) result end .,., module_eval(<<'.,.,', 'parser.y', 332) def _reduce_140(val, _values, result) - result = make_node(:UnionTypeExtension, name: val[2], directives: val[3], types: [], position_source: val[0]) + result = make_node(:UnionTypeExtension, name: val[2], directives: val[3], types: val[5], position_source: val[0]) result end .,., -module_eval(<<'.,.,', 'parser.y', 335) +module_eval(<<'.,.,', 'parser.y', 333) def _reduce_141(val, _values, result) - result = make_node(:EnumTypeExtension, name: val[2], directives: val[3], values: val[5], position_source: val[0]) + result = make_node(:UnionTypeExtension, name: val[2], directives: val[3], types: [], position_source: val[0]) result end .,., module_eval(<<'.,.,', 'parser.y', 336) def _reduce_142(val, _values, result) - result = make_node(:EnumTypeExtension, name: val[2], directives: val[3], values: [], position_source: val[0]) + result = make_node(:EnumTypeExtension, name: val[2], directives: val[3], values: val[5], position_source: val[0]) result end .,., -module_eval(<<'.,.,', 'parser.y', 339) +module_eval(<<'.,.,', 'parser.y', 337) def _reduce_143(val, _values, result) - result = make_node(:InputObjectTypeExtension, name: val[2], directives: val[3], fields: val[5], position_source: val[0]) + result = make_node(:EnumTypeExtension, name: val[2], directives: val[3], values: [], position_source: val[0]) result end .,., module_eval(<<'.,.,', 'parser.y', 340) def _reduce_144(val, _values, result) - result = make_node(:InputObjectTypeExtension, name: val[2], directives: val[3], fields: [], position_source: val[0]) + result = make_node(:InputObjectTypeExtension, name: val[2], directives: val[3], fields: val[5], position_source: val[0]) result end .,., -# reduce 145 omitted +module_eval(<<'.,.,', 'parser.y', 341) + def _reduce_145(val, _values, result) + result = make_node(:InputObjectTypeExtension, name: val[2], directives: val[3], fields: [], position_source: val[0]) + result + end +.,., # reduce 146 omitted # reduce 147 omitted -module_eval(<<'.,.,', 'parser.y', 350) - def _reduce_148(val, _values, result) +# reduce 148 omitted + +module_eval(<<'.,.,', 'parser.y', 351) + def _reduce_149(val, _values, result) 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]) result end .,., -module_eval(<<'.,.,', 'parser.y', 355) - def _reduce_149(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 356) + def _reduce_150(val, _values, result) result = make_node(:ObjectTypeDefinition, name: val[2], interfaces: val[3], directives: val[4], fields: val[6], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1]) result end .,., -module_eval(<<'.,.,', 'parser.y', 359) - def _reduce_150(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 360) + def _reduce_151(val, _values, result) result = EMPTY_ARRAY result end .,., -# reduce 151 omitted - -module_eval(<<'.,.,', 'parser.y', 363) - def _reduce_152(val, _values, result) - result = val[2] - result - end -.,., +# reduce 152 omitted module_eval(<<'.,.,', 'parser.y', 364) def _reduce_153(val, _values, result) - result = val[1] + result = val[2] result end .,., @@ -1796,162 +1797,169 @@ def _reduce_154(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 368) +module_eval(<<'.,.,', 'parser.y', 366) def _reduce_155(val, _values, result) - result = [make_node(:TypeName, name: val[0], position_source: val[0])] + result = val[1] result end .,., module_eval(<<'.,.,', 'parser.y', 369) def _reduce_156(val, _values, result) - val[0] << make_node(:TypeName, name: val[2], position_source: val[2]) + result = [make_node(:TypeName, name: val[0], position_source: val[0])] result end .,., -module_eval(<<'.,.,', 'parser.y', 372) +module_eval(<<'.,.,', 'parser.y', 370) def _reduce_157(val, _values, result) - result = [make_node(:TypeName, name: val[0], position_source: val[0])] + val[0] << make_node(:TypeName, name: val[2], position_source: val[2]) result end .,., module_eval(<<'.,.,', 'parser.y', 373) def _reduce_158(val, _values, result) - val[0] << make_node(:TypeName, name: val[1], position_source: val[1]) + result = [make_node(:TypeName, name: val[0], position_source: val[0])] result end .,., -module_eval(<<'.,.,', 'parser.y', 377) +module_eval(<<'.,.,', 'parser.y', 374) def _reduce_159(val, _values, result) - 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]) - + val[0] << make_node(:TypeName, name: val[1], position_source: val[1]) result end .,., -module_eval(<<'.,.,', 'parser.y', 381) +module_eval(<<'.,.,', 'parser.y', 378) def _reduce_160(val, _values, result) - result = [val[0]] + 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]) + result end .,., module_eval(<<'.,.,', 'parser.y', 382) def _reduce_161(val, _values, result) - val[0] << val[1] + result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 385) +module_eval(<<'.,.,', 'parser.y', 383) def _reduce_162(val, _values, result) - result = EMPTY_ARRAY + val[0] << val[1] result end .,., module_eval(<<'.,.,', 'parser.y', 386) def _reduce_163(val, _values, result) - result = val[1] + result = EMPTY_ARRAY result end .,., -module_eval(<<'.,.,', 'parser.y', 390) +module_eval(<<'.,.,', 'parser.y', 387) def _reduce_164(val, _values, result) - 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]) - + result = val[1] result end .,., -module_eval(<<'.,.,', 'parser.y', 394) +module_eval(<<'.,.,', 'parser.y', 391) def _reduce_165(val, _values, result) - result = EMPTY_ARRAY + 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]) + result end .,., module_eval(<<'.,.,', 'parser.y', 395) def _reduce_166(val, _values, result) - result = [val[0]] + result = EMPTY_ARRAY result end .,., module_eval(<<'.,.,', 'parser.y', 396) def _reduce_167(val, _values, result) - val[0] << val[1] + result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 400) +module_eval(<<'.,.,', 'parser.y', 397) def _reduce_168(val, _values, result) - result = make_node(:InterfaceTypeDefinition, 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]) - + val[0] << val[1] result end .,., -module_eval(<<'.,.,', 'parser.y', 404) +module_eval(<<'.,.,', 'parser.y', 401) def _reduce_169(val, _values, result) - result = [make_node(:TypeName, name: val[0], position_source: val[0])] + result = make_node(:InterfaceTypeDefinition, name: val[2], interfaces: val[3], directives: val[4], fields: val[6], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1]) + result end .,., module_eval(<<'.,.,', 'parser.y', 405) def _reduce_170(val, _values, result) - val[0] << make_node(:TypeName, name: val[2], position_source: val[2]) + result = [make_node(:TypeName, name: val[0], position_source: val[0])] result end .,., -module_eval(<<'.,.,', 'parser.y', 409) +module_eval(<<'.,.,', 'parser.y', 406) def _reduce_171(val, _values, result) - 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]) - + val[0] << make_node(:TypeName, name: val[2], position_source: val[2]) result end .,., -module_eval(<<'.,.,', 'parser.y', 414) +module_eval(<<'.,.,', 'parser.y', 410) def _reduce_172(val, _values, result) - 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]) + 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]) result end .,., -module_eval(<<'.,.,', 'parser.y', 419) +module_eval(<<'.,.,', 'parser.y', 415) def _reduce_173(val, _values, result) - 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]) + 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]) result end .,., -module_eval(<<'.,.,', 'parser.y', 424) +module_eval(<<'.,.,', 'parser.y', 420) def _reduce_174(val, _values, result) - result = make_node(:DirectiveDefinition, name: val[3], arguments: val[4], locations: val[6], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1]) + 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]) result end .,., -module_eval(<<'.,.,', 'parser.y', 428) +module_eval(<<'.,.,', 'parser.y', 425) def _reduce_175(val, _values, result) - result = [make_node(:DirectiveLocation, name: val[0].to_s, position_source: val[0])] + result = make_node(:DirectiveDefinition, name: val[3], arguments: val[4], locations: val[6], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1]) + result end .,., module_eval(<<'.,.,', 'parser.y', 429) def _reduce_176(val, _values, result) + result = [make_node(:DirectiveLocation, name: val[0].to_s, position_source: val[0])] + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 430) + def _reduce_177(val, _values, result) val[0] << make_node(:DirectiveLocation, name: val[2].to_s, position_source: val[2]) result end diff --git a/lib/graphql/language/parser.y b/lib/graphql/language/parser.y index 094dc98b80..990c96566d 100644 --- a/lib/graphql/language/parser.y +++ b/lib/graphql/language/parser.y @@ -325,8 +325,9 @@ rule | EXTEND TYPE name implements { result = make_node(:ObjectTypeExtension, name: val[2], interfaces: val[3], directives: [], fields: [], position_source: val[0]) } interface_type_extension: - EXTEND INTERFACE name directives_list_opt LCURLY field_definition_list RCURLY { result = make_node(:InterfaceTypeExtension, name: val[2], directives: val[3], fields: val[5], position_source: val[0]) } - | EXTEND INTERFACE name directives_list { result = make_node(:InterfaceTypeExtension, name: val[2], directives: val[3], fields: [], position_source: val[0]) } + EXTEND INTERFACE name implements_opt directives_list_opt LCURLY field_definition_list RCURLY { result = make_node(:InterfaceTypeExtension, name: val[2], interfaces: val[3], directives: val[4], fields: val[6], position_source: val[0]) } + | EXTEND INTERFACE name implements_opt directives_list { result = make_node(:InterfaceTypeExtension, name: val[2], interfaces: val[3], directives: val[4], fields: [], position_source: val[0]) } + | EXTEND INTERFACE name implements { result = make_node(:InterfaceTypeExtension, name: val[2], interfaces: val[3], directives: [], fields: [], position_source: val[0]) } union_type_extension: EXTEND UNION name directives_list_opt EQUALS union_members { result = make_node(:UnionTypeExtension, name: val[2], directives: val[3], types: val[5], position_source: val[0]) } @@ -397,8 +398,8 @@ rule | field_definition_list field_definition { val[0] << val[1] } interface_type_definition: - description_opt INTERFACE name directives_list_opt LCURLY field_definition_list RCURLY { - result = make_node(:InterfaceTypeDefinition, 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]) + description_opt INTERFACE name implements_opt directives_list_opt LCURLY field_definition_list RCURLY { + result = make_node(:InterfaceTypeDefinition, name: val[2], interfaces: val[3], directives: val[4], fields: val[6], description: val[0] || get_description(val[1]), definition_line: val[1].line, position_source: val[0] || val[1]) } union_members: diff --git a/lib/graphql/language/printer.rb b/lib/graphql/language/printer.rb index 0495e27de5..06f0259c8f 100644 --- a/lib/graphql/language/printer.rb +++ b/lib/graphql/language/printer.rb @@ -164,11 +164,15 @@ def print_scalar_type_definition(scalar_type) def print_object_type_definition(object_type) out = print_description(object_type) out << "type #{object_type.name}" - out << " implements " << object_type.interfaces.map(&:name).join(" & ") unless object_type.interfaces.empty? + out << print_implements(object_type) unless object_type.interfaces.empty? out << print_directives(object_type.directives) out << print_field_definitions(object_type.fields) end + def print_implements(type) + " implements #{type.interfaces.map(&:name).join(" & ")}" + end + def print_input_value_definition(input_value) out = "#{input_value.name}: #{print_node(input_value.type)}".dup out << " = #{print_node(input_value.default_value)}" unless input_value.default_value.nil? @@ -200,6 +204,7 @@ def print_field_definition(field) def print_interface_type_definition(interface_type) out = print_description(interface_type) out << "interface #{interface_type.name}" + out << print_implements(interface_type) if interface_type.interfaces.any? out << print_directives(interface_type.directives) out << print_field_definitions(interface_type.fields) end diff --git a/lib/graphql/schema/addition.rb b/lib/graphql/schema/addition.rb index 2c417c925c..685a6fb923 100644 --- a/lib/graphql/schema/addition.rb +++ b/lib/graphql/schema/addition.rb @@ -77,13 +77,13 @@ def add_type_and_traverse(new_types) def update_type_owner(owner, type) case owner - when Class + when Module if owner.kind.union? # It's a union with possible_types # Replace the item by class name owner.assign_type_membership_object_type(type) @possible_types[owner.graphql_name] = owner.possible_types - elsif type.kind.interface? && owner.kind.object? + elsif type.kind.interface? && (owner.kind.object? || owner.kind.interface?) new_interfaces = [] owner.interfaces.each do |int_t| if int_t.is_a?(String) && int_t == type.graphql_name @@ -98,12 +98,11 @@ def update_type_owner(owner, type) owner.implements(*new_interfaces) new_interfaces.each do |int| pt = @possible_types[int.graphql_name] ||= [] - if !pt.include?(owner) + if !pt.include?(owner) && owner.is_a?(Class) pt << owner end end end - when nil # It's a root type @types[type.graphql_name] = type @@ -214,12 +213,15 @@ def add_type(type, owner:, late_types:, path:) end if type.kind.object? @possible_types[type.graphql_name] = [type] + end + + if type.respond_to?(:interfaces) type.interface_type_memberships.each do |interface_type_membership| case interface_type_membership when Schema::TypeMembership interface_type = interface_type_membership.abstract_type # We can get these now; we'll have to get late-bound types later - if interface_type.is_a?(Module) + if interface_type.is_a?(Module) && type.is_a?(Class) implementers = @possible_types[interface_type.graphql_name] ||= [] implementers << type end diff --git a/lib/graphql/schema/build_from_definition.rb b/lib/graphql/schema/build_from_definition.rb index c6fc0ba850..c4c0930306 100644 --- a/lib/graphql/schema/build_from_definition.rb +++ b/lib/graphql/schema/build_from_definition.rb @@ -394,6 +394,11 @@ def build_interface_type(interface_type_definition, type_resolver) include GraphQL::Schema::Interface graphql_name(interface_type_definition.name) description(interface_type_definition.description) + interface_type_definition.interfaces.each do |interface_name| + "Implements: #{interface_type_definition} -> #{interface_name}" + interface_defn = type_resolver.call(interface_name) + implements(interface_defn) + end ast_node(interface_type_definition) builder.build_directives(self, interface_type_definition, type_resolver) diff --git a/lib/graphql/schema/interface.rb b/lib/graphql/schema/interface.rb index d04ab48f87..1c0659e4c8 100644 --- a/lib/graphql/schema/interface.rb +++ b/lib/graphql/schema/interface.rb @@ -16,6 +16,7 @@ module DefinitionMethods include GraphQL::Schema::Member::HasAstNode include GraphQL::Schema::Member::HasUnresolvedTypeError include GraphQL::Schema::Member::HasDirectives + include GraphQL::Schema::Member::HasInterfaces # Methods defined in this block will be: # - Added as class methods to this interface @@ -57,9 +58,10 @@ def included(child_class) child_class.extend(Schema::Interface::DefinitionMethods) child_class.type_membership_class(self.type_membership_class) - child_class.own_interfaces << self - child_class.interfaces.reverse_each do |interface_defn| - child_class.extend(interface_defn::DefinitionMethods) + child_class.ancestors.reverse_each do |ancestor| + if ancestor.const_defined?(:DefinitionMethods) + child_class.extend(ancestor::DefinitionMethods) + end end # Use an instance variable to tell whether it's been included previously or not; @@ -73,16 +75,13 @@ def included(child_class) end child_class.introspection(introspection) child_class.description(description) - if overridden_graphql_name - child_class.graphql_name(overridden_graphql_name) - end # If interfaces are mixed into each other, only define this class once if !child_class.const_defined?(:UnresolvedTypeError, false) add_unresolved_type_error(child_class) end elsif child_class < GraphQL::Schema::Object # This is being included into an object type, make sure it's using `implements(...)` - backtrace_line = caller(0, 10).find { |line| line.include?("schema/object.rb") && line.include?("in `implements'")} + backtrace_line = caller(0, 10).find { |line| line.include?("schema/member/has_interfaces.rb") && line.include?("in `implements'")} if !backtrace_line raise "Attach interfaces using `implements(#{self})`, not `include(#{self})`" end @@ -122,16 +121,6 @@ def to_graphql def kind GraphQL::TypeKinds::INTERFACE end - - protected - - def own_interfaces - @own_interfaces ||= [] - end - - def interfaces - own_interfaces + (own_interfaces.map { |i| i.own_interfaces }).flatten - end end # Extend this _after_ `DefinitionMethods` is defined, so it will be used diff --git a/lib/graphql/schema/member.rb b/lib/graphql/schema/member.rb index c8a191e7e2..887ede8747 100644 --- a/lib/graphql/schema/member.rb +++ b/lib/graphql/schema/member.rb @@ -6,6 +6,7 @@ require 'graphql/schema/member/has_ast_node' require 'graphql/schema/member/has_directives' require 'graphql/schema/member/has_deprecation_reason' +require 'graphql/schema/member/has_interfaces' require 'graphql/schema/member/has_path' require 'graphql/schema/member/has_unresolved_type_error' require 'graphql/schema/member/has_validators' diff --git a/lib/graphql/schema/member/accepts_definition.rb b/lib/graphql/schema/member/accepts_definition.rb index e450a7b683..96aa12753c 100644 --- a/lib/graphql/schema/member/accepts_definition.rb +++ b/lib/graphql/schema/member/accepts_definition.rb @@ -85,8 +85,15 @@ def accepts_definition(name) define_method(name) do |*args| if args.any? instance_variable_set(ivar_name, args) + else + if (v = instance_variable_get(ivar_name)) + v + elsif (ancestor = ancestors.find { |i| i.respond_to?(name) && i != self }) + ancestor.public_send(name) + else + nil + end end - instance_variable_get(ivar_name) || ((int = interfaces.first { |i| i.respond_to?()}) && int.public_send(name)) end end end diff --git a/lib/graphql/schema/member/has_fields.rb b/lib/graphql/schema/member/has_fields.rb index 6c76ea0c10..466a46fd7e 100644 --- a/lib/graphql/schema/member/has_fields.rb +++ b/lib/graphql/schema/member/has_fields.rb @@ -3,7 +3,7 @@ module GraphQL class Schema class Member - # Shared code for Object and Interface + # Shared code for Objects, Interfaces, Mutations, Subscriptions module HasFields # Add a field to this object or interface with the given definition # @see {GraphQL::Schema::Field#initialize} for method signature diff --git a/lib/graphql/schema/member/has_interfaces.rb b/lib/graphql/schema/member/has_interfaces.rb new file mode 100644 index 0000000000..21e9f34799 --- /dev/null +++ b/lib/graphql/schema/member/has_interfaces.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +module GraphQL + class Schema + class Member + module HasInterfaces + def implements(*new_interfaces, **options) + new_memberships = [] + new_interfaces.each do |int| + if int.is_a?(Module) + unless int.include?(GraphQL::Schema::Interface) + raise "#{int} cannot be implemented since it's not a GraphQL Interface. Use `include` for plain Ruby modules." + end + + new_memberships << int.type_membership_class.new(int, self, **options) + + # Include the methods here, + # `.fields` will use the inheritance chain + # to find inherited fields + include(int) + + # If this interface has interfaces of its own, add those, too + int.interfaces.each do |next_interface| + implements(next_interface) + end + elsif int.is_a?(GraphQL::InterfaceType) + new_memberships << int.type_membership_class.new(int, self, **options) + elsif int.is_a?(String) || int.is_a?(GraphQL::Schema::LateBoundType) + if options.any? + raise ArgumentError, "`implements(...)` doesn't support options with late-loaded types yet. Remove #{options} and open an issue to request this feature." + end + new_memberships << int + else + raise ArgumentError, "Unexpected interface definition (expected module): #{int} (#{int.class})" + end + end + + # Remove any interfaces which are being replaced (late-bound types are updated in place this way) + own_interface_type_memberships.reject! { |old_i_m| + old_int_type = old_i_m.respond_to?(:abstract_type) ? old_i_m.abstract_type : old_i_m + old_name = Schema::Member::BuildType.to_type_name(old_int_type) + + new_memberships.any? { |new_i_m| + new_int_type = new_i_m.respond_to?(:abstract_type) ? new_i_m.abstract_type : new_i_m + new_name = Schema::Member::BuildType.to_type_name(new_int_type) + + new_name == old_name + } + } + own_interface_type_memberships.concat(new_memberships) + end + + def own_interface_type_memberships + @own_interface_type_memberships ||= [] + end + + def interface_type_memberships + own_interface_type_memberships + ((self.is_a?(Class) && superclass.respond_to?(:interface_type_memberships)) ? superclass.interface_type_memberships : []) + end + + # param context [Query::Context] If omitted, skip filtering. + def interfaces(context = GraphQL::Query::NullContext) + visible_interfaces = [] + unfiltered = context == GraphQL::Query::NullContext + own_interface_type_memberships.each do |type_membership| + # During initialization, `type_memberships` can hold late-bound types + case type_membership + when String, Schema::LateBoundType + visible_interfaces << type_membership + when Schema::TypeMembership + if unfiltered || type_membership.visible?(context) + visible_interfaces << type_membership.abstract_type + end + else + raise "Invariant: Unexpected type_membership #{type_membership.class}: #{type_membership.inspect}" + end + end + + if self.is_a?(Class) && superclass <= GraphQL::Schema::Object + visible_interfaces.concat(superclass.interfaces(context)) + end + + visible_interfaces + end + end + end + end +end diff --git a/lib/graphql/schema/object.rb b/lib/graphql/schema/object.rb index 1689f036ef..3d9d0fb9c2 100644 --- a/lib/graphql/schema/object.rb +++ b/lib/graphql/schema/object.rb @@ -7,6 +7,7 @@ class Schema class Object < GraphQL::Schema::Member extend GraphQL::Schema::Member::AcceptsDefinition extend GraphQL::Schema::Member::HasFields + extend GraphQL::Schema::Member::HasInterfaces # @return [Object] the application object this type is wrapping attr_reader :object @@ -103,75 +104,6 @@ def inherited(child_class) super end - def implements(*new_interfaces, **options) - new_memberships = [] - new_interfaces.each do |int| - if int.is_a?(Module) - unless int.include?(GraphQL::Schema::Interface) - raise "#{int} cannot be implemented since it's not a GraphQL Interface. Use `include` for plain Ruby modules." - end - - new_memberships << int.type_membership_class.new(int, self, **options) - - # Include the methods here, - # `.fields` will use the inheritance chain - # to find inherited fields - include(int) - elsif int.is_a?(GraphQL::InterfaceType) - new_memberships << int.type_membership_class.new(int, self, **options) - elsif int.is_a?(String) || int.is_a?(GraphQL::Schema::LateBoundType) - if options.any? - raise ArgumentError, "`implements(...)` doesn't support options with late-loaded types yet. Remove #{options} and open an issue to request this feature." - end - new_memberships << int - else - raise ArgumentError, "Unexpected interface definition (expected module): #{int} (#{int.class})" - end - end - - # Remove any interfaces which are being replaced (late-bound types are updated in place this way) - own_interface_type_memberships.reject! { |old_i_m| - old_int_type = old_i_m.respond_to?(:abstract_type) ? old_i_m.abstract_type : old_i_m - old_name = Schema::Member::BuildType.to_type_name(old_int_type) - - new_memberships.any? { |new_i_m| - new_int_type = new_i_m.respond_to?(:abstract_type) ? new_i_m.abstract_type : new_i_m - new_name = Schema::Member::BuildType.to_type_name(new_int_type) - - new_name == old_name - } - } - own_interface_type_memberships.concat(new_memberships) - end - - def own_interface_type_memberships - @own_interface_type_memberships ||= [] - end - - def interface_type_memberships - own_interface_type_memberships + (superclass.respond_to?(:interface_type_memberships) ? superclass.interface_type_memberships : []) - end - - # param context [Query::Context] If omitted, skip filtering. - def interfaces(context = GraphQL::Query::NullContext) - visible_interfaces = [] - unfiltered = context == GraphQL::Query::NullContext - own_interface_type_memberships.each do |type_membership| - # During initialization, `type_memberships` can hold late-bound types - case type_membership - when String, Schema::LateBoundType - visible_interfaces << type_membership - when Schema::TypeMembership - if unfiltered || type_membership.visible?(context) - visible_interfaces << type_membership.abstract_type - end - else - raise "Invariant: Unexpected type_membership #{type_membership.class}: #{type_membership.inspect}" - end - end - visible_interfaces + (superclass <= GraphQL::Schema::Object ? superclass.interfaces(context) : []) - end - # @return [Hash GraphQL::Schema::Field>] All of this object's fields, indexed by name # @see get_field A faster way to find one field by name ({#fields} merges hashes of inherited fields; {#get_field} just looks up one field.) def fields diff --git a/spec/graphql/schema/build_from_definition_spec.rb b/spec/graphql/schema/build_from_definition_spec.rb index fd21eaf9af..526ab87e74 100644 --- a/spec/graphql/schema/build_from_definition_spec.rb +++ b/spec/graphql/schema/build_from_definition_spec.rb @@ -512,6 +512,30 @@ def assert_schema_and_compare_output(definition) assert_schema_and_compare_output(schema) end + it "supports interfaces that implement interfaces" do + schema = <<-SCHEMA +interface Named implements Node { + id: ID + name: String +} + +interface Node { + id: ID +} + +type Query { + thing: Thing +} + +type Thing implements Named & Node { + id: ID + name: String +} + SCHEMA + + assert_schema_and_compare_output(schema) + end + it 'supports simple output enum' do schema = <<-SCHEMA schema { diff --git a/spec/graphql/schema/interface_spec.rb b/spec/graphql/schema/interface_spec.rb index 7477606fa3..65630f464c 100644 --- a/spec/graphql/schema/interface_spec.rb +++ b/spec/graphql/schema/interface_spec.rb @@ -214,6 +214,69 @@ module InterfaceE end end + describe "can implement other interfaces" do + class InterfaceImplementsSchema < GraphQL::Schema + module InterfaceA + include GraphQL::Schema::Interface + field :a, String, null: true + + def a; "a"; end + end + + module InterfaceB + include GraphQL::Schema::Interface + implements InterfaceA + field :b, String, null: true + + def b; "b"; end + end + + class Query < GraphQL::Schema::Object + implements InterfaceB + end + + query(Query) + end + + it "runs queries on inherited interfaces" do + result = InterfaceImplementsSchema.execute("{ a b }") + assert_equal "a", result["data"]["a"] + assert_equal "b", result["data"]["b"] + + result2 = InterfaceImplementsSchema.execute(<<-GRAPHQL) + { + ... on InterfaceA { + ... on InterfaceB { + f1: a + f2: b + } + } + } + GRAPHQL + assert_equal "a", result2["data"]["f1"] + assert_equal "b", result2["data"]["f2"] + end + + it "has the right structure" do + expected_schema = <<-SCHEMA +interface InterfaceA { + a: String +} + +interface InterfaceB implements InterfaceA { + a: String + b: String +} + +type Query implements InterfaceA & InterfaceB { + a: String + b: String +} + SCHEMA + assert_equal expected_schema, InterfaceImplementsSchema.to_definition + end + end + describe "migrated legacy tests" do let(:interface) { Dummy::Edible } From 3805648a58eee7ea92723f2b191446ccdba08026 Mon Sep 17 00:00:00 2001 From: Robert Mosolgo Date: Wed, 8 Sep 2021 14:20:48 -0400 Subject: [PATCH 7/7] Add interface interfaces to introspection --- lib/graphql/introspection/type_type.rb | 2 +- spec/graphql/schema/interface_spec.rb | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/graphql/introspection/type_type.rb b/lib/graphql/introspection/type_type.rb index ba834555e5..2965b88f0c 100644 --- a/lib/graphql/introspection/type_type.rb +++ b/lib/graphql/introspection/type_type.rb @@ -50,7 +50,7 @@ def enum_values(include_deprecated:) end def interfaces - if @object.kind == GraphQL::TypeKinds::OBJECT + if @object.kind.object? || @object.kind.interface? @context.warden.interfaces(@object) else nil diff --git a/spec/graphql/schema/interface_spec.rb b/spec/graphql/schema/interface_spec.rb index 65630f464c..6cdedeffc0 100644 --- a/spec/graphql/schema/interface_spec.rb +++ b/spec/graphql/schema/interface_spec.rb @@ -257,6 +257,11 @@ class Query < GraphQL::Schema::Object assert_equal "b", result2["data"]["f2"] end + it "shows up in introspection" do + result = InterfaceImplementsSchema.execute("{ __type(name: \"InterfaceB\") { interfaces { name } } }") + assert_equal ["InterfaceA"], result["data"]["__type"]["interfaces"].map { |i| i["name"] } + end + it "has the right structure" do expected_schema = <<-SCHEMA interface InterfaceA {