Skip to content

Commit 246b4fd

Browse files
committed
Eliminate runtime .is_a? checks from HasArguments
1 parent dc06a16 commit 246b4fd

3 files changed

Lines changed: 104 additions & 55 deletions

File tree

lib/graphql/schema/directive.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class Schema
88
# - {.resolve}: Wraps field resolution (so it should call `yield` to continue)
99
class Directive < GraphQL::Schema::Member
1010
extend GraphQL::Schema::Member::HasArguments
11+
extend GraphQL::Schema::Member::HasArguments::HasDirectiveArguments
1112

1213
class << self
1314
# Directives aren't types, they don't have kinds.

lib/graphql/schema/field.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module GraphQL
66
class Schema
77
class Field
88
include GraphQL::Schema::Member::HasArguments
9+
include GraphQL::Schema::Member::HasArguments::FieldConfigured
910
include GraphQL::Schema::Member::HasAstNode
1011
include GraphQL::Schema::Member::HasPath
1112
include GraphQL::Schema::Member::HasValidators

lib/graphql/schema/member/has_arguments.rb

Lines changed: 102 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ def self.included(cls)
1111
def self.extended(cls)
1212
cls.extend(ArgumentClassAccessor)
1313
cls.include(ArgumentObjectLoader)
14+
cls.extend(ClassConfigured)
1415
end
1516

1617
# @see {GraphQL::Schema::Argument#initialize} for parameters
@@ -109,14 +110,6 @@ def remove_argument(arg_defn)
109110

110111
# @return [Hash<String => GraphQL::Schema::Argument] Arguments defined on this thing, keyed by name. Includes inherited definitions
111112
def arguments(context = GraphQL::Query::NullContext)
112-
inherited_arguments = if self.is_a?(Class) && superclass.respond_to?(:arguments)
113-
superclass.arguments(context)
114-
elsif defined?(@resolver_class) && @resolver_class
115-
@resolver_class.field_arguments(context)
116-
else
117-
nil
118-
end
119-
# Local definitions override inherited ones
120113
if own_arguments.any?
121114
own_arguments_that_apply = {}
122115
own_arguments.each do |name, args_entry|
@@ -125,70 +118,119 @@ def arguments(context = GraphQL::Query::NullContext)
125118
end
126119
end
127120
end
121+
# might be nil if there are actually no arguments
122+
own_arguments_that_apply || own_arguments
123+
end
128124

129-
if inherited_arguments
130-
if own_arguments_that_apply
131-
inherited_arguments.merge(own_arguments_that_apply)
132-
else
133-
inherited_arguments
125+
module ClassConfigured
126+
def inherited(child_class)
127+
super
128+
child_class.extend(InheritedArguments)
129+
end
130+
131+
module InheritedArguments
132+
def arguments(context = GraphQL::Query::NullContext)
133+
own_arguments = super
134+
inherited_arguments = superclass.arguments(context)
135+
136+
if own_arguments.any?
137+
if inherited_arguments.any?
138+
# Local definitions override inherited ones
139+
inherited_arguments.merge(own_arguments)
140+
else
141+
own_arguments
142+
end
143+
else
144+
inherited_arguments
145+
end
146+
end
147+
148+
def all_argument_definitions
149+
all_defns = {}
150+
ancestors.reverse_each do |ancestor|
151+
if ancestor.respond_to?(:own_arguments)
152+
all_defns.merge!(ancestor.own_arguments)
153+
end
154+
end
155+
all_defns = all_defns.values
156+
all_defns.flatten!
157+
all_defns
158+
end
159+
160+
161+
def get_argument(argument_name, context = GraphQL::Query::NullContext)
162+
warden = Warden.from_context(context)
163+
for ancestor in ancestors
164+
if ancestor.respond_to?(:own_arguments) &&
165+
(a = ancestor.own_arguments[argument_name]) &&
166+
(a = Warden.visible_entry?(:visible_argument?, a, context, warden))
167+
return a
168+
end
169+
end
170+
nil
134171
end
135-
else
136-
# might be nil if there are actually no arguments
137-
own_arguments_that_apply || own_arguments
138172
end
139173
end
140174

