protected function collectConflictsBetweenFragments(
        ComparisonContext $context,
        string $fragmentNameA,
        string $fragmentNameB,
        bool $areMutuallyExclusive
    ): void {
        // No need to compare a fragment to itself.
        if ($fragmentNameA === $fragmentNameB) {
            return;
        }

        // Memoize so two fragments are not compared for conflicts more than once.
        if ($this->comparedFragmentPairs->has($fragmentNameA, $fragmentNameB, $areMutuallyExclusive)) {
            return;
        }

        $this->comparedFragmentPairs->add($fragmentNameA, $fragmentNameB, $areMutuallyExclusive);

        $fragmentA = $this->getContext()->getFragment($fragmentNameA);
        $fragmentB = $this->getContext()->getFragment($fragmentNameB);

        if (null === $fragmentA || null === $fragmentB) {
            return;
        }

        $contextA = $this->getReferencedFieldsAndFragmentNames($fragmentA);
        $contextB = $this->getReferencedFieldsAndFragmentNames($fragmentB);

        // (F) First, collect all conflicts between these two collections of fields
        // (not including any nested fragments).
        $this->collectConflictsBetween(
            $context,
            $contextA->getFieldMap(),
            $contextB->getFieldMap(),
            $areMutuallyExclusive
        );

        $fragmentNamesB = $contextB->getFragmentNames();

        // (G) Then collect conflicts between the first fragment and any nested
        // fragments spread in the second fragment.
        if (!empty($fragmentNamesB)) {
            $fragmentNamesBCount = \count($fragmentNamesB);

            /** @noinspection ForeachInvariantsInspection */
            for ($j = 0; $j < $fragmentNamesBCount; $j++) {
                $this->collectConflictsBetweenFragments(
                    $context,
                    $fragmentNameA,
                    $fragmentNamesB[$j],
                    $areMutuallyExclusive
                );
            }
        }

        $fragmentNamesA = $contextA->getFragmentNames();

        // (G) Then collect conflicts between the second fragment and any nested
        // fragments spread in the first fragment.
        if (!empty($fragmentNamesA)) {
            $fragmentNamesACount = \count($fragmentNamesA);

            /** @noinspection ForeachInvariantsInspection */
            for ($i = 0; $i < $fragmentNamesACount; $i++) {
                $this->collectConflictsBetweenFragments(
                    $context,
                    $fragmentNamesA[$i],
                    $fragmentNameB,
                    $areMutuallyExclusive
                );
            }
        }
    }