123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- // @flow strict
- import inspect from '../../jsutils/inspect';
- import { GraphQLError } from '../../error/GraphQLError';
- import { type ASTVisitor } from '../../language/visitor';
- import { isCompositeType } from '../../type/definition';
- import { typeFromAST } from '../../utilities/typeFromAST';
- import { doTypesOverlap } from '../../utilities/typeComparators';
- import { type ValidationContext } from '../ValidationContext';
- export function typeIncompatibleSpreadMessage(
- fragName: string,
- parentType: string,
- fragType: string,
- ): string {
- return `Fragment "${fragName}" cannot be spread here as objects of type "${parentType}" can never be of type "${fragType}".`;
- }
- export function typeIncompatibleAnonSpreadMessage(
- parentType: string,
- fragType: string,
- ): string {
- return `Fragment cannot be spread here as objects of type "${parentType}" can never be of type "${fragType}".`;
- }
- /**
- * Possible fragment spread
- *
- * A fragment spread is only valid if the type condition could ever possibly
- * be true: if there is a non-empty intersection of the possible parent types,
- * and possible types which pass the type condition.
- */
- export function PossibleFragmentSpreads(
- context: ValidationContext,
- ): ASTVisitor {
- return {
- InlineFragment(node) {
- const fragType = context.getType();
- const parentType = context.getParentType();
- if (
- isCompositeType(fragType) &&
- isCompositeType(parentType) &&
- !doTypesOverlap(context.getSchema(), fragType, parentType)
- ) {
- context.reportError(
- new GraphQLError(
- typeIncompatibleAnonSpreadMessage(
- inspect(parentType),
- inspect(fragType),
- ),
- node,
- ),
- );
- }
- },
- FragmentSpread(node) {
- const fragName = node.name.value;
- const fragType = getFragmentType(context, fragName);
- const parentType = context.getParentType();
- if (
- fragType &&
- parentType &&
- !doTypesOverlap(context.getSchema(), fragType, parentType)
- ) {
- context.reportError(
- new GraphQLError(
- typeIncompatibleSpreadMessage(
- fragName,
- inspect(parentType),
- inspect(fragType),
- ),
- node,
- ),
- );
- }
- },
- };
- }
- function getFragmentType(context, name) {
- const frag = context.getFragment(name);
- if (frag) {
- const type = typeFromAST(context.getSchema(), frag.typeCondition);
- if (isCompositeType(type)) {
- return type;
- }
- }
- }
|