@@ -40,8 +40,8 @@ def conflicts_within_selection_set(node, parent_type)
40
40
41
41
fragment_spreads . each_with_index do |fragment_spread , i |
42
42
are_mutually_exclusive = mutually_exclusive? (
43
- fragment_spread . parents . last ,
44
- parent_type
43
+ fragment_spread . parents ,
44
+ [ parent_type ]
45
45
)
46
46
47
47
# (B) Then find conflicts between these fields and those represented by
@@ -58,8 +58,8 @@ def conflicts_within_selection_set(node, parent_type)
58
58
# item in that same list (except for itself).
59
59
fragment_spreads [ i + 1 ..-1 ] . each do |fragment_spread2 |
60
60
are_mutually_exclusive = mutually_exclusive? (
61
- fragment_spread . parents . last ,
62
- fragment_spread2 . parents . last
61
+ fragment_spread . parents ,
62
+ fragment_spread2 . parents
63
63
)
64
64
65
65
find_conflicts_between_fragments (
@@ -103,7 +103,7 @@ def find_conflicts_between_fragments(fragment_spread1, fragment_spread2, mutuall
103
103
)
104
104
fragment_fields2 , fragment_spreads2 = fields_and_fragments_from_selection (
105
105
fragment2 ,
106
- parents : [ *fragment_spread2 , fragment_type2 ]
106
+ parents : [ *fragment_spread2 . parents , fragment_type2 ]
107
107
)
108
108
109
109
# (F) First, find all conflicts between these two collections of fields
@@ -187,7 +187,7 @@ def find_conflict(response_key, field1, field2, mutually_exclusive: false)
187
187
node2 = field2 . node
188
188
189
189
are_mutually_exclusive = mutually_exclusive ||
190
- mutually_exclusive? ( parent_type1 , parent_type2 )
190
+ mutually_exclusive? ( field1 . parents , field2 . parents )
191
191
192
192
if !are_mutually_exclusive
193
193
if node1 . name != node2 . name
@@ -215,14 +215,17 @@ def find_conflicts_between_sub_selection_sets(field1, field2, mutually_exclusive
215
215
216
216
return_type1 = field1 . definition . type . unwrap
217
217
return_type2 = field2 . definition . type . unwrap
218
+ parents1 = [ *field1 . parents , return_type1 ]
219
+ parents2 = [ *field2 . parents , return_type2 ]
218
220
219
221
fields , fragment_spreads = fields_and_fragments_from_selection (
220
222
field1 . node ,
221
- parents : [ *field1 . parents , return_type1 ] )
223
+ parents : parents1
224
+ )
222
225
223
226
fields2 , fragment_spreads2 = fields_and_fragments_from_selection (
224
227
field2 . node ,
225
- parents : [ * field2 . parents , return_type2 ]
228
+ parents : parents2
226
229
)
227
230
228
231
# (H) First, collect all conflicts between these two collections of field.
@@ -231,30 +234,20 @@ def find_conflicts_between_sub_selection_sets(field1, field2, mutually_exclusive
231
234
# (I) Then collect conflicts between the first collection of fields and
232
235
# those referenced by each fragment name associated with the second.
233
236
fragment_spreads2 . each do |fragment_spread |
234
- fragment_is_mutually_exclusive = mutually_exclusive? (
235
- return_type1 ,
236
- fragment_spread . parents . last
237
- )
238
-
239
237
find_conflicts_between_fields_and_fragment (
240
238
fragment_spread ,
241
239
fields ,
242
- mutually_exclusive : mutually_exclusive || fragment_is_mutually_exclusive ,
240
+ mutually_exclusive : mutually_exclusive ,
243
241
)
244
242
end
245
243
246
244
# (I) Then collect conflicts between the second collection of fields and
247
245
# those referenced by each fragment name associated with the first.
248
246
fragment_spreads . each do |fragment_spread |
249
- fragment_is_mutually_exclusive = mutually_exclusive? (
250
- return_type2 ,
251
- fragment_spread . parents . last
252
- )
253
-
254
247
find_conflicts_between_fields_and_fragment (
255
248
fragment_spread ,
256
249
fields2 ,
257
- mutually_exclusive : mutually_exclusive || fragment_is_mutually_exclusive ,
250
+ mutually_exclusive : mutually_exclusive ,
258
251
)
259
252
end
260
253
@@ -263,15 +256,10 @@ def find_conflicts_between_sub_selection_sets(field1, field2, mutually_exclusive
263
256
# names to each item in the second set of names.
264
257
fragment_spreads . each do |frag1 |
265
258
fragment_spreads2 . each do |frag2 |
266
- fragments_are_mutually_exclusive = mutually_exclusive? (
267
- frag1 . parents . last ,
268
- frag2 . parents . last
269
- )
270
-
271
259
find_conflicts_between_fragments (
272
260
frag1 ,
273
261
frag2 ,
274
- mutually_exclusive : mutually_exclusive || fragments_are_mutually_exclusive ,
262
+ mutually_exclusive : mutually_exclusive
275
263
)
276
264
end
277
265
end
@@ -296,11 +284,9 @@ def find_conflicts_between(response_keys, response_keys2, mutually_exclusive:)
296
284
end
297
285
298
286
def fields_and_fragments_from_selection ( node , parents :)
299
- @fields_and_fragments_from_node [ node ] ||= begin
300
- fields , fragment_spreads = find_fields_and_fragments ( node . selections , parents : parents )
301
- response_keys = fields . group_by { |f | f . node . alias || f . node . name }
302
- [ response_keys , fragment_spreads ]
303
- end
287
+ fields , fragment_spreads = find_fields_and_fragments ( node . selections , parents : parents )
288
+ response_keys = fields . group_by { |f | f . node . alias || f . node . name }
289
+ [ response_keys , fragment_spreads ]
304
290
end
305
291
306
292
def find_fields_and_fragments ( selections , parents :, fields : [ ] , fragment_spreads : [ ] )
@@ -348,8 +334,26 @@ def compared_fragments_key(frag1, frag2, exclusive)
348
334
"#{ [ frag1 , frag2 ] . sort . join ( '-' ) } -#{ exclusive } "
349
335
end
350
336
351
- def mutually_exclusive? ( type1 , type2 )
352
- type1 != type2 && type1 . kind . object? && type2 . kind . object?
337
+ # Given two list of parents, find out if they are mutually exclusive
338
+ def mutually_exclusive? ( parents1 , parents2 )
339
+ i = 0
340
+ j = 0
341
+
342
+ while i <= parents1 . size - 1 && j <= parents2 . size - 1 do
343
+ type1 = parents1 [ i ]
344
+ type2 = parents2 [ j ]
345
+
346
+ # If the types we're comparing are both different object types,
347
+ # they have to be mutually exclusive.
348
+ if type1 != type2 && type1 . kind . object? && type2 . kind . object?
349
+ return true
350
+ end
351
+
352
+ i = i + 1 if i < parents1 . size - 1
353
+ j = j + 1 if j < parents2 . size - 1
354
+ end
355
+
356
+ false
353
357
end
354
358
end
355
359
end
0 commit comments