private static void CheckDependencies(IList <Tuple <RuleDependencyAttribute, ICustomAttributeProvider> > dependencies, Type recognizerType)
{
string[] ruleNames = GetRuleNames(recognizerType);
int[] ruleVersions = GetRuleVersions(recognizerType, ruleNames);
RuleDependencyChecker.RuleRelations relations = ExtractRuleRelations(recognizerType);
StringBuilder errors = new StringBuilder();
foreach (Tuple <RuleDependencyAttribute, ICustomAttributeProvider> dependency in dependencies)
{
if (!dependency.Item1.Recognizer.IsAssignableFrom(recognizerType))
{
continue;
}
// this is the rule in the dependency set with the highest version number
int effectiveRule = dependency.Item1.Rule;
if (effectiveRule < 0 || effectiveRule >= ruleVersions.Length)
{
string message = string.Format("Rule dependency on unknown rule {0}@{1} in {2}", dependency.Item1.Rule, dependency.Item1.Version, dependency.Item1.Recognizer.ToString());
errors.AppendLine(dependency.Item2.ToString());
errors.AppendLine(message);
continue;
}
Dependents dependents = Dependents.Self | dependency.Item1.Dependents;
ReportUnimplementedDependents(errors, dependency, dependents);
BitSet @checked = new BitSet();
int highestRequiredDependency = CheckDependencyVersion(errors, dependency, ruleNames, ruleVersions, effectiveRule, null);
if ((dependents & Dependents.Parents) != 0)
{
BitSet parents = relations.parents[dependency.Item1.Rule];
for (int parent = parents.NextSetBit(0); parent >= 0; parent = parents.NextSetBit(parent + 1))
{
if (parent < 0 || parent >= ruleVersions.Length || @checked.Get(parent))
{
continue;
}
@checked.Set(parent);
int required = CheckDependencyVersion(errors, dependency, ruleNames, ruleVersions, parent, "parent");
highestRequiredDependency = Math.Max(highestRequiredDependency, required);
}
}
if ((dependents & Dependents.Children) != 0)
{
BitSet children = relations.children[dependency.Item1.Rule];
for (int child = children.NextSetBit(0); child >= 0; child = children.NextSetBit(child + 1))
{
if (child < 0 || child >= ruleVersions.Length || @checked.Get(child))
{
continue;
}
@checked.Set(child);
int required = CheckDependencyVersion(errors, dependency, ruleNames, ruleVersions, child, "child");
highestRequiredDependency = Math.Max(highestRequiredDependency, required);
}
}
if ((dependents & Dependents.Ancestors) != 0)
{
BitSet ancestors = relations.GetAncestors(dependency.Item1.Rule);
for (int ancestor = ancestors.NextSetBit(0); ancestor >= 0; ancestor = ancestors.NextSetBit(ancestor + 1))
{
if (ancestor < 0 || ancestor >= ruleVersions.Length || @checked.Get(ancestor))
{
continue;
}
@checked.Set(ancestor);
int required = CheckDependencyVersion(errors, dependency, ruleNames, ruleVersions, ancestor, "ancestor");
highestRequiredDependency = Math.Max(highestRequiredDependency, required);
}
}
if ((dependents & Dependents.Descendants) != 0)
{
BitSet descendants = relations.GetDescendants(dependency.Item1.Rule);
for (int descendant = descendants.NextSetBit(0); descendant >= 0; descendant = descendants.NextSetBit(descendant + 1))
{
if (descendant < 0 || descendant >= ruleVersions.Length || @checked.Get(descendant))
{
continue;
}
@checked.Set(descendant);
int required = CheckDependencyVersion(errors, dependency, ruleNames, ruleVersions, descendant, "descendant");
highestRequiredDependency = Math.Max(highestRequiredDependency, required);
}
}
int declaredVersion = dependency.Item1.Version;
if (declaredVersion > highestRequiredDependency)
{
string message = string.Format("Rule dependency version mismatch: {0} has maximum dependency version {1} (expected {2}) in {3}", ruleNames[dependency.Item1.Rule], highestRequiredDependency, declaredVersion, dependency.Item1.Recognizer.ToString());
errors.AppendLine(dependency.Item2.ToString());
errors.AppendLine(message);
}
}
if (errors.Length > 0)
{
throw new InvalidOperationException(errors.ToString());
}
}