NoUnusedFragments.js.flow 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. // @flow strict
  2. import { GraphQLError } from '../../error/GraphQLError';
  3. import { type ASTVisitor } from '../../language/visitor';
  4. import { type ASTValidationContext } from '../ValidationContext';
  5. export function unusedFragMessage(fragName: string): string {
  6. return `Fragment "${fragName}" is never used.`;
  7. }
  8. /**
  9. * No unused fragments
  10. *
  11. * A GraphQL document is only valid if all fragment definitions are spread
  12. * within operations, or spread within other fragments spread within operations.
  13. */
  14. export function NoUnusedFragments(context: ASTValidationContext): ASTVisitor {
  15. const operationDefs = [];
  16. const fragmentDefs = [];
  17. return {
  18. OperationDefinition(node) {
  19. operationDefs.push(node);
  20. return false;
  21. },
  22. FragmentDefinition(node) {
  23. fragmentDefs.push(node);
  24. return false;
  25. },
  26. Document: {
  27. leave() {
  28. const fragmentNameUsed = Object.create(null);
  29. for (const operation of operationDefs) {
  30. for (const fragment of context.getRecursivelyReferencedFragments(
  31. operation,
  32. )) {
  33. fragmentNameUsed[fragment.name.value] = true;
  34. }
  35. }
  36. for (const fragmentDef of fragmentDefs) {
  37. const fragName = fragmentDef.name.value;
  38. if (fragmentNameUsed[fragName] !== true) {
  39. context.reportError(
  40. new GraphQLError(unusedFragMessage(fragName), fragmentDef),
  41. );
  42. }
  43. }
  44. },
  45. },
  46. };
  47. }