forked from jasder/antlr
Implement runtime rule dependency checking
This commit is contained in:
parent
1bb1f23579
commit
590ae4fe66
|
@ -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" />
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue