private static RuleDependencyChecker.RuleRelations ExtractRuleRelations(Type recognizer) { string serializedATN = GetSerializedATN(recognizer); if (serializedATN == null) { return(null); } ATN atn = new ATNDeserializer().Deserialize(serializedATN.ToCharArray()); RuleDependencyChecker.RuleRelations relations = new RuleDependencyChecker.RuleRelations(atn.ruleToStartState.Length); foreach (ATNState state in atn.states) { if (!state.epsilonOnlyTransitions) { continue; } foreach (Transition transition in state.GetTransitions()) { if (transition.TransitionType != TransitionType.Rule) { continue; } RuleTransition ruleTransition = (RuleTransition)transition; relations.AddRuleInvocation(state.ruleIndex, ruleTransition.target.ruleIndex); } } return(relations); }
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()); } }
private static RuleDependencyChecker.RuleRelations ExtractRuleRelations(Type recognizer) { string serializedATN = GetSerializedATN(recognizer); if (serializedATN == null) { return null; } ATN atn = new ATNDeserializer().Deserialize(serializedATN.ToCharArray()); RuleDependencyChecker.RuleRelations relations = new RuleDependencyChecker.RuleRelations(atn.ruleToStartState.Length); foreach (ATNState state in atn.states) { if (!state.epsilonOnlyTransitions) { continue; } foreach (Transition transition in state.Transitions) { if (transition.TransitionType != TransitionType.Rule) { continue; } RuleTransition ruleTransition = (RuleTransition)transition; relations.AddRuleInvocation(state.ruleIndex, ruleTransition.target.ruleIndex); } } return relations; }