graphql 2.1.1 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/graphql/analysis/ast/query_depth.rb +7 -2
- data/lib/graphql/dataloader.rb +29 -10
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +1 -1
- data/lib/graphql/execution/interpreter/runtime.rb +7 -26
- data/lib/graphql/execution/lookahead.rb +87 -20
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/pagination/connection.rb +15 -10
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/query/context.rb +4 -0
- data/lib/graphql/query/null_context.rb +2 -10
- data/lib/graphql/query.rb +10 -0
- data/lib/graphql/schema/build_from_definition.rb +0 -11
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive.rb +1 -1
- data/lib/graphql/schema/enum.rb +2 -2
- data/lib/graphql/schema/field/scope_extension.rb +4 -3
- data/lib/graphql/schema/field.rb +2 -2
- data/lib/graphql/schema/has_single_input_argument.rb +2 -2
- data/lib/graphql/schema/input_object.rb +1 -1
- data/lib/graphql/schema/interface.rb +10 -10
- data/lib/graphql/schema/loader.rb +0 -2
- data/lib/graphql/schema/member/has_arguments.rb +47 -36
- data/lib/graphql/schema/member/has_fields.rb +4 -4
- data/lib/graphql/schema/member/has_interfaces.rb +2 -2
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/resolver.rb +3 -3
- data/lib/graphql/schema/union.rb +1 -1
- data/lib/graphql/schema/warden.rb +73 -57
- data/lib/graphql/schema.rb +154 -43
- data/lib/graphql/subscriptions/event.rb +1 -1
- data/lib/graphql/subscriptions.rb +2 -2
- data/lib/graphql/version.rb +1 -1
- metadata +17 -17
@@ -20,6 +20,15 @@ module GraphQL
|
|
20
20
|
# - Added as class methods to this interface
|
21
21
|
# - Added as class methods to all child interfaces
|
22
22
|
def definition_methods(&block)
|
23
|
+
# Use an instance variable to tell whether it's been included previously or not;
|
24
|
+
# You can't use constant detection because constants are brought into scope
|
25
|
+
# by `include`, which has already happened at this point.
|
26
|
+
if !defined?(@_definition_methods)
|
27
|
+
defn_methods_module = Module.new
|
28
|
+
@_definition_methods = defn_methods_module
|
29
|
+
const_set(:DefinitionMethods, defn_methods_module)
|
30
|
+
extend(self::DefinitionMethods)
|
31
|
+
end
|
23
32
|
self::DefinitionMethods.module_eval(&block)
|
24
33
|
end
|
25
34
|
|
@@ -47,20 +56,11 @@ module GraphQL
|
|
47
56
|
|
48
57
|
child_class.type_membership_class(self.type_membership_class)
|
49
58
|
child_class.ancestors.reverse_each do |ancestor|
|
50
|
-
if ancestor.const_defined?(:DefinitionMethods)
|
59
|
+
if ancestor.const_defined?(:DefinitionMethods) && ancestor != child_class
|
51
60
|
child_class.extend(ancestor::DefinitionMethods)
|
52
61
|
end
|
53
62
|
end
|
54
63
|
|
55
|
-
# Use an instance variable to tell whether it's been included previously or not;
|
56
|
-
# You can't use constant detection because constants are brought into scope
|
57
|
-
# by `include`, which has already happened at this point.
|
58
|
-
if !child_class.instance_variable_defined?(:@_definition_methods)
|
59
|
-
defn_methods_module = Module.new
|
60
|
-
child_class.instance_variable_set(:@_definition_methods, defn_methods_module)
|
61
|
-
child_class.const_set(:DefinitionMethods, defn_methods_module)
|
62
|
-
child_class.extend(child_class::DefinitionMethods)
|
63
|
-
end
|
64
64
|
child_class.introspection(introspection)
|
65
65
|
child_class.description(description)
|
66
66
|
# If interfaces are mixed into each other, only define this class once
|
@@ -176,7 +176,6 @@ module GraphQL
|
|
176
176
|
while (of_type = unwrapped_field_hash["ofType"])
|
177
177
|
unwrapped_field_hash = of_type
|
178
178
|
end
|
179
|
-
type_name = unwrapped_field_hash["name"]
|
180
179
|
|
181
180
|
type_defn.field(
|
182
181
|
field_hash["name"],
|
@@ -186,7 +185,6 @@ module GraphQL
|
|
186
185
|
null: true,
|
187
186
|
camelize: false,
|
188
187
|
connection_extension: nil,
|
189
|
-
connection: type_name.end_with?("Connection"),
|
190
188
|
) do
|
191
189
|
if field_hash["args"].any?
|
192
190
|
loader.build_arguments(self, field_hash["args"], type_resolver)
|
@@ -109,7 +109,7 @@ module GraphQL
|
|
109
109
|
end
|
110
110
|
|
111
111
|
# @return [Hash<String => GraphQL::Schema::Argument] Arguments defined on this thing, keyed by name. Includes inherited definitions
|
112
|
-
def arguments(context = GraphQL::Query::NullContext)
|
112
|
+
def arguments(context = GraphQL::Query::NullContext.instance)
|
113
113
|
if own_arguments.any?
|
114
114
|
own_arguments_that_apply = {}
|
115
115
|
own_arguments.each do |name, args_entry|
|
@@ -133,7 +133,7 @@ module GraphQL
|
|
133
133
|
end
|
134
134
|
|
135
135
|
module InheritedArguments
|
136
|
-
def arguments(context = GraphQL::Query::NullContext)
|
136
|
+
def arguments(context = GraphQL::Query::NullContext.instance)
|
137
137
|
own_arguments = super
|
138
138
|
inherited_arguments = superclass.arguments(context)
|
139
139
|
|
@@ -166,7 +166,7 @@ module GraphQL
|
|
166
166
|
end
|
167
167
|
|
168
168
|
|
169
|
-
def get_argument(argument_name, context = GraphQL::Query::NullContext)
|
169
|
+
def get_argument(argument_name, context = GraphQL::Query::NullContext.instance)
|
170
170
|
warden = Warden.from_context(context)
|
171
171
|
for ancestor in ancestors
|
172
172
|
if ancestor.respond_to?(:own_arguments) &&
|
@@ -181,7 +181,7 @@ module GraphQL
|
|
181
181
|
end
|
182
182
|
|
183
183
|
module FieldConfigured
|
184
|
-
def arguments(context = GraphQL::Query::NullContext)
|
184
|
+
def arguments(context = GraphQL::Query::NullContext.instance)
|
185
185
|
own_arguments = super
|
186
186
|
if @resolver_class
|
187
187
|
inherited_arguments = @resolver_class.field_arguments(context)
|
@@ -236,7 +236,7 @@ module GraphQL
|
|
236
236
|
end
|
237
237
|
|
238
238
|
# @return [GraphQL::Schema::Argument, nil] Argument defined on this thing, fetched by name.
|
239
|
-
def get_argument(argument_name, context = GraphQL::Query::NullContext)
|
239
|
+
def get_argument(argument_name, context = GraphQL::Query::NullContext.instance)
|
240
240
|
warden = Warden.from_context(context)
|
241
241
|
if (arg_config = own_arguments[argument_name]) && (visible_arg = Warden.visible_entry?(:visible_argument?, arg_config, context, warden))
|
242
242
|
visible_arg
|
@@ -379,41 +379,52 @@ module GraphQL
|
|
379
379
|
def authorize_application_object(argument, id, context, loaded_application_object)
|
380
380
|
context.query.after_lazy(loaded_application_object) do |application_object|
|
381
381
|
if application_object.nil?
|
382
|
-
err = GraphQL::LoadApplicationObjectFailedError.new(argument: argument, id: id, object: application_object)
|
383
|
-
load_application_object_failed(err)
|
382
|
+
err = GraphQL::LoadApplicationObjectFailedError.new(context: context, argument: argument, id: id, object: application_object)
|
383
|
+
application_object = load_application_object_failed(err)
|
384
384
|
end
|
385
385
|
# Double-check that the located object is actually of this type
|
386
386
|
# (Don't want to allow arbitrary access to objects this way)
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
387
|
+
if application_object.nil?
|
388
|
+
nil
|
389
|
+
else
|
390
|
+
maybe_lazy_resolve_type = context.schema.resolve_type(argument.loads, application_object, context)
|
391
|
+
context.query.after_lazy(maybe_lazy_resolve_type) do |resolve_type_result|
|
392
|
+
if resolve_type_result.is_a?(Array) && resolve_type_result.size == 2
|
393
|
+
application_object_type, application_object = resolve_type_result
|
394
|
+
else
|
395
|
+
application_object_type = resolve_type_result
|
396
|
+
# application_object is already assigned
|
397
|
+
end
|
398
|
+
|
399
|
+
if !(
|
400
|
+
context.warden.possible_types(argument.loads).include?(application_object_type) ||
|
401
|
+
context.warden.loadable?(argument.loads, context)
|
402
|
+
)
|
403
|
+
err = GraphQL::LoadApplicationObjectFailedError.new(context: context, argument: argument, id: id, object: application_object)
|
404
|
+
application_object = load_application_object_failed(err)
|
405
|
+
end
|
406
|
+
|
407
|
+
if application_object.nil?
|
408
|
+
nil
|
409
|
+
else
|
410
|
+
# This object was loaded successfully
|
411
|
+
# and resolved to the right type,
|
412
|
+
# now apply the `.authorized?` class method if there is one
|
413
|
+
context.query.after_lazy(application_object_type.authorized?(application_object, context)) do |authed|
|
414
|
+
if authed
|
415
|
+
application_object
|
415
416
|
else
|
416
|
-
|
417
|
+
err = GraphQL::UnauthorizedError.new(
|
418
|
+
object: application_object,
|
419
|
+
type: application_object_type,
|
420
|
+
context: context,
|
421
|
+
)
|
422
|
+
if self.respond_to?(:unauthorized_object)
|
423
|
+
err.set_backtrace(caller)
|
424
|
+
unauthorized_object(err)
|
425
|
+
else
|
426
|
+
raise err
|
427
|
+
end
|
417
428
|
end
|
418
429
|
end
|
419
430
|
end
|
@@ -97,7 +97,7 @@ module GraphQL
|
|
97
97
|
end
|
98
98
|
|
99
99
|
module InterfaceMethods
|
100
|
-
def get_field(field_name, context = GraphQL::Query::NullContext)
|
100
|
+
def get_field(field_name, context = GraphQL::Query::NullContext.instance)
|
101
101
|
warden = Warden.from_context(context)
|
102
102
|
for ancestor in ancestors
|
103
103
|
if ancestor.respond_to?(:own_fields) &&
|
@@ -110,7 +110,7 @@ module GraphQL
|
|
110
110
|
end
|
111
111
|
|
112
112
|
# @return [Hash<String => GraphQL::Schema::Field>] Fields on this object, keyed by name, including inherited fields
|
113
|
-
def fields(context = GraphQL::Query::NullContext)
|
113
|
+
def fields(context = GraphQL::Query::NullContext.instance)
|
114
114
|
warden = Warden.from_context(context)
|
115
115
|
# Local overrides take precedence over inherited fields
|
116
116
|
visible_fields = {}
|
@@ -130,7 +130,7 @@ module GraphQL
|
|
130
130
|
end
|
131
131
|
|
132
132
|
module ObjectMethods
|
133
|
-
def get_field(field_name, context = GraphQL::Query::NullContext)
|
133
|
+
def get_field(field_name, context = GraphQL::Query::NullContext.instance)
|
134
134
|
# Objects need to check that the interface implementation is visible, too
|
135
135
|
warden = Warden.from_context(context)
|
136
136
|
ancs = ancestors
|
@@ -148,7 +148,7 @@ module GraphQL
|
|
148
148
|
end
|
149
149
|
|
150
150
|
# @return [Hash<String => GraphQL::Schema::Field>] Fields on this object, keyed by name, including inherited fields
|
151
|
-
def fields(context = GraphQL::Query::NullContext)
|
151
|
+
def fields(context = GraphQL::Query::NullContext.instance)
|
152
152
|
# Objects need to check that the interface implementation is visible, too
|
153
153
|
warden = Warden.from_context(context)
|
154
154
|
# Local overrides take precedence over inherited fields
|
@@ -70,7 +70,7 @@ module GraphQL
|
|
70
70
|
end
|
71
71
|
|
72
72
|
module InheritedInterfaces
|
73
|
-
def interfaces(context = GraphQL::Query::NullContext)
|
73
|
+
def interfaces(context = GraphQL::Query::NullContext.instance)
|
74
74
|
visible_interfaces = super
|
75
75
|
inherited_interfaces = superclass.interfaces(context)
|
76
76
|
if visible_interfaces.any?
|
@@ -99,7 +99,7 @@ module GraphQL
|
|
99
99
|
end
|
100
100
|
|
101
101
|
# param context [Query::Context] If omitted, skip filtering.
|
102
|
-
def interfaces(context = GraphQL::Query::NullContext)
|
102
|
+
def interfaces(context = GraphQL::Query::NullContext.instance)
|
103
103
|
warden = Warden.from_context(context)
|
104
104
|
visible_interfaces = nil
|
105
105
|
own_interface_type_memberships.each do |type_membership|
|
@@ -17,15 +17,15 @@ module GraphQL
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def valid_isolated_input?(v)
|
20
|
-
valid_input?(v, GraphQL::Query::NullContext)
|
20
|
+
valid_input?(v, GraphQL::Query::NullContext.instance)
|
21
21
|
end
|
22
22
|
|
23
23
|
def coerce_isolated_input(v)
|
24
|
-
coerce_input(v, GraphQL::Query::NullContext)
|
24
|
+
coerce_input(v, GraphQL::Query::NullContext.instance)
|
25
25
|
end
|
26
26
|
|
27
27
|
def coerce_isolated_result(v)
|
28
|
-
coerce_result(v, GraphQL::Query::NullContext)
|
28
|
+
coerce_result(v, GraphQL::Query::NullContext.instance)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -205,12 +205,12 @@ module GraphQL
|
|
205
205
|
end
|
206
206
|
end
|
207
207
|
|
208
|
-
def get_argument(name, context = GraphQL::Query::NullContext)
|
208
|
+
def get_argument(name, context = GraphQL::Query::NullContext.instance)
|
209
209
|
self.class.get_argument(name, context)
|
210
210
|
end
|
211
211
|
|
212
212
|
class << self
|
213
|
-
def field_arguments(context = GraphQL::Query::NullContext)
|
213
|
+
def field_arguments(context = GraphQL::Query::NullContext.instance)
|
214
214
|
arguments(context)
|
215
215
|
end
|
216
216
|
|
@@ -218,7 +218,7 @@ module GraphQL
|
|
218
218
|
any_arguments?
|
219
219
|
end
|
220
220
|
|
221
|
-
def get_field_argument(name, context = GraphQL::Query::NullContext)
|
221
|
+
def get_field_argument(name, context = GraphQL::Query::NullContext.instance)
|
222
222
|
get_argument(name, context)
|
223
223
|
end
|
224
224
|
|
data/lib/graphql/schema/union.rb
CHANGED
@@ -10,7 +10,7 @@ module GraphQL
|
|
10
10
|
super
|
11
11
|
end
|
12
12
|
|
13
|
-
def possible_types(*types, context: GraphQL::Query::NullContext, **options)
|
13
|
+
def possible_types(*types, context: GraphQL::Query::NullContext.instance, **options)
|
14
14
|
if types.any?
|
15
15
|
types.each do |t|
|
16
16
|
assert_valid_union_member(t)
|
@@ -60,6 +60,7 @@ module GraphQL
|
|
60
60
|
def visible_type_membership?(tm, ctx); tm.visible?(ctx); end
|
61
61
|
def interface_type_memberships(obj_t, ctx); obj_t.interface_type_memberships; end
|
62
62
|
def arguments(owner, ctx); owner.arguments(ctx); end
|
63
|
+
def loadable?(type, ctx); type.visible?(ctx); end
|
63
64
|
end
|
64
65
|
end
|
65
66
|
|
@@ -84,6 +85,7 @@ module GraphQL
|
|
84
85
|
def fields(type_defn); type_defn.all_field_definitions; end # rubocop:disable Development/ContextIsPassedCop
|
85
86
|
def get_field(parent_type, field_name); @schema.get_field(parent_type, field_name); end
|
86
87
|
def reachable_type?(type_name); true; end
|
88
|
+
def loadable?(type, _ctx); true; end
|
87
89
|
def reachable_types; @schema.types.values; end # rubocop:disable Development/ContextIsPassedCop
|
88
90
|
def possible_types(type_defn); @schema.possible_types(type_defn); end
|
89
91
|
def interfaces(obj_type); obj_type.interfaces; end
|
@@ -104,7 +106,7 @@ module GraphQL
|
|
104
106
|
@types = @visible_types = @reachable_types = @visible_parent_fields =
|
105
107
|
@visible_possible_types = @visible_fields = @visible_arguments = @visible_enum_arrays =
|
106
108
|
@visible_enum_values = @visible_interfaces = @type_visibility = @type_memberships =
|
107
|
-
@visible_and_reachable_type = @unions = @unfiltered_interfaces =
|
109
|
+
@visible_and_reachable_type = @unions = @unfiltered_interfaces =
|
108
110
|
@reachable_type_set =
|
109
111
|
nil
|
110
112
|
end
|
@@ -122,6 +124,11 @@ module GraphQL
|
|
122
124
|
end
|
123
125
|
end
|
124
126
|
|
127
|
+
# @return [Boolean] True if this type is used for `loads:` but not in the schema otherwise and not _explicitly_ hidden.
|
128
|
+
def loadable?(type, _ctx)
|
129
|
+
!reachable_type_set.include?(type) && visible_type?(type)
|
130
|
+
end
|
131
|
+
|
125
132
|
# @return [GraphQL::BaseType, nil] The type named `type_name`, if it exists (else `nil`)
|
126
133
|
def get_type(type_name)
|
127
134
|
@visible_types ||= read_through do |name|
|
@@ -282,11 +289,26 @@ module GraphQL
|
|
282
289
|
next true if root_type?(type_defn) || type_defn.introspection?
|
283
290
|
|
284
291
|
if type_defn.kind.union?
|
285
|
-
|
292
|
+
possible_types(type_defn).any? && (referenced?(type_defn) || orphan_type?(type_defn))
|
286
293
|
elsif type_defn.kind.interface?
|
287
|
-
|
294
|
+
if possible_types(type_defn).any?
|
295
|
+
true
|
296
|
+
else
|
297
|
+
if @context.respond_to?(:logger) && (logger = @context.logger)
|
298
|
+
logger.debug { "Interface `#{type_defn.graphql_name}` hidden because it has no visible implementors" }
|
299
|
+
end
|
300
|
+
false
|
301
|
+
end
|
288
302
|
else
|
289
|
-
referenced?(type_defn)
|
303
|
+
if referenced?(type_defn)
|
304
|
+
true
|
305
|
+
elsif type_defn.kind.object?
|
306
|
+
# Show this object if it belongs to ...
|
307
|
+
interfaces(type_defn).any? { |t| referenced?(t) } || # an interface which is referenced in the schema
|
308
|
+
union_memberships(type_defn).any? { |t| referenced?(t) || orphan_type?(t) } # or a union which is referenced or added via orphan_types
|
309
|
+
else
|
310
|
+
false
|
311
|
+
end
|
290
312
|
end
|
291
313
|
end
|
292
314
|
|
@@ -341,29 +363,15 @@ module GraphQL
|
|
341
363
|
end
|
342
364
|
|
343
365
|
def referenced?(type_defn)
|
344
|
-
@references_to ||= @schema.references_to
|
345
366
|
graphql_name = type_defn.unwrap.graphql_name
|
346
|
-
members = @references_to
|
367
|
+
members = @schema.references_to(graphql_name)
|
347
368
|
members.any? { |m| visible?(m) }
|
348
369
|
end
|
349
370
|
|
350
|
-
NO_REFERENCES = [].freeze
|
351
|
-
|
352
371
|
def orphan_type?(type_defn)
|
353
372
|
@schema.orphan_types.include?(type_defn)
|
354
373
|
end
|
355
374
|
|
356
|
-
def visible_abstract_type?(type_defn)
|
357
|
-
type_defn.kind.object? && (
|
358
|
-
interfaces(type_defn).any? ||
|
359
|
-
union_memberships(type_defn).any?
|
360
|
-
)
|
361
|
-
end
|
362
|
-
|
363
|
-
def visible_possible_types?(type_defn)
|
364
|
-
possible_types(type_defn).any? { |t| visible_and_reachable_type?(t) }
|
365
|
-
end
|
366
|
-
|
367
375
|
def visible?(member)
|
368
376
|
@visibility_cache[member]
|
369
377
|
end
|
@@ -402,54 +410,62 @@ module GraphQL
|
|
402
410
|
end
|
403
411
|
end
|
404
412
|
|
413
|
+
included_interface_possible_types_set = Set.new
|
414
|
+
|
405
415
|
until unvisited_types.empty?
|
406
416
|
type = unvisited_types.pop
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
417
|
+
visit_type(type, unvisited_types, @reachable_type_set, rt_hash, included_interface_possible_types_set, include_interface_possible_types: false)
|
418
|
+
end
|
419
|
+
|
420
|
+
@reachable_type_set
|
421
|
+
end
|
422
|
+
|
423
|
+
def visit_type(type, unvisited_types, visited_type_set, type_by_name_hash, included_interface_possible_types_set, include_interface_possible_types:)
|
424
|
+
if visited_type_set.add?(type) || (include_interface_possible_types && type.kind.interface? && included_interface_possible_types_set.add?(type))
|
425
|
+
type_by_name = type_by_name_hash[type.graphql_name] ||= type
|
426
|
+
if type_by_name != type
|
427
|
+
name_1, name_2 = [type.inspect, type_by_name.inspect].sort
|
428
|
+
raise DuplicateNamesError.new(
|
429
|
+
duplicated_name: type.graphql_name, duplicated_definition_1: name_1, duplicated_definition_2: name_2
|
430
|
+
)
|
431
|
+
end
|
432
|
+
if type.kind.input_object?
|
433
|
+
# recurse into visible arguments
|
434
|
+
arguments(type).each do |argument|
|
435
|
+
argument_type = argument.type.unwrap
|
436
|
+
unvisited_types << argument_type
|
413
437
|
end
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
# recurse into visible
|
422
|
-
|
423
|
-
unvisited_types <<
|
438
|
+
elsif type.kind.union?
|
439
|
+
# recurse into visible possible types
|
440
|
+
possible_types(type).each do |possible_type|
|
441
|
+
unvisited_types << possible_type
|
442
|
+
end
|
443
|
+
elsif type.kind.fields?
|
444
|
+
if type.kind.object?
|
445
|
+
# recurse into visible implemented interfaces
|
446
|
+
interfaces(type).each do |interface|
|
447
|
+
unvisited_types << interface
|
424
448
|
end
|
425
|
-
elsif
|
426
|
-
|
427
|
-
|
428
|
-
possible_types(type).each do |possible_type|
|
429
|
-
unvisited_types << possible_type
|
430
|
-
end
|
431
|
-
elsif type.kind.object?
|
432
|
-
# recurse into visible implemented interfaces
|
433
|
-
interfaces(type).each do |interface|
|
434
|
-
unvisited_types << interface
|
435
|
-
end
|
449
|
+
elsif include_interface_possible_types
|
450
|
+
possible_types(type).each do |pt|
|
451
|
+
unvisited_types << pt
|
436
452
|
end
|
453
|
+
end
|
454
|
+
# Don't visit interface possible types -- it's not enough to justify visibility
|
437
455
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
456
|
+
# recurse into visible fields
|
457
|
+
fields(type).each do |field|
|
458
|
+
field_type = field.type.unwrap
|
459
|
+
# In this case, if it's an interface, we want to include
|
460
|
+
visit_type(field_type, unvisited_types, visited_type_set, type_by_name_hash, included_interface_possible_types_set, include_interface_possible_types: true)
|
461
|
+
# recurse into visible arguments
|
462
|
+
arguments(field).each do |argument|
|
463
|
+
argument_type = argument.type.unwrap
|
464
|
+
unvisited_types << argument_type
|
447
465
|
end
|
448
466
|
end
|
449
467
|
end
|
450
468
|
end
|
451
|
-
|
452
|
-
@reachable_type_set
|
453
469
|
end
|
454
470
|
end
|
455
471
|
end
|