141-
def all_argument_definitions
142-
if self.is_a?(Class)
143-
all_defns = {}
144-
ancestors.reverse_each do |ancestor|
145-
if ancestor.respond_to?(:own_arguments)
146-
all_defns.merge!(ancestor.own_arguments)
175+
module FieldConfigured
176+
def arguments(context = GraphQL::Query::NullContext)
177+
own_arguments = super
178+
if defined?(@resolver_class) && @resolver_class
179+
inherited_arguments = @resolver_class.field_arguments(context)
180+
if own_arguments.any?
181+
if inherited_arguments.any?
182+
inherited_arguments.merge(own_arguments)
183+
else
184+
own_arguments
185+
end
186+
else
187+
inherited_arguments
147188
end
189+
else
190+
own_arguments
148191
end
149-
elsif defined?(@resolver_class) && @resolver_class
150-
all_defns = {}
151-
@resolver_class.all_field_argument_definitions.each do |arg_defn|
152-
key = arg_defn.graphql_name
153-
case (current_value = all_defns[key])
154-
when nil
155-
all_defns[key] = arg_defn
156-
when Array
157-
current_value << arg_defn
158-
when GraphQL::Schema::Argument
159-
all_defns[key] = [current_value, arg_defn]
160-
else
161-
raise "Invariant: Unexpected argument definition, #{current_value.class}: #{current_value.inspect}"
192+
end
193+
194+
def all_argument_definitions
195+
if defined?(@resolver_class) && @resolver_class
196+
all_defns = {}
197+
@resolver_class.all_field_argument_definitions.each do |arg_defn|
198+
key = arg_defn.graphql_name
199+
case (current_value = all_defns[key])
200+
when nil
201+
all_defns[key] = arg_defn
202+
when Array
203+
current_value << arg_defn
204+
when GraphQL::Schema::Argument
205+
all_defns[key] = [current_value, arg_defn]
206+
else
207+
raise "Invariant: Unexpected argument definition, #{current_value.class}: #{current_value.inspect}"
208+
end
162209
end
210+
all_defns.merge!(own_arguments)
211+
all_defns = all_defns.values
212+
all_defns.flatten!
213+
all_defns
214+
else
215+
super
163216
end
164-
all_defns.merge!(own_arguments)
165-
else
166-
all_defns = own_arguments
167217
end
168-
all_defns = all_defns.values
218+
end
219+
220+
def all_argument_definitions
221+
all_defns = own_arguments.values
169222
all_defns.flatten!
170223
all_defns
171224
end
172225

173226
# @return [GraphQL::Schema::Argument, nil] Argument defined on this thing, fetched by name.
174227
def get_argument(argument_name, context = GraphQL::Query::NullContext)
175228
warden = Warden.from_context(context)
176-
if !self.is_a?(Class)
177-
if (arg_config = own_arguments[argument_name]) && (visible_arg = Warden.visible_entry?(:visible_argument?, arg_config, context, warden))
178-
visible_arg
179-
elsif defined?(@resolver_class) && @resolver_class
180-
@resolver_class.get_field_argument(argument_name, context)
181-
else
182-
nil
183-
end
229+
if (arg_config = own_arguments[argument_name]) && (visible_arg = Warden.visible_entry?(:visible_argument?, arg_config, context, warden))
230+
visible_arg
231+
elsif defined?(@resolver_class) && @resolver_class
232+
@resolver_class.get_field_argument(argument_name, context)
184233
else
185-
for ancestor in ancestors
186-
if ancestor.respond_to?(:own_arguments) &&
187-
(a = ancestor.own_arguments[argument_name]) &&
188-
(a = Warden.visible_entry?(:visible_argument?, a, context, warden))
189-
return a
190-
end
191-
end
192234
nil
193235
end
194236
end
@@ -265,7 +307,12 @@ def coerce_arguments(parent_object, values, context, &block)
265307
# but not for directives.
266308
# TODO apply static validations on schema definitions?
267309
def validate_directive_argument(arg_defn, value)
268-
if arg_defn.owner.is_a?(Class) && arg_defn.owner < GraphQL::Schema::Directive
310+
# this is only implemented on directives.
311+
nil
312+
end
313+
314+
module HasDirectiveArguments
315+
def validate_directive_argument(arg_defn, value)
269316
if value.nil? && arg_defn.type.non_null?
270317
raise ArgumentError, "#{arg_defn.path} is required, but no value was given"
271318
end

0 commit comments

Comments
 (0)