overlappingFieldsCanBeMergedRule function
Visitor
overlappingFieldsCanBeMergedRule(
- ValidationCtx context
Overlapping fields can be merged
A selection set is only valid if all fields (including spreading any fragments) either correspond to distinct response names or can be merged without ambiguity.
See https://spec.graphql.org/draft/#sec-Field-Selection-Merging
Implementation
Visitor overlappingFieldsCanBeMergedRule(
ValidationCtx context,
) {
// A memoization for when two fragments are compared "between" each other for
// conflicts. Two fragments may be compared many times, so memoizing this can
// dramatically improve the performance of this validator.
final comparedFragmentPairs = PairSet();
// A cache for the "field map" and list of fragment names found in any given
// selection set. Selection sets may be asked for this information multiple
// times, so this improves the performance of this validator.
final Map<SelectionSetNode, FieldsAndFragmentNames>
/// [Map.identity] required since the span is not used in [Node.==]
/// and, right now, [SelectionSetNode.span] is null anyway
cachedFieldsAndFragmentNames = Map.identity();
final visitor = TypedVisitor();
visitor.add<SelectionSetNode>((selectionSet) {
final conflicts = findConflictsWithinSelectionSet(
context,
cachedFieldsAndFragmentNames,
comparedFragmentPairs,
context.typeInfo.getParentType(),
selectionSet,
);
for (final c in conflicts) {
final reasonMsg = _reasonMessage(c.reason);
context.reportError(
GraphQLError(
'Fields "${c.reason.name}" conflict because ${reasonMsg}.'
' Use different aliases on the fields to fetch both if this was intentional.',
locations: List.of(
c.fields1.followedBy(c.fields2).map(
(e) => GraphQLErrorLocation.fromSourceLocation(
(e.span ?? e.name.span)!.start,
),
),
),
extensions: _overlappingFieldsCanBeMergedSpec.extensions(),
),
);
}
});
return visitor;
}