2013-02-16 05:30:47 +08:00
/ *
* [ The "BSD license" ]
* Copyright ( c ) 2013 Terence Parr
* Copyright ( c ) 2013 Sam Harwell
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
*
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* /
2014-04-28 10:31:27 +08:00
#if NET45PLUS
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Reflection ;
using System.Security ;
using System.Text ;
using Antlr4.Runtime ;
using Antlr4.Runtime.Atn ;
using Antlr4.Runtime.Misc ;
using Antlr4.Runtime.Sharpen ;
namespace Antlr4.Runtime.Misc
{
/// <author>Sam Harwell</author>
public class RuleDependencyChecker
{
private static readonly HashSet < string > checkedAssemblies = new HashSet < string > ( ) ;
public static void CheckDependencies ( Assembly assembly )
{
if ( IsChecked ( assembly ) )
{
return ;
}
IEnumerable < TypeInfo > typesToCheck = GetTypesToCheck ( assembly ) ;
List < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > dependencies = new List < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > ( ) ;
foreach ( TypeInfo clazz in typesToCheck )
{
dependencies . AddRange ( GetDependencies ( clazz ) ) ;
}
if ( dependencies . Count > 0 )
{
IDictionary < TypeInfo , IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > > recognizerDependencies = new Dictionary < TypeInfo , IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > > ( ) ;
foreach ( Tuple < RuleDependencyAttribute , ICustomAttributeProvider > dependency in dependencies )
{
TypeInfo recognizerType = dependency . Item1 . Recognizer . GetTypeInfo ( ) ;
IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > list ;
if ( ! recognizerDependencies . TryGetValue ( recognizerType , out list ) )
{
list = new List < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > ( ) ;
recognizerDependencies [ recognizerType ] = list ;
}
list . Add ( dependency ) ;
}
foreach ( KeyValuePair < TypeInfo , IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > > entry in recognizerDependencies )
{
//processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("ANTLR 4: Validating {0} dependencies on rules in {1}.", entry.getValue().size(), entry.getKey().toString()));
CheckDependencies ( entry . Value , entry . Key ) ;
}
}
MarkChecked ( assembly ) ;
}
private static IEnumerable < TypeInfo > GetTypesToCheck ( Assembly assembly )
{
return assembly . DefinedTypes ;
}
private static bool IsChecked ( Assembly assembly )
{
lock ( checkedAssemblies )
{
return checkedAssemblies . Contains ( assembly . FullName ) ;
}
}
private static void MarkChecked ( Assembly assembly )
{
lock ( checkedAssemblies )
{
checkedAssemblies . Add ( assembly . FullName ) ;
}
}
private static void CheckDependencies ( IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > dependencies , TypeInfo 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 . GetTypeInfo ( ) . 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 readonly Dependents ImplementedDependents = Dependents . Self | Dependents . Parents | Dependents . Children | Dependents . Ancestors | Dependents . Descendants ;
private static void ReportUnimplementedDependents ( StringBuilder errors , Tuple < RuleDependencyAttribute , ICustomAttributeProvider > dependency , Dependents dependents )
{
Dependents unimplemented = dependents ;
unimplemented & = ~ ImplementedDependents ;
if ( unimplemented ! = Dependents . None )
{
string message = string . Format ( "Cannot validate the following dependents of rule {0}: {1}" , dependency . Item1 . Rule , unimplemented ) ;
errors . AppendLine ( message ) ;
}
}
private static int CheckDependencyVersion ( StringBuilder errors , Tuple < RuleDependencyAttribute , ICustomAttributeProvider > dependency , string [ ] ruleNames , int [ ] ruleVersions , int relatedRule , string relation )
{
string ruleName = ruleNames [ dependency . Item1 . Rule ] ;
string path ;
if ( relation = = null )
{
path = ruleName ;
}
else
{
string mismatchedRuleName = ruleNames [ relatedRule ] ;
path = string . Format ( "rule {0} ({1} of {2})" , mismatchedRuleName , relation , ruleName ) ;
}
int declaredVersion = dependency . Item1 . Version ;
int actualVersion = ruleVersions [ relatedRule ] ;
if ( actualVersion > declaredVersion )
{
string message = string . Format ( "Rule dependency version mismatch: {0} has version {1} (expected <= {2}) in {3}" , path , actualVersion , declaredVersion , dependency . Item1 . Recognizer . ToString ( ) ) ;
errors . AppendLine ( dependency . Item2 . ToString ( ) ) ;
errors . AppendLine ( message ) ;
}
return actualVersion ;
}
private static int [ ] GetRuleVersions ( TypeInfo recognizerClass , string [ ] ruleNames )
{
int [ ] versions = new int [ ruleNames . Length ] ;
IEnumerable < FieldInfo > fields = recognizerClass . DeclaredFields ;
foreach ( FieldInfo field in fields )
{
bool isStatic = field . IsStatic ;
bool isInteger = field . FieldType = = typeof ( int ) ;
if ( isStatic & & isInteger & & field . Name . StartsWith ( "RULE_" ) )
{
try
{
string name = field . Name . Substring ( "RULE_" . Length ) ;
if ( name . Length = = 0 | | ! System . Char . IsLower ( name [ 0 ] ) )
{
continue ;
}
int index = ( int ) field . GetValue ( null ) ;
if ( index < 0 | | index > = versions . Length )
{
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}." , @params ) ;
#endif
continue ;
}
MethodInfo ruleMethod = GetRuleMethod ( recognizerClass , name ) ;
if ( ruleMethod = = null )
{
object [ ] @params = new object [ ] { name , recognizerClass . Name } ;
#if false
Logger . Log ( Level . Warning , "Could not find rule method for rule ''{0}'' in recognizer {1}." , @params ) ;
#endif
continue ;
}
RuleVersionAttribute ruleVersion = ruleMethod . GetCustomAttribute < RuleVersionAttribute > ( ) ;
int version = ruleVersion ! = null ? ruleVersion . Version : 0 ;
versions [ index ] = version ;
}
catch ( ArgumentException )
{
#if false
Logger . Log ( Level . Warning , null , ex ) ;
#else
throw ;
#endif
}
catch ( MemberAccessException )
{
#if false
Logger . Log ( Level . Warning , null , ex ) ;
#else
throw ;
#endif
}
}
}
return versions ;
}
private static MethodInfo GetRuleMethod ( TypeInfo recognizerClass , string name )
{
IEnumerable < MethodInfo > declaredMethods = recognizerClass . DeclaredMethods ;
foreach ( MethodInfo method in declaredMethods )
{
if ( method . Name . Equals ( name ) & & method . GetCustomAttribute < RuleVersionAttribute > ( ) ! = null )
{
return method ;
}
}
return null ;
}
private static string [ ] GetRuleNames ( TypeInfo recognizerClass )
{
FieldInfo ruleNames = recognizerClass . DeclaredFields . First ( i = > i . Name = = "ruleNames" ) ;
return ( string [ ] ) ruleNames . GetValue ( null ) ;
}
public static IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > GetDependencies ( TypeInfo clazz )
{
IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > result = new List < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > ( ) ;
GetElementDependencies ( AsCustomAttributeProvider ( clazz ) , result ) ;
foreach ( ConstructorInfo ctor in clazz . DeclaredConstructors )
{
GetElementDependencies ( AsCustomAttributeProvider ( ctor ) , result ) ;
foreach ( ParameterInfo parameter in ctor . GetParameters ( ) )
GetElementDependencies ( AsCustomAttributeProvider ( parameter ) , result ) ;
}
foreach ( FieldInfo field in clazz . DeclaredFields )
{
GetElementDependencies ( AsCustomAttributeProvider ( field ) , result ) ;
}
foreach ( MethodInfo method in clazz . DeclaredMethods )
{
GetElementDependencies ( AsCustomAttributeProvider ( method ) , result ) ;
#if COMPACT
if ( method . ReturnTypeCustomAttributes ! = null )
GetElementDependencies ( AsCustomAttributeProvider ( method . ReturnTypeCustomAttributes ) , result ) ;
#else
if ( method . ReturnParameter ! = null )
GetElementDependencies ( AsCustomAttributeProvider ( method . ReturnParameter ) , result ) ;
#endif
foreach ( ParameterInfo parameter in method . GetParameters ( ) )
GetElementDependencies ( AsCustomAttributeProvider ( parameter ) , result ) ;
}
return result ;
}
private static void GetElementDependencies ( ICustomAttributeProvider annotatedElement , IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > result )
{
foreach ( RuleDependencyAttribute dependency in annotatedElement . GetCustomAttributes ( typeof ( RuleDependencyAttribute ) , true ) )
{
result . Add ( Tuple . Create ( dependency , annotatedElement ) ) ;
}
}
private static RuleDependencyChecker . RuleRelations ExtractRuleRelations ( TypeInfo 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 ;
}
2015-05-09 20:34:57 +08:00
foreach ( Transition transition in state . transitions )
2014-04-28 10:31:27 +08:00
{
if ( transition . TransitionType ! = TransitionType . Rule )
{
continue ;
}
RuleTransition ruleTransition = ( RuleTransition ) transition ;
relations . AddRuleInvocation ( state . ruleIndex , ruleTransition . target . ruleIndex ) ;
}
}
return relations ;
}
private static string GetSerializedATN ( TypeInfo recognizerClass )
{
FieldInfo serializedAtnField = recognizerClass . DeclaredFields . First ( i = > i . Name = = "_serializedATN" ) ;
if ( serializedAtnField ! = null )
return ( string ) serializedAtnField . GetValue ( null ) ;
if ( recognizerClass . BaseType ! = null )
return GetSerializedATN ( recognizerClass . BaseType . GetTypeInfo ( ) ) ;
return null ;
}
private sealed class RuleRelations
{
public readonly BitSet [ ] parents ;
public readonly BitSet [ ] children ;
public RuleRelations ( int ruleCount )
{
parents = new BitSet [ ruleCount ] ;
for ( int i = 0 ; i < ruleCount ; i + + )
{
parents [ i ] = new BitSet ( ) ;
}
children = new BitSet [ ruleCount ] ;
for ( int i_1 = 0 ; i_1 < ruleCount ; i_1 + + )
{
children [ i_1 ] = new BitSet ( ) ;
}
}
public bool AddRuleInvocation ( int caller , int callee )
{
if ( caller < 0 )
{
// tokens rule
return false ;
}
if ( children [ caller ] . Get ( callee ) )
{
// already added
return false ;
}
children [ caller ] . Set ( callee ) ;
parents [ callee ] . Set ( caller ) ;
return true ;
}
public BitSet GetAncestors ( int rule )
{
BitSet ancestors = new BitSet ( ) ;
ancestors . Or ( parents [ rule ] ) ;
while ( true )
{
int cardinality = ancestors . Cardinality ( ) ;
for ( int i = ancestors . NextSetBit ( 0 ) ; i > = 0 ; i = ancestors . NextSetBit ( i + 1 ) )
{
ancestors . Or ( parents [ i ] ) ;
}
if ( ancestors . Cardinality ( ) = = cardinality )
{
// nothing changed
break ;
}
}
return ancestors ;
}
public BitSet GetDescendants ( int rule )
{
BitSet descendants = new BitSet ( ) ;
descendants . Or ( children [ rule ] ) ;
while ( true )
{
int cardinality = descendants . Cardinality ( ) ;
for ( int i = descendants . NextSetBit ( 0 ) ; i > = 0 ; i = descendants . NextSetBit ( i + 1 ) )
{
descendants . Or ( children [ i ] ) ;
}
if ( descendants . Cardinality ( ) = = cardinality )
{
// nothing changed
break ;
}
}
return descendants ;
}
}
private RuleDependencyChecker ( )
{
}
#if PORTABLE
public interface ICustomAttributeProvider
{
object [ ] GetCustomAttributes ( Type attributeType , bool inherit ) ;
}
protected static ICustomAttributeProvider AsCustomAttributeProvider ( TypeInfo type )
{
return new TypeCustomAttributeProvider ( type ) ;
}
protected static ICustomAttributeProvider AsCustomAttributeProvider ( MethodBase method )
{
return new MethodBaseCustomAttributeProvider ( method ) ;
}
protected static ICustomAttributeProvider AsCustomAttributeProvider ( ParameterInfo parameter )
{
return new ParameterInfoCustomAttributeProvider ( parameter ) ;
}
protected static ICustomAttributeProvider AsCustomAttributeProvider ( FieldInfo field )
{
return new FieldInfoCustomAttributeProvider ( field ) ;
}
protected sealed class TypeCustomAttributeProvider : ICustomAttributeProvider
{
private readonly TypeInfo _provider ;
public TypeCustomAttributeProvider ( TypeInfo provider )
{
_provider = provider ;
}
public object [ ] GetCustomAttributes ( Type attributeType , bool inherit )
{
return _provider . GetCustomAttributes ( attributeType , inherit ) . ToArray ( ) ;
}
}
protected sealed class MethodBaseCustomAttributeProvider : ICustomAttributeProvider
{
private readonly MethodBase _provider ;
public MethodBaseCustomAttributeProvider ( MethodBase provider )
{
_provider = provider ;
}
public object [ ] GetCustomAttributes ( Type attributeType , bool inherit )
{
return _provider . GetCustomAttributes ( attributeType , inherit ) . ToArray ( ) ;
}
}
protected sealed class ParameterInfoCustomAttributeProvider : ICustomAttributeProvider
{
private readonly ParameterInfo _provider ;
public ParameterInfoCustomAttributeProvider ( ParameterInfo provider )
{
_provider = provider ;
}
public object [ ] GetCustomAttributes ( Type attributeType , bool inherit )
{
return _provider . GetCustomAttributes ( attributeType , inherit ) . ToArray ( ) ;
}
}
protected sealed class FieldInfoCustomAttributeProvider : ICustomAttributeProvider
{
private readonly FieldInfo _provider ;
public FieldInfoCustomAttributeProvider ( FieldInfo provider )
{
_provider = provider ;
}
public object [ ] GetCustomAttributes ( Type attributeType , bool inherit )
{
return _provider . GetCustomAttributes ( attributeType , inherit ) . ToArray ( ) ;
}
}
#else
protected static ICustomAttributeProvider AsCustomAttributeProvider ( ICustomAttributeProvider obj )
{
return obj ;
}
#endif
}
}
#else
2013-02-16 05:30:47 +08:00
using System ;
using System.Collections.Generic ;
using System.Reflection ;
using System.Security ;
using System.Text ;
using Antlr4.Runtime ;
2013-02-26 04:37:45 +08:00
using Antlr4.Runtime.Atn ;
using Antlr4.Runtime.Misc ;
2014-04-28 20:22:22 +08:00
using Antlr4.Runtime.Sharpen ;
2013-02-16 05:30:47 +08:00
namespace Antlr4.Runtime.Misc
{
2013-02-16 22:14:20 +08:00
/// <author>Sam Harwell</author>
public class RuleDependencyChecker
{
2013-02-26 05:09:31 +08:00
#if false
2014-02-17 03:33:54 +08:00
private static readonly Logger Logger = Logger . GetLogger ( typeof ( Antlr4 . Runtime . Misc . RuleDependencyChecker ) . FullName ) ;
2013-02-26 05:09:31 +08:00
#endif
2013-02-16 05:30:47 +08:00
2013-03-12 10:46:09 +08:00
private const BindingFlags AllDeclaredStaticMembers = BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static ;
private const BindingFlags AllDeclaredMembers = AllDeclaredStaticMembers | BindingFlags . Instance ;
2013-02-28 02:58:36 +08:00
private static readonly HashSet < string > checkedAssemblies = new HashSet < string > ( ) ;
2013-02-16 05:30:47 +08:00
2013-02-26 05:15:47 +08:00
public static void CheckDependencies ( Assembly assembly )
2013-02-16 22:14:20 +08:00
{
2013-02-26 05:15:47 +08:00
if ( IsChecked ( assembly ) )
2013-02-16 22:14:20 +08:00
{
return ;
}
2013-03-12 11:39:22 +08:00
2013-02-26 05:15:47 +08:00
IList < Type > typesToCheck = GetTypesToCheck ( assembly ) ;
2013-03-12 11:39:22 +08:00
List < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > dependencies = new List < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > ( ) ;
2013-02-16 22:14:20 +08:00
foreach ( Type clazz in typesToCheck )
{
2013-03-12 11:39:22 +08:00
dependencies . AddRange ( GetDependencies ( clazz ) ) ;
}
if ( dependencies . Count > 0 )
{
2014-02-17 05:25:16 +08:00
IDictionary < Type , IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > > recognizerDependencies = new Dictionary < Type , IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > > ( ) ;
2013-02-26 05:09:31 +08:00
foreach ( Tuple < RuleDependencyAttribute , ICustomAttributeProvider > dependency in dependencies )
2013-02-26 04:37:45 +08:00
{
2013-02-26 05:09:31 +08:00
Type recognizerType = dependency . Item1 . Recognizer ;
2013-02-28 06:20:24 +08:00
IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > list ;
if ( ! recognizerDependencies . TryGetValue ( recognizerType , out list ) )
2013-02-26 04:37:45 +08:00
{
2013-02-26 05:09:31 +08:00
list = new List < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > ( ) ;
2013-02-27 00:31:04 +08:00
recognizerDependencies [ recognizerType ] = list ;
2013-02-26 04:37:45 +08:00
}
2013-02-26 05:09:31 +08:00
list . Add ( dependency ) ;
2013-02-26 04:37:45 +08:00
}
2013-03-12 11:39:22 +08:00
2014-02-17 05:25:16 +08:00
foreach ( KeyValuePair < Type , IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > > entry in recognizerDependencies )
2013-02-26 04:37:45 +08:00
{
2013-03-12 11:18:46 +08:00
//processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("ANTLR 4: Validating {0} dependencies on rules in {1}.", entry.getValue().size(), entry.getKey().toString()));
2013-02-26 04:37:45 +08:00
CheckDependencies ( entry . Value , entry . Key ) ;
}
2013-02-16 22:14:20 +08:00
}
2013-02-16 05:30:47 +08:00
2013-02-26 05:15:47 +08:00
MarkChecked ( assembly ) ;
2013-02-26 04:37:45 +08:00
}
2013-02-26 05:15:47 +08:00
private static IList < Type > GetTypesToCheck ( Assembly assembly )
2013-02-26 04:37:45 +08:00
{
2013-02-26 05:15:47 +08:00
return assembly . GetTypes ( ) ;
2013-02-26 04:37:45 +08:00
}
2013-02-26 05:15:47 +08:00
private static bool IsChecked ( Assembly assembly )
2013-02-16 22:14:20 +08:00
{
2013-02-26 05:15:47 +08:00
lock ( checkedAssemblies )
2013-02-16 22:14:20 +08:00
{
2013-02-26 05:15:47 +08:00
return checkedAssemblies . Contains ( assembly . FullName ) ;
2013-02-16 22:14:20 +08:00
}
}
2013-02-16 05:30:47 +08:00
2013-02-26 05:15:47 +08:00
private static void MarkChecked ( Assembly assembly )
2013-02-16 22:14:20 +08:00
{
2013-02-26 05:15:47 +08:00
lock ( checkedAssemblies )
2013-02-16 22:14:20 +08:00
{
2013-02-26 05:15:47 +08:00
checkedAssemblies . Add ( assembly . FullName ) ;
2013-02-16 22:14:20 +08:00
}
}
2013-02-16 05:30:47 +08:00
2014-02-17 05:25:16 +08:00
private static void CheckDependencies ( IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > dependencies , Type recognizerType )
2013-02-16 22:14:20 +08:00
{
2013-02-26 04:37:45 +08:00
string [ ] ruleNames = GetRuleNames ( recognizerType ) ;
int [ ] ruleVersions = GetRuleVersions ( recognizerType , ruleNames ) ;
2014-02-17 03:33:54 +08:00
RuleDependencyChecker . RuleRelations relations = ExtractRuleRelations ( recognizerType ) ;
2013-02-26 04:37:45 +08:00
StringBuilder errors = new StringBuilder ( ) ;
2013-02-26 05:09:31 +08:00
foreach ( Tuple < RuleDependencyAttribute , ICustomAttributeProvider > dependency in dependencies )
2013-02-16 22:14:20 +08:00
{
2013-02-26 05:09:31 +08:00
if ( ! dependency . Item1 . Recognizer . IsAssignableFrom ( recognizerType ) )
2013-02-26 04:37:45 +08:00
{
continue ;
}
// this is the rule in the dependency set with the highest version number
2013-02-26 05:09:31 +08:00
int effectiveRule = dependency . Item1 . Rule ;
2013-02-26 04:37:45 +08:00
if ( effectiveRule < 0 | | effectiveRule > = ruleVersions . Length )
2013-02-16 22:14:20 +08:00
{
2014-02-17 05:25:16 +08:00
string message = string . Format ( "Rule dependency on unknown rule {0}@{1} in {2}" , dependency . Item1 . Rule , dependency . Item1 . Version , dependency . Item1 . Recognizer . ToString ( ) ) ;
2013-03-12 11:39:51 +08:00
errors . AppendLine ( dependency . Item2 . ToString ( ) ) ;
2013-03-12 11:18:46 +08:00
errors . AppendLine ( message ) ;
2013-02-16 22:14:20 +08:00
continue ;
}
2013-02-26 05:09:31 +08:00
Dependents dependents = Dependents . Self | dependency . Item1 . Dependents ;
2013-02-26 04:37:45 +08:00
ReportUnimplementedDependents ( errors , dependency , dependents ) ;
2013-02-26 04:38:30 +08:00
BitSet @checked = new BitSet ( ) ;
2014-02-17 03:33:54 +08:00
int highestRequiredDependency = CheckDependencyVersion ( errors , dependency , ruleNames , ruleVersions , effectiveRule , null ) ;
2013-02-28 02:19:52 +08:00
if ( ( dependents & Dependents . Parents ) ! = 0 )
2013-02-26 04:37:45 +08:00
{
2013-02-26 05:09:31 +08:00
BitSet parents = relations . parents [ dependency . Item1 . Rule ] ;
2014-02-17 03:33:54 +08:00
for ( int parent = parents . NextSetBit ( 0 ) ; parent > = 0 ; parent = parents . NextSetBit ( parent + 1 ) )
2013-02-26 04:37:45 +08:00
{
2013-02-26 04:38:30 +08:00
if ( parent < 0 | | parent > = ruleVersions . Length | | @checked . Get ( parent ) )
2013-02-26 04:37:45 +08:00
{
continue ;
}
2013-02-26 04:38:30 +08:00
@checked . Set ( parent ) ;
2014-02-17 03:33:54 +08:00
int required = CheckDependencyVersion ( errors , dependency , ruleNames , ruleVersions , parent , "parent" ) ;
2013-02-26 04:37:45 +08:00
highestRequiredDependency = Math . Max ( highestRequiredDependency , required ) ;
}
}
2013-02-28 02:19:52 +08:00
if ( ( dependents & Dependents . Children ) ! = 0 )
2013-02-26 04:37:45 +08:00
{
2013-02-26 05:09:31 +08:00
BitSet children = relations . children [ dependency . Item1 . Rule ] ;
2014-02-17 03:33:54 +08:00
for ( int child = children . NextSetBit ( 0 ) ; child > = 0 ; child = children . NextSetBit ( child + 1 ) )
2013-02-26 04:37:45 +08:00
{
2013-02-26 04:38:30 +08:00
if ( child < 0 | | child > = ruleVersions . Length | | @checked . Get ( child ) )
2013-02-26 04:37:45 +08:00
{
continue ;
}
2013-02-26 04:38:30 +08:00
@checked . Set ( child ) ;
2014-02-17 03:33:54 +08:00
int required = CheckDependencyVersion ( errors , dependency , ruleNames , ruleVersions , child , "child" ) ;
2013-02-26 04:37:45 +08:00
highestRequiredDependency = Math . Max ( highestRequiredDependency , required ) ;
}
}
2013-02-28 02:19:52 +08:00
if ( ( dependents & Dependents . Ancestors ) ! = 0 )
2013-02-16 22:14:20 +08:00
{
2013-02-26 05:09:31 +08:00
BitSet ancestors = relations . GetAncestors ( dependency . Item1 . Rule ) ;
2014-02-17 03:33:54 +08:00
for ( int ancestor = ancestors . NextSetBit ( 0 ) ; ancestor > = 0 ; ancestor = ancestors . NextSetBit ( ancestor + 1 ) )
2013-02-26 04:37:45 +08:00
{
2013-02-26 04:38:30 +08:00
if ( ancestor < 0 | | ancestor > = ruleVersions . Length | | @checked . Get ( ancestor ) )
2013-02-26 04:37:45 +08:00
{
continue ;
}
2013-02-26 04:38:30 +08:00
@checked . Set ( ancestor ) ;
2014-02-17 03:33:54 +08:00
int required = CheckDependencyVersion ( errors , dependency , ruleNames , ruleVersions , ancestor , "ancestor" ) ;
2013-02-26 04:37:45 +08:00
highestRequiredDependency = Math . Max ( highestRequiredDependency , required ) ;
}
2013-02-16 22:14:20 +08:00
}
2013-02-28 02:19:52 +08:00
if ( ( dependents & Dependents . Descendants ) ! = 0 )
2013-02-16 22:14:20 +08:00
{
2013-02-26 05:09:31 +08:00
BitSet descendants = relations . GetDescendants ( dependency . Item1 . Rule ) ;
2014-02-17 03:33:54 +08:00
for ( int descendant = descendants . NextSetBit ( 0 ) ; descendant > = 0 ; descendant = descendants . NextSetBit ( descendant + 1 ) )
2013-02-16 22:14:20 +08:00
{
2014-02-17 03:33:54 +08:00
if ( descendant < 0 | | descendant > = ruleVersions . Length | | @checked . Get ( descendant ) )
2013-02-26 04:37:45 +08:00
{
continue ;
}
2013-02-26 04:38:30 +08:00
@checked . Set ( descendant ) ;
2014-02-17 03:33:54 +08:00
int required = CheckDependencyVersion ( errors , dependency , ruleNames , ruleVersions , descendant , "descendant" ) ;
2013-02-26 04:37:45 +08:00
highestRequiredDependency = Math . Max ( highestRequiredDependency , required ) ;
2013-02-16 22:14:20 +08:00
}
}
2013-02-26 05:09:31 +08:00
int declaredVersion = dependency . Item1 . Version ;
2013-02-26 04:37:45 +08:00
if ( declaredVersion > highestRequiredDependency )
{
2014-02-17 05:25:16 +08:00
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 ( ) ) ;
2013-03-12 11:39:51 +08:00
errors . AppendLine ( dependency . Item2 . ToString ( ) ) ;
2013-03-12 11:18:46 +08:00
errors . AppendLine ( message ) ;
2013-02-26 04:37:45 +08:00
}
2013-02-16 22:14:20 +08:00
}
2013-02-26 04:37:45 +08:00
if ( errors . Length > 0 )
2013-02-16 22:14:20 +08:00
{
2013-02-26 04:37:45 +08:00
throw new InvalidOperationException ( errors . ToString ( ) ) ;
2013-02-16 22:14:20 +08:00
}
2013-02-26 04:37:45 +08:00
}
2014-02-17 05:25:16 +08:00
private static readonly Dependents ImplementedDependents = Dependents . Self | Dependents . Parents | Dependents . Children | Dependents . Ancestors | Dependents . Descendants ;
2013-02-26 04:37:45 +08:00
2014-02-17 05:25:16 +08:00
private static void ReportUnimplementedDependents ( StringBuilder errors , Tuple < RuleDependencyAttribute , ICustomAttributeProvider > dependency , Dependents dependents )
2013-02-26 04:37:45 +08:00
{
2013-02-26 05:09:31 +08:00
Dependents unimplemented = dependents ;
unimplemented & = ~ ImplementedDependents ;
if ( unimplemented ! = Dependents . None )
2013-02-26 04:37:45 +08:00
{
2014-02-17 05:25:16 +08:00
string message = string . Format ( "Cannot validate the following dependents of rule {0}: {1}" , dependency . Item1 . Rule , unimplemented ) ;
2013-03-12 11:18:46 +08:00
errors . AppendLine ( message ) ;
2013-02-26 04:37:45 +08:00
}
}
2014-02-17 05:25:16 +08:00
private static int CheckDependencyVersion ( StringBuilder errors , Tuple < RuleDependencyAttribute , ICustomAttributeProvider > dependency , string [ ] ruleNames , int [ ] ruleVersions , int relatedRule , string relation )
2013-02-26 04:37:45 +08:00
{
2013-02-26 05:09:31 +08:00
string ruleName = ruleNames [ dependency . Item1 . Rule ] ;
2013-02-26 04:37:45 +08:00
string path ;
if ( relation = = null )
{
path = ruleName ;
}
else
{
string mismatchedRuleName = ruleNames [ relatedRule ] ;
2014-02-17 05:25:16 +08:00
path = string . Format ( "rule {0} ({1} of {2})" , mismatchedRuleName , relation , ruleName ) ;
2013-02-26 04:37:45 +08:00
}
2013-02-26 05:09:31 +08:00
int declaredVersion = dependency . Item1 . Version ;
2013-02-26 04:37:45 +08:00
int actualVersion = ruleVersions [ relatedRule ] ;
if ( actualVersion > declaredVersion )
{
2014-02-17 05:25:16 +08:00
string message = string . Format ( "Rule dependency version mismatch: {0} has version {1} (expected <= {2}) in {3}" , path , actualVersion , declaredVersion , dependency . Item1 . Recognizer . ToString ( ) ) ;
2013-03-12 11:39:51 +08:00
errors . AppendLine ( dependency . Item2 . ToString ( ) ) ;
2013-03-12 11:18:46 +08:00
errors . AppendLine ( message ) ;
2013-02-26 04:37:45 +08:00
}
return actualVersion ;
2013-02-16 22:14:20 +08:00
}
2013-02-16 05:30:47 +08:00
2014-02-17 05:25:16 +08:00
private static int [ ] GetRuleVersions ( Type recognizerClass , string [ ] ruleNames )
2013-02-16 22:14:20 +08:00
{
int [ ] versions = new int [ ruleNames . Length ] ;
FieldInfo [ ] fields = recognizerClass . GetFields ( ) ;
foreach ( FieldInfo field in fields )
{
2013-02-26 05:09:31 +08:00
bool isStatic = field . IsStatic ;
2013-02-16 22:14:20 +08:00
bool isInteger = field . FieldType = = typeof ( int ) ;
if ( isStatic & & isInteger & & field . Name . StartsWith ( "RULE_" ) )
{
try
{
2013-02-26 05:09:31 +08:00
string name = field . Name . Substring ( "RULE_" . Length ) ;
2013-02-18 10:34:36 +08:00
if ( name . Length = = 0 | | ! System . Char . IsLower ( name [ 0 ] ) )
2013-02-16 22:14:20 +08:00
{
continue ;
}
2013-02-26 05:09:31 +08:00
int index = ( int ) field . GetValue ( null ) ;
2013-02-16 22:14:20 +08:00
if ( index < 0 | | index > = versions . Length )
{
2013-02-26 05:09:31 +08:00
#if false
2014-11-18 01:47:28 +08:00
object [ ] @params = new object [ ] { index , field . Name , recognizerClass . Name } ;
2014-02-17 03:33:54 +08:00
Logger . Log ( Level . Warning , "Rule index {0} for rule ''{1}'' out of bounds for recognizer {2}." , @params ) ;
2013-02-26 05:09:31 +08:00
#endif
2013-02-16 22:14:20 +08:00
continue ;
}
MethodInfo ruleMethod = GetRuleMethod ( recognizerClass , name ) ;
if ( ruleMethod = = null )
{
2013-02-26 05:09:31 +08:00
#if false
2014-11-18 01:47:28 +08:00
object [ ] @params = new object [ ] { name , recognizerClass . Name } ;
2014-02-17 03:33:54 +08:00
Logger . Log ( Level . Warning , "Could not find rule method for rule ''{0}'' in recognizer {1}." , @params ) ;
2013-02-26 05:09:31 +08:00
#endif
2013-02-16 22:14:20 +08:00
continue ;
}
2013-02-28 02:48:10 +08:00
RuleVersionAttribute ruleVersion = ( RuleVersionAttribute ) Attribute . GetCustomAttribute ( ruleMethod , typeof ( RuleVersionAttribute ) ) ;
2013-02-26 05:09:31 +08:00
int version = ruleVersion ! = null ? ruleVersion . Version : 0 ;
2013-02-16 22:14:20 +08:00
versions [ index ] = version ;
}
2013-02-27 04:37:20 +08:00
catch ( ArgumentException )
2013-02-16 22:14:20 +08:00
{
2013-02-26 05:09:31 +08:00
#if false
2013-02-16 22:14:20 +08:00
Logger . Log ( Level . Warning , null , ex ) ;
2013-02-27 04:37:20 +08:00
#else
throw ;
2013-02-26 05:09:31 +08:00
#endif
2013-02-16 22:14:20 +08:00
}
2013-02-27 04:37:20 +08:00
catch ( MemberAccessException )
2013-02-16 22:14:20 +08:00
{
2013-02-26 05:09:31 +08:00
#if false
2013-02-16 22:14:20 +08:00
Logger . Log ( Level . Warning , null , ex ) ;
2013-02-27 04:37:20 +08:00
#else
throw ;
2013-02-26 05:09:31 +08:00
#endif
2013-02-16 22:14:20 +08:00
}
}
}
return versions ;
}
2013-02-16 05:30:47 +08:00
2014-02-17 05:25:16 +08:00
private static MethodInfo GetRuleMethod ( Type recognizerClass , string name )
2013-02-16 22:14:20 +08:00
{
MethodInfo [ ] declaredMethods = recognizerClass . GetMethods ( ) ;
foreach ( MethodInfo method in declaredMethods )
{
2013-02-28 02:48:10 +08:00
if ( method . Name . Equals ( name ) & & Attribute . IsDefined ( method , typeof ( RuleVersionAttribute ) ) )
2013-02-16 22:14:20 +08:00
{
return method ;
}
}
return null ;
}
2013-02-16 05:30:47 +08:00
2013-02-26 05:09:31 +08:00
private static string [ ] GetRuleNames ( Type recognizerClass )
2013-02-16 22:14:20 +08:00
{
2013-02-26 05:09:31 +08:00
FieldInfo ruleNames = recognizerClass . GetField ( "ruleNames" ) ;
return ( string [ ] ) ruleNames . GetValue ( null ) ;
2013-02-16 22:14:20 +08:00
}
2013-02-16 05:30:47 +08:00
2013-02-26 05:09:31 +08:00
public static IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > GetDependencies ( Type clazz )
2013-02-16 22:14:20 +08:00
{
2014-02-17 05:25:16 +08:00
IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > result = new List < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > ( ) ;
2013-02-16 05:30:47 +08:00
2013-03-06 05:32:34 +08:00
GetElementDependencies ( AsCustomAttributeProvider ( clazz ) , result ) ;
2013-03-12 10:46:09 +08:00
foreach ( ConstructorInfo ctor in clazz . GetConstructors ( AllDeclaredMembers ) )
2013-02-26 05:09:31 +08:00
{
2013-03-06 05:32:34 +08:00
GetElementDependencies ( AsCustomAttributeProvider ( ctor ) , result ) ;
2013-02-26 05:09:31 +08:00
foreach ( ParameterInfo parameter in ctor . GetParameters ( ) )
2013-03-06 05:32:34 +08:00
GetElementDependencies ( AsCustomAttributeProvider ( parameter ) , result ) ;
2013-02-26 05:09:31 +08:00
}
2013-02-16 05:30:47 +08:00
2013-03-12 10:46:09 +08:00
foreach ( FieldInfo field in clazz . GetFields ( AllDeclaredMembers ) )
2013-02-26 05:09:31 +08:00
{
2013-03-06 05:32:34 +08:00
GetElementDependencies ( AsCustomAttributeProvider ( field ) , result ) ;
2013-02-26 05:09:31 +08:00
}
2013-02-16 05:30:47 +08:00
2013-03-12 10:46:09 +08:00
foreach ( MethodInfo method in clazz . GetMethods ( AllDeclaredMembers ) )
2013-02-26 05:09:31 +08:00
{
2013-03-06 05:32:34 +08:00
GetElementDependencies ( AsCustomAttributeProvider ( method ) , result ) ;
2014-04-28 04:41:36 +08:00
#if COMPACT
2013-04-18 09:15:57 +08:00
if ( method . ReturnTypeCustomAttributes ! = null )
GetElementDependencies ( AsCustomAttributeProvider ( method . ReturnTypeCustomAttributes ) , result ) ;
#else
2013-02-26 05:09:31 +08:00
if ( method . ReturnParameter ! = null )
2013-03-06 05:32:34 +08:00
GetElementDependencies ( AsCustomAttributeProvider ( method . ReturnParameter ) , result ) ;
2013-04-18 09:15:57 +08:00
#endif
2013-02-16 05:30:47 +08:00
2013-02-26 05:09:31 +08:00
foreach ( ParameterInfo parameter in method . GetParameters ( ) )
2013-03-06 05:32:34 +08:00
GetElementDependencies ( AsCustomAttributeProvider ( parameter ) , result ) ;
2013-02-16 22:14:20 +08:00
}
2013-02-26 05:09:31 +08:00
2013-02-16 22:14:20 +08:00
return result ;
}
2013-02-16 05:30:47 +08:00
2014-02-17 05:25:16 +08:00
private static void GetElementDependencies ( ICustomAttributeProvider annotatedElement , IList < Tuple < RuleDependencyAttribute , ICustomAttributeProvider > > result )
2013-02-16 22:14:20 +08:00
{
2013-02-26 05:09:31 +08:00
foreach ( RuleDependencyAttribute dependency in annotatedElement . GetCustomAttributes ( typeof ( RuleDependencyAttribute ) , true ) )
2013-02-16 22:14:20 +08:00
{
2013-02-26 05:09:31 +08:00
result . Add ( Tuple . Create ( dependency , annotatedElement ) ) ;
2013-02-16 22:14:20 +08:00
}
}
2013-02-16 05:30:47 +08:00
2014-02-17 05:25:16 +08:00
private static RuleDependencyChecker . RuleRelations ExtractRuleRelations ( Type recognizer )
2013-02-26 04:37:45 +08:00
{
string serializedATN = GetSerializedATN ( recognizer ) ;
if ( serializedATN = = null )
{
return null ;
}
2014-02-17 04:51:37 +08:00
ATN atn = new ATNDeserializer ( ) . Deserialize ( serializedATN . ToCharArray ( ) ) ;
2014-02-17 03:33:54 +08:00
RuleDependencyChecker . RuleRelations relations = new RuleDependencyChecker . RuleRelations ( atn . ruleToStartState . Length ) ;
2013-02-26 04:37:45 +08:00
foreach ( ATNState state in atn . states )
{
if ( ! state . epsilonOnlyTransitions )
{
continue ;
}
2015-05-09 20:34:57 +08:00
foreach ( Transition transition in state . transitions )
2013-02-26 04:37:45 +08:00
{
if ( transition . TransitionType ! = TransitionType . Rule )
{
continue ;
}
RuleTransition ruleTransition = ( RuleTransition ) transition ;
relations . AddRuleInvocation ( state . ruleIndex , ruleTransition . target . ruleIndex ) ;
}
}
return relations ;
}
2013-02-26 05:09:31 +08:00
private static string GetSerializedATN ( Type recognizerClass )
2013-02-26 04:37:45 +08:00
{
2013-03-12 10:46:09 +08:00
FieldInfo serializedAtnField = recognizerClass . GetField ( "_serializedATN" , AllDeclaredStaticMembers ) ;
2013-02-26 05:09:31 +08:00
if ( serializedAtnField ! = null )
return ( string ) serializedAtnField . GetValue ( null ) ;
if ( recognizerClass . BaseType ! = null )
return GetSerializedATN ( recognizerClass . BaseType ) ;
return null ;
2013-02-26 04:37:45 +08:00
}
private sealed class RuleRelations
{
2013-02-26 05:09:31 +08:00
public readonly BitSet [ ] parents ;
2013-02-26 04:37:45 +08:00
2013-02-26 05:09:31 +08:00
public readonly BitSet [ ] children ;
2013-02-26 04:37:45 +08:00
public RuleRelations ( int ruleCount )
{
parents = new BitSet [ ruleCount ] ;
for ( int i = 0 ; i < ruleCount ; i + + )
{
parents [ i ] = new BitSet ( ) ;
}
children = new BitSet [ ruleCount ] ;
for ( int i_1 = 0 ; i_1 < ruleCount ; i_1 + + )
{
children [ i_1 ] = new BitSet ( ) ;
}
}
public bool AddRuleInvocation ( int caller , int callee )
{
if ( caller < 0 )
{
// tokens rule
return false ;
}
if ( children [ caller ] . Get ( callee ) )
{
// already added
return false ;
}
children [ caller ] . Set ( callee ) ;
parents [ callee ] . Set ( caller ) ;
return true ;
}
public BitSet GetAncestors ( int rule )
{
BitSet ancestors = new BitSet ( ) ;
ancestors . Or ( parents [ rule ] ) ;
while ( true )
{
int cardinality = ancestors . Cardinality ( ) ;
for ( int i = ancestors . NextSetBit ( 0 ) ; i > = 0 ; i = ancestors . NextSetBit ( i + 1 ) )
{
ancestors . Or ( parents [ i ] ) ;
}
if ( ancestors . Cardinality ( ) = = cardinality )
{
// nothing changed
break ;
}
}
return ancestors ;
}
public BitSet GetDescendants ( int rule )
{
BitSet descendants = new BitSet ( ) ;
descendants . Or ( children [ rule ] ) ;
while ( true )
{
int cardinality = descendants . Cardinality ( ) ;
for ( int i = descendants . NextSetBit ( 0 ) ; i > = 0 ; i = descendants . NextSetBit ( i + 1 ) )
{
descendants . Or ( children [ i ] ) ;
}
if ( descendants . Cardinality ( ) = = cardinality )
{
// nothing changed
break ;
}
}
return descendants ;
}
}
2013-02-26 03:23:46 +08:00
private RuleDependencyChecker ( )
2013-02-16 22:14:20 +08:00
{
}
2013-03-06 05:32:34 +08:00
#if PORTABLE
public interface ICustomAttributeProvider
{
object [ ] GetCustomAttributes ( Type attributeType , bool inherit ) ;
}
protected static ICustomAttributeProvider AsCustomAttributeProvider ( Type type )
{
return new TypeCustomAttributeProvider ( type ) ;
}
protected static ICustomAttributeProvider AsCustomAttributeProvider ( MethodBase method )
{
return new MethodBaseCustomAttributeProvider ( method ) ;
}
protected static ICustomAttributeProvider AsCustomAttributeProvider ( ParameterInfo parameter )
{
return new ParameterInfoCustomAttributeProvider ( parameter ) ;
}
protected static ICustomAttributeProvider AsCustomAttributeProvider ( FieldInfo field )
{
return new FieldInfoCustomAttributeProvider ( field ) ;
}
protected sealed class TypeCustomAttributeProvider : ICustomAttributeProvider
{
private readonly Type _provider ;
public TypeCustomAttributeProvider ( Type provider )
{
_provider = provider ;
}
public object [ ] GetCustomAttributes ( Type attributeType , bool inherit )
{
return Attribute . GetCustomAttributes ( _provider , attributeType , inherit ) ;
}
}
protected sealed class MethodBaseCustomAttributeProvider : ICustomAttributeProvider
{
private readonly MethodBase _provider ;
public MethodBaseCustomAttributeProvider ( MethodBase provider )
{
_provider = provider ;
}
public object [ ] GetCustomAttributes ( Type attributeType , bool inherit )
{
return Attribute . GetCustomAttributes ( _provider , attributeType , inherit ) ;
}
}
protected sealed class ParameterInfoCustomAttributeProvider : ICustomAttributeProvider
{
private readonly ParameterInfo _provider ;
public ParameterInfoCustomAttributeProvider ( ParameterInfo provider )
{
_provider = provider ;
}
public object [ ] GetCustomAttributes ( Type attributeType , bool inherit )
{
return Attribute . GetCustomAttributes ( _provider , attributeType , inherit ) ;
}
}
protected sealed class FieldInfoCustomAttributeProvider : ICustomAttributeProvider
{
private readonly FieldInfo _provider ;
public FieldInfoCustomAttributeProvider ( FieldInfo provider )
{
_provider = provider ;
}
public object [ ] GetCustomAttributes ( Type attributeType , bool inherit )
{
return Attribute . GetCustomAttributes ( _provider , attributeType , inherit ) ;
}
}
#else
protected static ICustomAttributeProvider AsCustomAttributeProvider ( ICustomAttributeProvider obj )
{
return obj ;
}
#endif
2013-02-16 22:14:20 +08:00
}
2013-02-16 05:30:47 +08:00
}
2014-04-28 10:31:27 +08:00
#endif