Implement runtime rule dependency checking

This commit is contained in:
Sam Harwell 2013-02-25 15:09:31 -06:00
parent 1bb1f23579
commit 590ae4fe66
2 changed files with 117 additions and 217 deletions

View File

@ -141,7 +141,7 @@
<Compile Include="Misc\NotNullAttribute.cs" /> <Compile Include="Misc\NotNullAttribute.cs" />
<None Include="Misc\OrderedHashSet`1.cs" /> <None Include="Misc\OrderedHashSet`1.cs" />
<Compile Include="Misc\ParseCanceledException.cs" /> <Compile Include="Misc\ParseCanceledException.cs" />
<None Include="Misc\RuleDependencyChecker.cs" /> <Compile Include="Misc\RuleDependencyChecker.cs" />
<None Include="Misc\RuleDependencyProcessor.cs" /> <None Include="Misc\RuleDependencyProcessor.cs" />
<None Include="Misc\TestRig.cs" /> <None Include="Misc\TestRig.cs" />
<Compile Include="Misc\Utils.cs" /> <Compile Include="Misc\Utils.cs" />

View File

@ -36,21 +36,20 @@ using Antlr4.Runtime;
using Antlr4.Runtime.Atn; using Antlr4.Runtime.Atn;
using Antlr4.Runtime.Misc; using Antlr4.Runtime.Misc;
using Sharpen; using Sharpen;
using Sharpen.Annotation;
using Sharpen.Logging;
using Sharpen.Reflect;
namespace Antlr4.Runtime.Misc namespace Antlr4.Runtime.Misc
{ {
/// <author>Sam Harwell</author> /// <author>Sam Harwell</author>
public class RuleDependencyChecker public class RuleDependencyChecker
{ {
#if false
private static readonly Logger Logger = Logger.GetLogger(typeof(Antlr4.Runtime.Misc.RuleDependencyChecker private static readonly Logger Logger = Logger.GetLogger(typeof(Antlr4.Runtime.Misc.RuleDependencyChecker
).FullName); ).FullName);
#endif
private static readonly ISet<Type> checkedTypes = new HashSet<Type>(); private static readonly ISet<Type> checkedTypes = new HashSet<Type>();
public static void CheckDependencies<_T0>(Type<_T0> dependentClass) public static void CheckDependencies(Type dependentClass)
{ {
if (IsChecked(dependentClass)) if (IsChecked(dependentClass))
{ {
@ -63,56 +62,56 @@ namespace Antlr4.Runtime.Misc
{ {
continue; continue;
} }
IList<Tuple<RuleDependency, IAnnotatedElement>> dependencies = GetDependencies(clazz IList<Tuple<RuleDependencyAttribute, ICustomAttributeProvider>> dependencies = GetDependencies(clazz
); );
if (dependencies.Count == 0) if (dependencies.Count == 0)
{ {
continue; continue;
} }
IDictionary<Type, IList<Tuple<RuleDependency, IAnnotatedElement>>> recognizerDependencies IDictionary<Type, IList<Tuple<RuleDependencyAttribute, ICustomAttributeProvider>>> recognizerDependencies
= new Dictionary<Type, IList<Tuple<RuleDependency, IAnnotatedElement>>>(); = new Dictionary<Type, IList<Tuple<RuleDependencyAttribute, ICustomAttributeProvider>>>();
foreach (Tuple<RuleDependency, IAnnotatedElement> dependency in dependencies) foreach (Tuple<RuleDependencyAttribute, ICustomAttributeProvider> dependency in dependencies)
{ {
Type recognizerType = dependency.Item1.Recognizer(); Type recognizerType = dependency.Item1.Recognizer;
IList<Tuple<RuleDependency, IAnnotatedElement>> list = recognizerDependencies.Get IList<Tuple<RuleDependencyAttribute, ICustomAttributeProvider>> list = recognizerDependencies.Get
(recognizerType); (recognizerType);
if (list == null) if (list == null)
{ {
list = new List<Tuple<RuleDependency, IAnnotatedElement>>(); list = new List<Tuple<RuleDependencyAttribute, ICustomAttributeProvider>>();
recognizerDependencies.Put(recognizerType, list); recognizerDependencies.Put(recognizerType, list);
} }
list.AddItem(dependency); list.Add(dependency);
} }
foreach (KeyValuePair<Type, IList<Tuple<RuleDependency, IAnnotatedElement>>> entry foreach (KeyValuePair<Type, IList<Tuple<RuleDependencyAttribute, ICustomAttributeProvider>>> entry
in recognizerDependencies.EntrySet()) in recognizerDependencies)
{ {
//processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("ANTLR 4: Validating %d dependencies on rules in %s.", entry.getValue().size(), entry.getKey().toString())); //processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("ANTLR 4: Validating %d dependencies on rules in %s.", entry.getValue().size(), entry.getKey().toString()));
CheckDependencies(entry.Value, entry.Key); CheckDependencies(entry.Value, entry.Key);
} }
CheckDependencies(dependencies, dependencies[0].Item1.Recognizer()); CheckDependencies(dependencies, dependencies[0].Item1.Recognizer);
} }
} }
private static IList<Type> GetTypesToCheck<_T0>(Type<_T0> clazz) private static IList<Type> GetTypesToCheck(Type clazz)
{ {
ISet<Type> result = new HashSet<Type>(); ISet<Type> result = new HashSet<Type>();
GetTypesToCheck(clazz, result); GetTypesToCheck(clazz, result);
return new List<Type>(result); return new List<Type>(result);
} }
private static void GetTypesToCheck<_T0>(Type<_T0> clazz, ISet<Type> result) private static void GetTypesToCheck(Type clazz, ISet<Type> result)
{ {
if (!result.AddItem(clazz)) if (!result.Add(clazz))
{ {
return; return;
} }
foreach (Type declared in clazz.GetDeclaredClasses()) foreach (Type declared in clazz.GetNestedTypes())
{ {
GetTypesToCheck(declared, result); GetTypesToCheck(declared, result);
} }
} }
private static bool IsChecked<_T0>(Type<_T0> clazz) private static bool IsChecked(Type clazz)
{ {
lock (checkedTypes) lock (checkedTypes)
{ {
@ -120,48 +119,46 @@ namespace Antlr4.Runtime.Misc
} }
} }
private static void MarkChecked<_T0>(Type<_T0> clazz) private static void MarkChecked(Type clazz)
{ {
lock (checkedTypes) lock (checkedTypes)
{ {
checkedTypes.AddItem(clazz); checkedTypes.Add(clazz);
} }
} }
private static void CheckDependencies<_T0>(IList<Tuple<RuleDependency, IAnnotatedElement private static void CheckDependencies(IList<Tuple<RuleDependencyAttribute, ICustomAttributeProvider
>> dependencies, Type<_T0> recognizerType) where _T0:Recognizer<object, object >> dependencies, Type recognizerType)
>
{ {
string[] ruleNames = GetRuleNames(recognizerType); string[] ruleNames = GetRuleNames(recognizerType);
int[] ruleVersions = GetRuleVersions(recognizerType, ruleNames); int[] ruleVersions = GetRuleVersions(recognizerType, ruleNames);
RuleDependencyChecker.RuleRelations relations = ExtractRuleRelations(recognizerType RuleDependencyChecker.RuleRelations relations = ExtractRuleRelations(recognizerType
); );
StringBuilder errors = new StringBuilder(); StringBuilder errors = new StringBuilder();
foreach (Tuple<RuleDependency, IAnnotatedElement> dependency in dependencies) foreach (Tuple<RuleDependencyAttribute, ICustomAttributeProvider> dependency in dependencies)
{ {
if (!dependency.Item1.Recognizer().IsAssignableFrom(recognizerType)) if (!dependency.Item1.Recognizer.IsAssignableFrom(recognizerType))
{ {
continue; continue;
} }
// this is the rule in the dependency set with the highest version number // this is the rule in the dependency set with the highest version number
int effectiveRule = dependency.Item1.Rule(); int effectiveRule = dependency.Item1.Rule;
if (effectiveRule < 0 || effectiveRule >= ruleVersions.Length) if (effectiveRule < 0 || effectiveRule >= ruleVersions.Length)
{ {
string message = string.Format("Rule dependency on unknown rule %d@%d in %s%n", dependency string message = string.Format("Rule dependency on unknown rule %d@%d in %s%n", dependency
.Item1.Rule(), dependency.Item1.Version(), dependency.Item1.Recognizer().ToString .Item1.Rule, dependency.Item1.Version, dependency.Item1.Recognizer.ToString
()); ());
errors.Append(message); errors.Append(message);
continue; continue;
} }
EnumSet<Dependents> dependents = EnumSet.Of(Dependents.Self, dependency.Item1.Dependents Dependents dependents = Dependents.Self | dependency.Item1.Dependents;
());
ReportUnimplementedDependents(errors, dependency, dependents); ReportUnimplementedDependents(errors, dependency, dependents);
BitSet @checked = new BitSet(); BitSet @checked = new BitSet();
int highestRequiredDependency = CheckDependencyVersion(errors, dependency, ruleNames int highestRequiredDependency = CheckDependencyVersion(errors, dependency, ruleNames
, ruleVersions, effectiveRule, null); , ruleVersions, effectiveRule, null);
if (dependents.Contains(Dependents.Parents)) if (dependents.HasFlag(Dependents.Parents))
{ {
BitSet parents = relations.parents[dependency.Item1.Rule()]; BitSet parents = relations.parents[dependency.Item1.Rule];
for (int parent = parents.NextSetBit(0); parent >= 0; parent = parents.NextSetBit for (int parent = parents.NextSetBit(0); parent >= 0; parent = parents.NextSetBit
(parent + 1)) (parent + 1))
{ {
@ -175,9 +172,9 @@ namespace Antlr4.Runtime.Misc
highestRequiredDependency = Math.Max(highestRequiredDependency, required); highestRequiredDependency = Math.Max(highestRequiredDependency, required);
} }
} }
if (dependents.Contains(Dependents.Children)) if (dependents.HasFlag(Dependents.Children))
{ {
BitSet children = relations.children[dependency.Item1.Rule()]; BitSet children = relations.children[dependency.Item1.Rule];
for (int child = children.NextSetBit(0); child >= 0; child = children.NextSetBit( for (int child = children.NextSetBit(0); child >= 0; child = children.NextSetBit(
child + 1)) child + 1))
{ {
@ -191,9 +188,9 @@ namespace Antlr4.Runtime.Misc
highestRequiredDependency = Math.Max(highestRequiredDependency, required); highestRequiredDependency = Math.Max(highestRequiredDependency, required);
} }
} }
if (dependents.Contains(Dependents.Ancestors)) if (dependents.HasFlag(Dependents.Ancestors))
{ {
BitSet ancestors = relations.GetAncestors(dependency.Item1.Rule()); BitSet ancestors = relations.GetAncestors(dependency.Item1.Rule);
for (int ancestor = ancestors.NextSetBit(0); ancestor >= 0; ancestor = ancestors. for (int ancestor = ancestors.NextSetBit(0); ancestor >= 0; ancestor = ancestors.
NextSetBit(ancestor + 1)) NextSetBit(ancestor + 1))
{ {
@ -207,9 +204,9 @@ namespace Antlr4.Runtime.Misc
highestRequiredDependency = Math.Max(highestRequiredDependency, required); highestRequiredDependency = Math.Max(highestRequiredDependency, required);
} }
} }
if (dependents.Contains(Dependents.Descendants)) if (dependents.HasFlag(Dependents.Descendants))
{ {
BitSet descendants = relations.GetDescendants(dependency.Item1.Rule()); BitSet descendants = relations.GetDescendants(dependency.Item1.Rule);
for (int descendant = descendants.NextSetBit(0); descendant >= 0; descendant = descendants for (int descendant = descendants.NextSetBit(0); descendant >= 0; descendant = descendants
.NextSetBit(descendant + 1)) .NextSetBit(descendant + 1))
{ {
@ -224,12 +221,12 @@ namespace Antlr4.Runtime.Misc
highestRequiredDependency = Math.Max(highestRequiredDependency, required); highestRequiredDependency = Math.Max(highestRequiredDependency, required);
} }
} }
int declaredVersion = dependency.Item1.Version(); int declaredVersion = dependency.Item1.Version;
if (declaredVersion > highestRequiredDependency) if (declaredVersion > highestRequiredDependency)
{ {
string message = string.Format("Rule dependency version mismatch: %s has maximum dependency version %d (expected %d) in %s%n" string message = string.Format("Rule dependency version mismatch: %s has maximum dependency version %d (expected %d) in %s%n"
, ruleNames[dependency.Item1.Rule()], highestRequiredDependency, declaredVersion , ruleNames[dependency.Item1.Rule], highestRequiredDependency, declaredVersion
, dependency.Item1.Recognizer().ToString()); , dependency.Item1.Recognizer.ToString());
errors.Append(message); errors.Append(message);
} }
} }
@ -240,28 +237,28 @@ namespace Antlr4.Runtime.Misc
MarkChecked(recognizerType); MarkChecked(recognizerType);
} }
private static readonly ISet<Dependents> ImplementedDependents = EnumSet.Of(Dependents private static readonly Dependents ImplementedDependents = Dependents
.Self, Dependents.Parents, Dependents.Children, Dependents.Ancestors, Dependents .Self | Dependents.Parents | Dependents.Children | Dependents.Ancestors | Dependents
.Descendants); .Descendants;
private static void ReportUnimplementedDependents(StringBuilder errors, Tuple<RuleDependency private static void ReportUnimplementedDependents(StringBuilder errors, Tuple<RuleDependencyAttribute
, IAnnotatedElement> dependency, EnumSet<Dependents> dependents) , ICustomAttributeProvider> dependency, Dependents dependents)
{ {
EnumSet<Dependents> unimplemented = dependents.Clone(); Dependents unimplemented = dependents;
unimplemented.RemoveAll(ImplementedDependents); unimplemented &= ~ImplementedDependents;
if (!unimplemented.IsEmpty()) if (unimplemented != Dependents.None)
{ {
string message = string.Format("Cannot validate the following dependents of rule %d: %s%n" string message = string.Format("Cannot validate the following dependents of rule %d: %s%n"
, dependency.Item1.Rule(), unimplemented); , dependency.Item1.Rule, unimplemented);
errors.Append(message); errors.Append(message);
} }
} }
private static int CheckDependencyVersion(StringBuilder errors, Tuple<RuleDependency private static int CheckDependencyVersion(StringBuilder errors, Tuple<RuleDependencyAttribute
, IAnnotatedElement> dependency, string[] ruleNames, int[] ruleVersions, int , ICustomAttributeProvider> dependency, string[] ruleNames, int[] ruleVersions, int
relatedRule, string relation) relatedRule, string relation)
{ {
string ruleName = ruleNames[dependency.Item1.Rule()]; string ruleName = ruleNames[dependency.Item1.Rule];
string path; string path;
if (relation == null) if (relation == null)
{ {
@ -273,76 +270,84 @@ namespace Antlr4.Runtime.Misc
path = string.Format("rule %s (%s of %s)", mismatchedRuleName, relation, ruleName path = string.Format("rule %s (%s of %s)", mismatchedRuleName, relation, ruleName
); );
} }
int declaredVersion = dependency.Item1.Version(); int declaredVersion = dependency.Item1.Version;
int actualVersion = ruleVersions[relatedRule]; int actualVersion = ruleVersions[relatedRule];
if (actualVersion > declaredVersion) if (actualVersion > declaredVersion)
{ {
string message = string.Format("Rule dependency version mismatch: %s has version %d (expected <= %d) in %s%n" string message = string.Format("Rule dependency version mismatch: %s has version %d (expected <= %d) in %s%n"
, path, actualVersion, declaredVersion, dependency.Item1.Recognizer().ToString , path, actualVersion, declaredVersion, dependency.Item1.Recognizer.ToString
()); ());
errors.Append(message); errors.Append(message);
} }
return actualVersion; return actualVersion;
} }
private static int[] GetRuleVersions<_T0>(Type<_T0> recognizerClass, string[] ruleNames private static int[] GetRuleVersions(Type recognizerClass, string[] ruleNames
) where _T0:Recognizer<object, object> )
{ {
int[] versions = new int[ruleNames.Length]; int[] versions = new int[ruleNames.Length];
FieldInfo[] fields = recognizerClass.GetFields(); FieldInfo[] fields = recognizerClass.GetFields();
foreach (FieldInfo field in fields) foreach (FieldInfo field in fields)
{ {
bool isStatic = (field.GetModifiers() & Modifier.Static) != 0; bool isStatic = field.IsStatic;
bool isInteger = field.FieldType == typeof(int); bool isInteger = field.FieldType == typeof(int);
if (isStatic && isInteger && field.Name.StartsWith("RULE_")) if (isStatic && isInteger && field.Name.StartsWith("RULE_"))
{ {
try try
{ {
string name = Sharpen.Runtime.Substring(field.Name, "RULE_".Length); string name = field.Name.Substring("RULE_".Length);
if (name.Length == 0 || !System.Char.IsLower(name[0])) if (name.Length == 0 || !System.Char.IsLower(name[0]))
{ {
continue; continue;
} }
int index = field.GetInt(null); int index = (int)field.GetValue(null);
if (index < 0 || index >= versions.Length) if (index < 0 || index >= versions.Length)
{ {
object[] @params = new object[] { index, field.Name, recognizerClass.Name }; object[] @params = new object[] { index, field.Name, recognizerClass.Name };
#if false
Logger.Log(Level.Warning, "Rule index {0} for rule ''{1}'' out of bounds for recognizer {2}." Logger.Log(Level.Warning, "Rule index {0} for rule ''{1}'' out of bounds for recognizer {2}."
, @params); , @params);
#endif
continue; continue;
} }
MethodInfo ruleMethod = GetRuleMethod(recognizerClass, name); MethodInfo ruleMethod = GetRuleMethod(recognizerClass, name);
if (ruleMethod == null) if (ruleMethod == null)
{ {
object[] @params = new object[] { name, recognizerClass.Name }; object[] @params = new object[] { name, recognizerClass.Name };
#if false
Logger.Log(Level.Warning, "Could not find rule method for rule ''{0}'' in recognizer {1}." Logger.Log(Level.Warning, "Could not find rule method for rule ''{0}'' in recognizer {1}."
, @params); , @params);
#endif
continue; continue;
} }
RuleVersion ruleVersion = ruleMethod.GetAnnotation<RuleVersion>(); RuleVersionAttribute ruleVersion = ruleMethod.GetCustomAttribute<RuleVersionAttribute>();
int version = ruleVersion != null ? ruleVersion.Value() : 0; int version = ruleVersion != null ? ruleVersion.Version : 0;
versions[index] = version; versions[index] = version;
} }
catch (ArgumentException ex) catch (ArgumentException ex)
{ {
#if false
Logger.Log(Level.Warning, null, ex); Logger.Log(Level.Warning, null, ex);
#endif
} }
catch (MemberAccessException ex) catch (MemberAccessException ex)
{ {
#if false
Logger.Log(Level.Warning, null, ex); Logger.Log(Level.Warning, null, ex);
#endif
} }
} }
} }
return versions; return versions;
} }
private static MethodInfo GetRuleMethod<_T0>(Type<_T0> recognizerClass, string name private static MethodInfo GetRuleMethod(Type recognizerClass, string name
) where _T0:Recognizer<object, object> )
{ {
MethodInfo[] declaredMethods = recognizerClass.GetMethods(); MethodInfo[] declaredMethods = recognizerClass.GetMethods();
foreach (MethodInfo method in declaredMethods) foreach (MethodInfo method in declaredMethods)
{ {
if (method.Name.Equals(name) && method.IsAnnotationPresent(typeof(RuleVersion))) if (method.Name.Equals(name) && method.GetCustomAttribute<RuleVersionAttribute>() != null)
{ {
return method; return method;
} }
@ -350,137 +355,54 @@ namespace Antlr4.Runtime.Misc
return null; return null;
} }
private static string[] GetRuleNames<_T0>(Type<_T0> recognizerClass) where _T0:Recognizer private static string[] GetRuleNames(Type recognizerClass)
<object, object>
{ {
try FieldInfo ruleNames = recognizerClass.GetField("ruleNames");
{ return (string[])ruleNames.GetValue(null);
FieldInfo ruleNames = recognizerClass.GetField("ruleNames");
return (string[])ruleNames.GetValue(null);
}
catch (NoSuchFieldException ex)
{
Logger.Log(Level.Warning, null, ex);
}
catch (SecurityException ex)
{
Logger.Log(Level.Warning, null, ex);
}
catch (ArgumentException ex)
{
Logger.Log(Level.Warning, null, ex);
}
catch (MemberAccessException ex)
{
Logger.Log(Level.Warning, null, ex);
}
return new string[0];
} }
public static IList<Tuple<RuleDependency, IAnnotatedElement>> GetDependencies<_T0 public static IList<Tuple<RuleDependencyAttribute, ICustomAttributeProvider>> GetDependencies(Type clazz)
>(Type<_T0> clazz)
{ {
IList<Tuple<RuleDependency, IAnnotatedElement>> result = new List<Tuple<RuleDependency IList<Tuple<RuleDependencyAttribute, ICustomAttributeProvider>> result = new List<Tuple<RuleDependencyAttribute
, IAnnotatedElement>>(); , ICustomAttributeProvider>>();
IList<ElementType> supportedTarget = Arrays.AsList(typeof(RuleDependency).GetAnnotation
<Target>().Value()); GetElementDependencies(clazz, result);
foreach (ElementType target in supportedTarget) foreach (ConstructorInfo ctor in clazz.GetConstructors(BindingFlags.DeclaredOnly))
{ {
switch (target) GetElementDependencies(ctor, result);
{ foreach (ParameterInfo parameter in ctor.GetParameters())
case ElementType.Type: GetElementDependencies(parameter, result);
{
if (!clazz.IsAnnotation())
{
GetElementDependencies(clazz, result);
}
break;
}
case ElementType.AnnotationType:
{
if (!clazz.IsAnnotation())
{
GetElementDependencies(clazz, result);
}
break;
}
case ElementType.Constructor:
{
foreach (Constructor<object> ctor in clazz.GetDeclaredConstructors())
{
GetElementDependencies(ctor, result);
}
break;
}
case ElementType.Field:
{
foreach (FieldInfo field in Sharpen.Runtime.GetDeclaredFields(clazz))
{
GetElementDependencies(field, result);
}
break;
}
case ElementType.LocalVariable:
{
System.Console.Error.WriteLine("Runtime rule dependency checking is not supported for local variables."
);
break;
}
case ElementType.Method:
{
foreach (MethodInfo method in Sharpen.Runtime.GetDeclaredMethods(clazz))
{
GetElementDependencies(method, result);
}
break;
}
case ElementType.Package:
{
// package is not a subset of class, so nothing to do here
break;
}
case ElementType.Parameter:
{
System.Console.Error.WriteLine("Runtime rule dependency checking is not supported for parameters."
);
break;
}
}
} }
foreach (FieldInfo field in clazz.GetFields(BindingFlags.DeclaredOnly))
{
GetElementDependencies(field, result);
}
foreach (MethodInfo method in clazz.GetMethods(BindingFlags.DeclaredOnly))
{
GetElementDependencies(method, result);
if (method.ReturnParameter != null)
GetElementDependencies(method.ReturnParameter, result);
foreach (ParameterInfo parameter in method.GetParameters())
GetElementDependencies(parameter, result);
}
return result; return result;
} }
private static void GetElementDependencies(IAnnotatedElement annotatedElement, IList private static void GetElementDependencies(ICustomAttributeProvider annotatedElement, IList
<Tuple<RuleDependency, IAnnotatedElement>> result) <Tuple<RuleDependencyAttribute, ICustomAttributeProvider>> result)
{ {
RuleDependency dependency = annotatedElement.GetAnnotation<RuleDependency>(); foreach (RuleDependencyAttribute dependency in annotatedElement.GetCustomAttributes(typeof(RuleDependencyAttribute), true))
if (dependency != null)
{ {
result.AddItem(Tuple.Create(dependency, annotatedElement)); result.Add(Tuple.Create(dependency, annotatedElement));
}
RuleDependencies dependencies = annotatedElement.GetAnnotation<RuleDependencies>(
);
if (dependencies != null)
{
foreach (RuleDependency d in dependencies.Value())
{
if (d != null)
{
result.AddItem(Tuple.Create(d, annotatedElement));
}
}
} }
} }
private static RuleDependencyChecker.RuleRelations ExtractRuleRelations<_T0>(Type private static RuleDependencyChecker.RuleRelations ExtractRuleRelations(Type
<_T0> recognizer) where _T0:Recognizer<object, object> recognizer)
{ {
string serializedATN = GetSerializedATN(recognizer); string serializedATN = GetSerializedATN(recognizer);
if (serializedATN == null) if (serializedATN == null)
@ -509,45 +431,23 @@ namespace Antlr4.Runtime.Misc
return relations; return relations;
} }
private static string GetSerializedATN<_T0>(Type<_T0> recognizerClass) private static string GetSerializedATN(Type recognizerClass)
{ {
try FieldInfo serializedAtnField = recognizerClass.GetField("_serializedATN", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
{ if (serializedAtnField != null)
FieldInfo serializedAtnField = Sharpen.Runtime.GetDeclaredField(recognizerClass, return (string)serializedAtnField.GetValue(null);
"_serializedATN");
if (Modifier.IsStatic(serializedAtnField.GetModifiers())) if (recognizerClass.BaseType != null)
{ return GetSerializedATN(recognizerClass.BaseType);
return (string)serializedAtnField.GetValue(null);
} return null;
return null;
}
catch (NoSuchFieldException)
{
if (recognizerClass.BaseType != null)
{
return GetSerializedATN(recognizerClass.BaseType);
}
return null;
}
catch (SecurityException)
{
return null;
}
catch (ArgumentException)
{
return null;
}
catch (MemberAccessException)
{
return null;
}
} }
private sealed class RuleRelations private sealed class RuleRelations
{ {
private readonly BitSet[] parents; public readonly BitSet[] parents;
private readonly BitSet[] children; public readonly BitSet[] children;
public RuleRelations(int ruleCount) public RuleRelations(int ruleCount)
{ {