private ImmutableArray<Diagnostic> CheckDependencies(CSharpCompilation compilation, IList<Tuple<AttributeData, ISymbol>> dependencies, INamedTypeSymbol recognizerType)
        {
            string[] ruleNames = GetRuleNames(recognizerType);
            int[] ruleVersions = GetRuleVersions(recognizerType, ruleNames);
            RuleRelations relations = ExtractRuleRelations(recognizerType);
            ImmutableArray<Diagnostic>.Builder errors = ImmutableArray.CreateBuilder<Diagnostic>();
            foreach (var dependency in dependencies)
            {
                if (ruleNames == null)
                {
                    Location location = GetRecognizerTypeLocation(dependency.Item1);
                    errors.Add(Diagnostic.Create(AnalysisError, location, "could not read rule names from generated parser"));
                    continue;
                }

                if (ruleVersions == null)
                {
                    Location location = GetRecognizerTypeLocation(dependency.Item1);
                    errors.Add(Diagnostic.Create(AnalysisError, location, "could not read rule versions from generated parser"));
                    continue;
                }

                if (relations == null)
                {
                    Location location = GetRecognizerTypeLocation(dependency.Item1);
                    errors.Add(Diagnostic.Create(AnalysisError, location, "could not read the ATN from the generated parser"));
                    continue;
                }

                if (!compilation.ClassifyConversion(recognizerType, GetRecognizerType(dependency.Item1)).IsImplicit)
                {
                    Location location = GetRecognizerTypeLocation(dependency.Item1);
                    errors.Add(Diagnostic.Create(AnalysisError, location, string.Format("could not convert '{0}' to '{1}'", recognizerType, GetRecognizerType(dependency.Item1))));
                    continue;
                }

                // this is the rule in the dependency set with the highest version number
                int effectiveRule = GetRule(dependency.Item1);
                if (effectiveRule < 0 || effectiveRule >= ruleVersions.Length)
                {
                    Location location = GetRuleLocation(dependency.Item1);
                    errors.Add(Diagnostic.Create(UnknownRule, location, GetRule(dependency.Item1), GetRecognizerType(dependency.Item1)));
                    continue;
                }

                Dependents dependents = Dependents.Self | (GetDependents(dependency.Item1) ?? Dependents.Parents);
                bool containsUnimplemented = ReportUnimplementedDependents(errors, dependency, ruleNames, dependents);
                bool[] @checked = new bool[ruleNames.Length];
                int highestRequiredDependency = CheckDependencyVersion(errors, dependency, ruleNames, ruleVersions, effectiveRule, null);
                if ((dependents & Dependents.Parents) != 0)
                {
                    bool[] parents = relations.parents[GetRule(dependency.Item1)];
                    for (int parent = Array.IndexOf(parents, true, 0); parent >= 0; parent = Array.IndexOf(parents, true, parent + 1))
                    {
                        if (parent >= ruleVersions.Length)
                        {
                            errors.Add(Diagnostic.Create(AnalysisError, GetLocation(dependency.Item1), "parent index out of range during analysis"));
                            continue;
                        }

                        if (@checked[parent])
                            continue;

                        @checked[parent] = true;
                        int required = CheckDependencyVersion(errors, dependency, ruleNames, ruleVersions, parent, "parent");
                        highestRequiredDependency = Math.Max(highestRequiredDependency, required);
                    }
                }

                if ((dependents & Dependents.Children) != 0)
                {
                    bool[] children = relations.children[GetRule(dependency.Item1)];
                    for (int child = Array.IndexOf(children, true, 0); child >= 0; child = Array.IndexOf(children, true, child + 1))
                    {
                        if (child >= ruleVersions.Length)
                        {
                            errors.Add(Diagnostic.Create(AnalysisError, GetLocation(dependency.Item1), "child index out of range during analysis"));
                            continue;
                        }

                        if (@checked[child])
                            continue;

                        @checked[child] = true;
                        int required = CheckDependencyVersion(errors, dependency, ruleNames, ruleVersions, child, "child");
                        highestRequiredDependency = Math.Max(highestRequiredDependency, required);
                    }
                }

                if ((dependents & Dependents.Ancestors) != 0)
                {
                    bool[] ancestors = relations.GetAncestors(GetRule(dependency.Item1));
                    for (int ancestor = Array.IndexOf(ancestors, true, 0); ancestor >= 0; ancestor = Array.IndexOf(ancestors, true, ancestor + 1))
                    {
                        if (ancestor >= ruleVersions.Length)
                        {
                            errors.Add(Diagnostic.Create(AnalysisError, GetLocation(dependency.Item1), "ancestor index out of range during analysis"));
                            continue;
                        }

                        if (@checked[ancestor])
                            continue;

                        @checked[ancestor] = true;
                        int required = CheckDependencyVersion(errors, dependency, ruleNames, ruleVersions, ancestor, "ancestor");
                        highestRequiredDependency = Math.Max(highestRequiredDependency, required);
                    }
                }

                if ((dependents & Dependents.Descendants) != 0)
                {
                    bool[] descendants = relations.GetDescendants(GetRule(dependency.Item1));
                    for (int descendant = Array.IndexOf(descendants, true, 0); descendant >= 0; descendant = Array.IndexOf(descendants, true, descendant + 1))
                    {
                        if (descendant >= ruleVersions.Length)
                        {
                            errors.Add(Diagnostic.Create(AnalysisError, GetLocation(dependency.Item1), "descendant index out of range during analysis"));
                            continue;
                        }

                        if (@checked[descendant])
                            continue;

                        @checked[descendant] = true;
                        int required = CheckDependencyVersion(errors, dependency, ruleNames, ruleVersions, descendant, "descendant");
                        highestRequiredDependency = Math.Max(highestRequiredDependency, required);
                    }
                }

                int declaredVersion = GetVersion(dependency.Item1);
                if (declaredVersion > highestRequiredDependency && !containsUnimplemented)
                {
                    Location location = Location.Create(dependency.Item1.ApplicationSyntaxReference.SyntaxTree, dependency.Item1.ApplicationSyntaxReference.Span);
                    errors.Add(Diagnostic.Create(VersionTooHigh, location, ruleNames[GetRule(dependency.Item1)], highestRequiredDependency, declaredVersion, GetRecognizerType(dependency.Item1)));
                }
            }

            return errors.ToImmutable();
        }