src/Validator/Rules/OverlappingFieldsCanBeMerged.php
private function internalCollectFieldsAndFragmentNames(
        ValidationContext $context,
        $parentType,
        SelectionSetNode $selectionSet,
        array &$astAndDefs,
        array &$fragmentNames
    ) {
        foreach ($selectionSet->selections as $selection) {
            switch (true) {
                case $selection instanceof FieldNode:
                    $fieldName = $selection->name->value;
                    $fieldDef  = null;
                    if ($parentType instanceof ObjectType ||
                        $parentType instanceof InterfaceType) {
                        $tmp = $parentType->getFields();
                        if (isset($tmp[$fieldName])) {
                            $fieldDef = $tmp[$fieldName];
                        }
                    }
                    $responseName = $selection->alias ? $selection->alias->value : $fieldName;

                    if (! isset($astAndDefs[$responseName])) {
                        $astAndDefs[$responseName] = [];
                    }
                    $astAndDefs[$responseName][] = [$parentType, $selection, $fieldDef];
                    break;
                case $selection instanceof FragmentSpreadNode:
                    $fragmentNames[$selection->name->value] = true;
                    break;
                case $selection instanceof InlineFragmentNode:
                    $typeCondition      = $selection->typeCondition;
                    $inlineFragmentType = $typeCondition
                        ? TypeInfo::typeFromAST($context->getSchema(), $typeCondition)
                        : $parentType;

                    $this->internalCollectFieldsAndFragmentNames(
                        $context,
                        $inlineFragmentType,
                        $selection->selectionSet,
                        $astAndDefs,
                        $fragmentNames
                    );
                    break;
            }
        }
    }
private function internalCollectFieldsAndFragmentNames(
        ValidationContext $context,
        $parentType,
        SelectionSetNode $selectionSet,
        array &$astAndDefs,
        array &$fragmentNames
    ) {
        foreach ($selectionSet->selections as $selection) {
            switch (true) {
                case $selection instanceof FieldNode:
                    $fieldName = $selection->name->value;
                    $fieldDef  = null;
                    if ($parentType instanceof ObjectType ||
                        $parentType instanceof InterfaceType) {
                        $tmp = $parentType->getFields();
                        if (isset($tmp[$fieldName])) {
                            $fieldDef = $tmp[$fieldName];
                        }
                    }
                    $responseName = $selection->alias ? $selection->alias->value : $fieldName;

                    if (! isset($astAndDefs[$responseName])) {
                        $astAndDefs[$responseName] = [];
                    }
                    $astAndDefs[$responseName][] = [$parentType, $selection, $fieldDef];
                    break;
                case $selection instanceof FragmentSpreadNode:
                    $fragmentNames[$selection->name->value] = true;
                    break;
                case $selection instanceof InlineFragmentNode:
                    $typeCondition      = $selection->typeCondition;
                    $inlineFragmentType = $typeCondition
                        ? TypeInfo::typeFromAST($context->getSchema(), $typeCondition)
                        : $parentType;

                    $this->internalCollectFieldsAndFragmentNames(
                        $context,
                        $inlineFragmentType,
                        $selection->selectionSet,
                        $astAndDefs,
                        $fragmentNames
                    );
                    break;
            }
        }
    }
Given a reference to a fragment, return the represented collection of fields
as well as a list of nested fragment names referenced via fragment spreads.

@param CompositeType $parentType
@param mixed[][][]   $astAndDefs
@param bool[]        $fragmentNames