@@ -59,10 +59,14 @@ function reasonMessage(reason: ConflictReasonMessage): string {
59
59
export function OverlappingFieldsCanBeMergedRule (
60
60
context : ValidationContext ,
61
61
) : ASTVisitor {
62
- // A memoization for when two fragments are compared "between" each other for
63
- // conflicts. Two fragments may be compared many times, so memoizing this can
64
- // dramatically improve the performance of this validator.
65
- const comparedFragmentPairs = new PairSet ( ) ;
62
+ // A memoization for when fields and a fragment or two fragments are compared
63
+ // "between" each other for conflicts. Comparisons made be made many times,
64
+ // so memoizing this can dramatically improve the performance of this validator.
65
+ const comparedFieldsAndFragmentPairs = new PairSet <
66
+ NodeAndDefCollection ,
67
+ string
68
+ > ( ( a , _ ) => typeof a === 'string' ) ;
69
+ const comparedFragmentPairs = new PairSet < string , string > ( ( a , b ) => a < b ) ;
66
70
67
71
// A cache for the "field map" and list of fragment names found in any given
68
72
// selection set. Selection sets may be asked for this information multiple
@@ -74,6 +78,7 @@ export function OverlappingFieldsCanBeMergedRule(
74
78
const conflicts = findConflictsWithinSelectionSet (
75
79
context ,
76
80
cachedFieldsAndFragmentNames ,
81
+ comparedFieldsAndFragmentPairs ,
77
82
comparedFragmentPairs ,
78
83
context . getParentType ( ) ,
79
84
selectionSet ,
@@ -168,7 +173,8 @@ type FieldsAndFragmentNames = readonly [NodeAndDefCollection, FragmentNames];
168
173
function findConflictsWithinSelectionSet (
169
174
context : ValidationContext ,
170
175
cachedFieldsAndFragmentNames : Map < SelectionSetNode , FieldsAndFragmentNames > ,
171
- comparedFragmentPairs : PairSet ,
176
+ comparedFieldsAndFragmentPairs : PairSet < NodeAndDefCollection , string > ,
177
+ comparedFragmentPairs : PairSet < string , string > ,
172
178
parentType : Maybe < GraphQLNamedType > ,
173
179
selectionSet : SelectionSetNode ,
174
180
) : Array < Conflict > {
@@ -187,6 +193,7 @@ function findConflictsWithinSelectionSet(
187
193
context ,
188
194
conflicts ,
189
195
cachedFieldsAndFragmentNames ,
196
+ comparedFieldsAndFragmentPairs ,
190
197
comparedFragmentPairs ,
191
198
fieldMap ,
192
199
) ;
@@ -199,6 +206,7 @@ function findConflictsWithinSelectionSet(
199
206
context ,
200
207
conflicts ,
201
208
cachedFieldsAndFragmentNames ,
209
+ comparedFieldsAndFragmentPairs ,
202
210
comparedFragmentPairs ,
203
211
false ,
204
212
fieldMap ,
@@ -213,6 +221,7 @@ function findConflictsWithinSelectionSet(
213
221
context ,
214
222
conflicts ,
215
223
cachedFieldsAndFragmentNames ,
224
+ comparedFieldsAndFragmentPairs ,
216
225
comparedFragmentPairs ,
217
226
false ,
218
227
fragmentNames [ i ] ,
@@ -230,17 +239,28 @@ function collectConflictsBetweenFieldsAndFragment(
230
239
context : ValidationContext ,
231
240
conflicts : Array < Conflict > ,
232
241
cachedFieldsAndFragmentNames : Map < SelectionSetNode , FieldsAndFragmentNames > ,
233
- comparedFragmentPairs : PairSet ,
242
+ comparedFieldsAndFragmentPairs : PairSet < NodeAndDefCollection , string > ,
243
+ comparedFragmentPairs : PairSet < string , string > ,
234
244
areMutuallyExclusive : boolean ,
235
245
fieldMap : NodeAndDefCollection ,
236
246
fragmentName : string ,
237
247
) : void {
238
248
// Memoize so the fields and fragments are not compared for conflicts more
239
249
// than once.
240
- if ( comparedFragmentPairs . has ( fieldMap , fragmentName , areMutuallyExclusive ) ) {
250
+ if (
251
+ comparedFieldsAndFragmentPairs . has (
252
+ fieldMap ,
253
+ fragmentName ,
254
+ areMutuallyExclusive ,
255
+ )
256
+ ) {
241
257
return ;
242
258
}
243
- comparedFragmentPairs . add ( fieldMap , fragmentName , areMutuallyExclusive ) ;
259
+ comparedFieldsAndFragmentPairs . add (
260
+ fieldMap ,
261
+ fragmentName ,
262
+ areMutuallyExclusive ,
263
+ ) ;
244
264
245
265
const fragment = context . getFragment ( fragmentName ) ;
246
266
if ( ! fragment ) {
@@ -265,6 +285,7 @@ function collectConflictsBetweenFieldsAndFragment(
265
285
context ,
266
286
conflicts ,
267
287
cachedFieldsAndFragmentNames ,
288
+ comparedFieldsAndFragmentPairs ,
268
289
comparedFragmentPairs ,
269
290
areMutuallyExclusive ,
270
291
fieldMap ,
@@ -278,6 +299,7 @@ function collectConflictsBetweenFieldsAndFragment(
278
299
context ,
279
300
conflicts ,
280
301
cachedFieldsAndFragmentNames ,
302
+ comparedFieldsAndFragmentPairs ,
281
303
comparedFragmentPairs ,
282
304
areMutuallyExclusive ,
283
305
fieldMap ,
@@ -292,7 +314,8 @@ function collectConflictsBetweenFragments(
292
314
context : ValidationContext ,
293
315
conflicts : Array < Conflict > ,
294
316
cachedFieldsAndFragmentNames : Map < SelectionSetNode , FieldsAndFragmentNames > ,
295
- comparedFragmentPairs : PairSet ,
317
+ comparedFieldsAndFragmentPairs : PairSet < NodeAndDefCollection , string > ,
318
+ comparedFragmentPairs : PairSet < string , string > ,
296
319
areMutuallyExclusive : boolean ,
297
320
fragmentName1 : string ,
298
321
fragmentName2 : string ,
@@ -339,6 +362,7 @@ function collectConflictsBetweenFragments(
339
362
context ,
340
363
conflicts ,
341
364
cachedFieldsAndFragmentNames ,
365
+ comparedFieldsAndFragmentPairs ,
342
366
comparedFragmentPairs ,
343
367
areMutuallyExclusive ,
344
368
fieldMap1 ,
@@ -352,6 +376,7 @@ function collectConflictsBetweenFragments(
352
376
context ,
353
377
conflicts ,
354
378
cachedFieldsAndFragmentNames ,
379
+ comparedFieldsAndFragmentPairs ,
355
380
comparedFragmentPairs ,
356
381
areMutuallyExclusive ,
357
382
fragmentName1 ,
@@ -366,6 +391,7 @@ function collectConflictsBetweenFragments(
366
391
context ,
367
392
conflicts ,
368
393
cachedFieldsAndFragmentNames ,
394
+ comparedFieldsAndFragmentPairs ,
369
395
comparedFragmentPairs ,
370
396
areMutuallyExclusive ,
371
397
referencedFragmentName1 ,
@@ -380,7 +406,8 @@ function collectConflictsBetweenFragments(
380
406
function findConflictsBetweenSubSelectionSets (
381
407
context : ValidationContext ,
382
408
cachedFieldsAndFragmentNames : Map < SelectionSetNode , FieldsAndFragmentNames > ,
383
- comparedFragmentPairs : PairSet ,
409
+ comparedFieldsAndFragmentPairs : PairSet < NodeAndDefCollection , string > ,
410
+ comparedFragmentPairs : PairSet < string , string > ,
384
411
areMutuallyExclusive : boolean ,
385
412
parentType1 : Maybe < GraphQLNamedType > ,
386
413
selectionSet1 : SelectionSetNode ,
@@ -407,6 +434,7 @@ function findConflictsBetweenSubSelectionSets(
407
434
context ,
408
435
conflicts ,
409
436
cachedFieldsAndFragmentNames ,
437
+ comparedFieldsAndFragmentPairs ,
410
438
comparedFragmentPairs ,
411
439
areMutuallyExclusive ,
412
440
fieldMap1 ,
@@ -420,6 +448,7 @@ function findConflictsBetweenSubSelectionSets(
420
448
context ,
421
449
conflicts ,
422
450
cachedFieldsAndFragmentNames ,
451
+ comparedFieldsAndFragmentPairs ,
423
452
comparedFragmentPairs ,
424
453
areMutuallyExclusive ,
425
454
fieldMap1 ,
@@ -434,6 +463,7 @@ function findConflictsBetweenSubSelectionSets(
434
463
context ,
435
464
conflicts ,
436
465
cachedFieldsAndFragmentNames ,
466
+ comparedFieldsAndFragmentPairs ,
437
467
comparedFragmentPairs ,
438
468
areMutuallyExclusive ,
439
469
fieldMap2 ,
@@ -450,6 +480,7 @@ function findConflictsBetweenSubSelectionSets(
450
480
context ,
451
481
conflicts ,
452
482
cachedFieldsAndFragmentNames ,
483
+ comparedFieldsAndFragmentPairs ,
453
484
comparedFragmentPairs ,
454
485
areMutuallyExclusive ,
455
486
fragmentName1 ,
@@ -465,7 +496,8 @@ function collectConflictsWithin(
465
496
context : ValidationContext ,
466
497
conflicts : Array < Conflict > ,
467
498
cachedFieldsAndFragmentNames : Map < SelectionSetNode , FieldsAndFragmentNames > ,
468
- comparedFragmentPairs : PairSet ,
499
+ comparedFieldsAndFragmentPairs : PairSet < NodeAndDefCollection , string > ,
500
+ comparedFragmentPairs : PairSet < string , string > ,
469
501
fieldMap : NodeAndDefCollection ,
470
502
) : void {
471
503
// A field map is a keyed collection, where each key represents a response
@@ -482,6 +514,7 @@ function collectConflictsWithin(
482
514
const conflict = findConflict (
483
515
context ,
484
516
cachedFieldsAndFragmentNames ,
517
+ comparedFieldsAndFragmentPairs ,
485
518
comparedFragmentPairs ,
486
519
false , // within one collection is never mutually exclusive
487
520
responseName ,
@@ -506,7 +539,8 @@ function collectConflictsBetween(
506
539
context : ValidationContext ,
507
540
conflicts : Array < Conflict > ,
508
541
cachedFieldsAndFragmentNames : Map < SelectionSetNode , FieldsAndFragmentNames > ,
509
- comparedFragmentPairs : PairSet ,
542
+ comparedFieldsAndFragmentPairs : PairSet < NodeAndDefCollection , string > ,
543
+ comparedFragmentPairs : PairSet < string , string > ,
510
544
parentFieldsAreMutuallyExclusive : boolean ,
511
545
fieldMap1 : NodeAndDefCollection ,
512
546
fieldMap2 : NodeAndDefCollection ,
@@ -524,6 +558,7 @@ function collectConflictsBetween(
524
558
const conflict = findConflict (
525
559
context ,
526
560
cachedFieldsAndFragmentNames ,
561
+ comparedFieldsAndFragmentPairs ,
527
562
comparedFragmentPairs ,
528
563
parentFieldsAreMutuallyExclusive ,
529
564
responseName ,
@@ -544,7 +579,8 @@ function collectConflictsBetween(
544
579
function findConflict (
545
580
context : ValidationContext ,
546
581
cachedFieldsAndFragmentNames : Map < SelectionSetNode , FieldsAndFragmentNames > ,
547
- comparedFragmentPairs : PairSet ,
582
+ comparedFieldsAndFragmentPairs : PairSet < NodeAndDefCollection , string > ,
583
+ comparedFragmentPairs : PairSet < string , string > ,
548
584
parentFieldsAreMutuallyExclusive : boolean ,
549
585
responseName : string ,
550
586
field1 : NodeAndDef ,
@@ -615,6 +651,7 @@ function findConflict(
615
651
const conflicts = findConflictsBetweenSubSelectionSets (
616
652
context ,
617
653
cachedFieldsAndFragmentNames ,
654
+ comparedFieldsAndFragmentPairs ,
618
655
comparedFragmentPairs ,
619
656
areMutuallyExclusive ,
620
657
getNamedType ( type1 ) ,
@@ -806,20 +843,20 @@ function subfieldConflicts(
806
843
/**
807
844
* A way to keep track of pairs of things when the ordering of the pair does not matter.
808
845
*/
809
- class PairSet {
810
- _data : Map < string | NodeAndDefCollection , Map < string , boolean > > ;
846
+ class PairSet < T , U > {
847
+ _data : Map < T | U , Map < T | U , boolean > > ;
848
+ _orderer : ( a : T | U , b : T | U ) => [ T | U , T | U ] ;
811
849
812
- constructor ( ) {
850
+ constructor ( comparator : ( a : T | U , b : T | U ) => boolean ) {
813
851
this . _data = new Map ( ) ;
852
+ this . _orderer = ( a : T | U , b : T | U ) =>
853
+ comparator ( a , b ) ? [ a , b ] : [ b , a ] ;
814
854
}
815
855
816
- has (
817
- a : string | NodeAndDefCollection ,
818
- b : string ,
819
- areMutuallyExclusive : boolean ,
820
- ) : boolean {
821
- const [ key1 , key2 ] =
822
- typeof a !== 'string' ? [ a , b ] : a < b ? [ a , b ] : [ b , a ] ;
856
+ has ( a : T , b : U , areMutuallyExclusive : boolean ) : boolean ;
857
+ has ( a : U , b : T , areMutuallyExclusive : boolean ) : boolean ;
858
+ has ( a : T | U , b : T | U , areMutuallyExclusive : boolean ) : boolean {
859
+ const [ key1 , key2 ] = this . _orderer ( a , b ) ;
823
860
824
861
const result = this . _data . get ( key1 ) ?. get ( key2 ) ;
825
862
if ( result === undefined ) {
@@ -832,13 +869,10 @@ class PairSet {
832
869
return areMutuallyExclusive ? true : areMutuallyExclusive === result ;
833
870
}
834
871
835
- add (
836
- a : string | NodeAndDefCollection ,
837
- b : string ,
838
- areMutuallyExclusive : boolean ,
839
- ) : void {
840
- const [ key1 , key2 ] =
841
- typeof a !== 'string' ? [ a , b ] : a < b ? [ a , b ] : [ b , a ] ;
872
+ add ( a : T , b : U , areMutuallyExclusive : boolean ) : void ;
873
+ add ( a : U , b : T , areMutuallyExclusive : boolean ) : void ;
874
+ add ( a : T | U , b : T | U , areMutuallyExclusive : boolean ) : void {
875
+ const [ key1 , key2 ] = this . _orderer ( a , b ) ;
842
876
843
877
const map = this . _data . get ( key1 ) ;
844
878
if ( map === undefined ) {
0 commit comments