Inheritance: AbstractNode, IDefinition, IHaveSelectionSet
        public IEnumerable<VariableUsage> GetRecursiveVariables(Operation operation)
        {
            IEnumerable<VariableUsage> results;
            if (_variables.TryGetValue(operation, out results))
            {
                return results;
            }

            var usages = GetVariables(operation).ToList();

            var fragments = GetRecursivelyReferencedFragments(operation);

            fragments.Apply(fragment =>
            {
                usages.AddRange(GetVariables(fragment));
            });

            _variables[operation] = usages;

            return usages;
        }
 protected bool Equals(Operation other)
 {
     return string.Equals(Name, other.Name) && OperationType == other.OperationType;
 }
        public IEnumerable<FragmentDefinition> GetRecursivelyReferencedFragments(Operation operation)
        {
            IEnumerable<FragmentDefinition> results;
            if (_fragments.TryGetValue(operation, out results))
            {
                return results;
            }

            var fragments = new List<FragmentDefinition>();
            var nodesToVisit = new Stack<SelectionSet>(new[] {operation.SelectionSet});
            var collectedNames = new Dictionary<string, bool>();

            while (nodesToVisit.Any())
            {
                var node = nodesToVisit.Pop();
                var spreads = GetFragmentSpreads(node);
                spreads.Apply(spread =>
                {
                    var fragName = spread.Name;
                    if (!collectedNames.ContainsKey(fragName))
                    {
                        collectedNames[fragName] = true;

                        var fragment = GetFragment(fragName);
                        if (fragment != null)
                        {
                            fragments.Add(fragment);
                            nodesToVisit.Push(fragment.SelectionSet);
                        }
                    }
                });
            }

            _fragments[operation] = fragments;

            return fragments;
        }