protected static function collectFields(ExecutionContext $context, ObjectType $type, SelectionSet $set, $fields, $visited)
    {
        $count = count($set->get('selections'));
        for ($i = 0; $i < $count; $i++) {
            $selection = $set->get('selections')[$i];
            switch ($selection::KIND) {
                case Node::KIND_FIELD:
                    if (!self::shouldIncludeNode($context, $selection->get('directives'))) {
                        continue;
                    }

                    $name = self::getFieldEntryKey($selection);
                    if (!isset($fields[$name])) {
                        $fields[$name] = new \ArrayObject();
                    }

                    $fields[$name][] = $selection;
                    break;

                case Node::KIND_INLINE_FRAGMENT:
                    if (!self::shouldIncludeNode($context, $selection->get('directives')) || !self::doesFragmentConditionMatch($context, $selection, $type)) {
                        continue;
                    }

                    self::collectFields(
                        $context,
                        $type,
                        $selection->get('selectionSet'),
                        $fields,
                        $visited
                    );

                    break;

                case Node::KIND_FRAGMENT_SPREAD:
                    $fragName = $selection->get('name')->get('value');
                    if (!empty($visited[$fragName]) || !self::shouldIncludeNode($context, $selection->get('directives'))) {
                        continue;
                    }

                    $visited[$fragName] = TRUE;
                    $fragment = isset($context->fragments[$fragName]) ? $context->fragments[$fragName] : NULL;
                    if (!$fragment || !self::shouldIncludeNode($context, $fragment->get('directives')) || !self::doesFragmentConditionMatch($context, $fragment, $type)) {
                        continue;
                    }

                    self::collectFields($context, $type, $fragment->get('selectionSet'), $fields, $visited);

                    break;
            }
        }

        return $fields;
    }