Skip to content

Commit 94b621e

Browse files
Marc-Andre Girouxrmosolgo
authored andcommitted
exclusivity logic, removed caching for now
1 parent 1cdd8d1 commit 94b621e

File tree

2 files changed

+37
-34
lines changed

2 files changed

+37
-34
lines changed

lib/graphql/static_validation/rules/fields_will_merge.rb

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ def conflicts_within_selection_set(node, parent_type)
4040

4141
fragment_spreads.each_with_index do |fragment_spread, i|
4242
are_mutually_exclusive = mutually_exclusive?(
43-
fragment_spread.parents.last,
44-
parent_type
43+
fragment_spread.parents,
44+
[parent_type]
4545
)
4646

4747
# (B) Then find conflicts between these fields and those represented by
@@ -58,8 +58,8 @@ def conflicts_within_selection_set(node, parent_type)
5858
# item in that same list (except for itself).
5959
fragment_spreads[i + 1..-1].each do |fragment_spread2|
6060
are_mutually_exclusive = mutually_exclusive?(
61-
fragment_spread.parents.last,
62-
fragment_spread2.parents.last
61+
fragment_spread.parents,
62+
fragment_spread2.parents
6363
)
6464

6565
find_conflicts_between_fragments(
@@ -103,7 +103,7 @@ def find_conflicts_between_fragments(fragment_spread1, fragment_spread2, mutuall
103103
)
104104
fragment_fields2, fragment_spreads2 = fields_and_fragments_from_selection(
105105
fragment2,
106-
parents: [*fragment_spread2, fragment_type2]
106+
parents: [*fragment_spread2.parents, fragment_type2]
107107
)
108108

109109
# (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)
187187
node2 = field2.node
188188

189189
are_mutually_exclusive = mutually_exclusive ||
190-
mutually_exclusive?(parent_type1, parent_type2)
190+
mutually_exclusive?(field1.parents, field2.parents)
191191

192192
if !are_mutually_exclusive
193193
if node1.name != node2.name
@@ -215,14 +215,17 @@ def find_conflicts_between_sub_selection_sets(field1, field2, mutually_exclusive
215215

216216
return_type1 = field1.definition.type.unwrap
217217
return_type2 = field2.definition.type.unwrap
218+
parents1 = [*field1.parents, return_type1]
219+
parents2 = [*field2.parents, return_type2]
218220

219221
fields, fragment_spreads = fields_and_fragments_from_selection(
220222
field1.node,
221-
parents: [*field1.parents, return_type1])
223+
parents: parents1
224+
)
222225

223226
fields2, fragment_spreads2 = fields_and_fragments_from_selection(
224227
field2.node,
225-
parents: [*field2.parents, return_type2]
228+
parents: parents2
226229
)
227230

228231
# (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
231234
# (I) Then collect conflicts between the first collection of fields and
232235
# those referenced by each fragment name associated with the second.
233236
fragment_spreads2.each do |fragment_spread|
234-
fragment_is_mutually_exclusive = mutually_exclusive?(
235-
return_type1,
236-
fragment_spread.parents.last
237-
)
238-
239237
find_conflicts_between_fields_and_fragment(
240238
fragment_spread,
241239
fields,
242-
mutually_exclusive: mutually_exclusive || fragment_is_mutually_exclusive,
240+
mutually_exclusive: mutually_exclusive,
243241
)
244242
end
245243

246244
# (I) Then collect conflicts between the second collection of fields and
247245
# those referenced by each fragment name associated with the first.
248246
fragment_spreads.each do |fragment_spread|
249-
fragment_is_mutually_exclusive = mutually_exclusive?(
250-
return_type2,
251-
fragment_spread.parents.last
252-
)
253-
254247
find_conflicts_between_fields_and_fragment(
255248
fragment_spread,
256249
fields2,
257-
mutually_exclusive: mutually_exclusive || fragment_is_mutually_exclusive,
250+
mutually_exclusive: mutually_exclusive,
258251
)
259252
end
260253

@@ -263,15 +256,10 @@ def find_conflicts_between_sub_selection_sets(field1, field2, mutually_exclusive
263256
# names to each item in the second set of names.
264257
fragment_spreads.each do |frag1|
265258
fragment_spreads2.each do |frag2|
266-
fragments_are_mutually_exclusive = mutually_exclusive?(
267-
frag1.parents.last,
268-
frag2.parents.last
269-
)
270-
271259
find_conflicts_between_fragments(
272260
frag1,
273261
frag2,
274-
mutually_exclusive: mutually_exclusive || fragments_are_mutually_exclusive,
262+
mutually_exclusive: mutually_exclusive
275263
)
276264
end
277265
end
@@ -296,11 +284,9 @@ def find_conflicts_between(response_keys, response_keys2, mutually_exclusive:)
296284
end
297285

298286
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]
304290
end
305291

306292
def find_fields_and_fragments(selections, parents:, fields: [], fragment_spreads: [])
@@ -348,8 +334,26 @@ def compared_fragments_key(frag1, frag2, exclusive)
348334
"#{[frag1, frag2].sort.join('-')}-#{exclusive}"
349335
end
350336

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
353357
end
354358
end
355359
end

spec/graphql/static_validation/rules/fields_will_merge_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,6 @@
527527
}
528528
|}
529529

530-
focus
531530
it "passes rule" do
532531
assert_equal [], errors
533532
end

0 commit comments

Comments
 (0)