using System;
using System.Xml;
using System.Collections;
using System.Collections.Specialized;
using AnticipatingMinds.Genesis.CodeDOM;
using AnticipatingMinds.CommonUIControls;
using AnticipatingMinds.Genesis.CodeDOM.Utilities;
using AnticipatingMinds.Genesis.KnowledgeManagement;
namespace AnticipatingMinds.KnowledgePack.Threading{
/// <summary>
/// Summary description for AvoidSelfManagedThreads.
/// </summary>
public class ExcessiveLockingRuleTemplate : RuleTemplate
{
public ExcessiveLockingRuleTemplate(string templateId, IDictionary templateProperties):base(templateId,templateProperties)
{
KnowledgePackLicense.Validate();
}
public override string Name
{
get
{
return ResourceManager.GetLocalizedString("ExcessiveLockingRuleTemplate|Name");
}
}
public override string Description
{
get
{
return ResourceManager.GetLocalizedString("ExcessiveLockingRuleTemplate|Description");
}
}
public override Rule CreateRule(string ruleId, IDictionary ruleProperties)
{
return new ExcessiveLockingRule(ruleId,Id,ruleProperties);
}
public override PropertyPage[] GetRulePropertiesUI(IDictionary ruleProperties)
{
PropertyPage[] pages = new PropertyPage[1];
pages[0] = new ExcessiveLockingPropertiesPage(ruleProperties);
return pages;
}
}
/// <summary>
/// Avoid using System.Threading.Thread class unless you change thread priority.
/// </summary>
/// <remarks>
/// Avoid using System.Threading.Thread class unless you change thread priority. Instead prefer usage
/// of system thread pool (ThreadPool class).
/// </remarks>
public class ExcessiveLockingRule : Rule
{
public new class PropertyName : Rule.PropertyName
{
public const string MaxOuterLoops = "MaxOuterLoops";
public const string MaxInnerLoops = "MaxInnerLoops";
public const string MaxStatements = "MaxStatements";
public const string MaxNestedLocks = "MaxNestedLocks";
public const string MaxMembersWithLocksRatio = "MaxMembersWithLocksRatio";
public const string MaxCallsToMembers = "MaxCallsToMembers";
}
internal ExcessiveLockingRule(string id, string templateId, IDictionary ruleProperties) : base(id,templateId,ruleProperties)
{
}
private class RuleData
{
public ArrayList TypeMembers = new ArrayList();
public ArrayList TypeMembersWithLockQty = new ArrayList();
public Hashtable LockStats = new Hashtable();
}
private class LockStats
{
public int OuterLoops = 0;
public int InnerLoops = 0;
public int ProtectedStatementsQty = 0;
public int NestedLocksQty = 0;
public int CallsToMembersQty = 0;
}
public CodeDomWalker.WalkerCallbackReturn CodeWalker(CodeElement codeElement,CodeDomWalker.CallBackNotificationType notificationType, CodeDomWalkerContext walkerContext,object applicationData)
{
if(notificationType == CodeDomWalker.CallBackNotificationType.OnElement)
{
}
return CodeDomWalker.WalkerCallbackReturn.Next;
}
public override RuleViolation[] Analyze(object targetedObject, System.Threading.ManualResetEvent cancelAnalysisEvent)
{
if(targetedObject is CodeTypeDeclaration)
{
RuleData ruleData = new RuleData();
CodeDomWalker.WalkCodeElement(targetedObject as CodeTypeDeclaration,new CodeDomWalker.WalkerCallback(TypeDeclarationAnalyzer),ruleData);
RuleViolationCollection violations = new RuleViolationCollection();
int classLockingRation = (int) (((float)ruleData.TypeMembersWithLockQty.Count/(float)ruleData.TypeMembers.Count)*100.0);
if(classLockingRation > MaxMembersWithLocksRatio)
{
RuleViolation violation = new RuleViolation(this,ResourceManager.GetLocalizedString("ExcessiveLockingRuleViolation|LockMembersRatioIsTooHigh",classLockingRation,(targetedObject as CodeTypeDeclaration).Name,MaxMembersWithLocksRatio),targetedObject as CodeTypeDeclaration);
violation.Severity = RuleViolation.ViolationSeverity.Suggestion;
violations.Add(violation);
}
foreach(CodeElement lockStatement in ruleData.LockStats.Keys)
{
LockStats lockStats = ruleData.LockStats[lockStatement] as LockStats;
if(lockStats.InnerLoops > MaxInnerLoops)
{
RuleViolation violation = new RuleViolation(this,ResourceManager.GetLocalizedString("ExcessiveLockingRuleViolation|ExcessiveLocking|InnerLoops",lockStats.InnerLoops,MaxInnerLoops),lockStatement);
violation.Severity = RuleViolation.ViolationSeverity.Suggestion;
violations.Add(violation);
}
if(lockStats.NestedLocksQty > MaxNestedLocks)
{
RuleViolation violation = new RuleViolation(this,ResourceManager.GetLocalizedString("ExcessiveLockingRuleViolation|ExcessiveLocking|NestedLocks",lockStats.NestedLocksQty,MaxNestedLocks),lockStatement);
violation.Severity = RuleViolation.ViolationSeverity.Suggestion;
violations.Add(violation);
}
if(lockStats.OuterLoops > MaxOuterLoops)
{
RuleViolation violation = new RuleViolation(this,ResourceManager.GetLocalizedString("ExcessiveLockingRuleViolation|ExcessiveLocking|OuterLoops",lockStats.OuterLoops,MaxOuterLoops),lockStatement);
violation.Severity = RuleViolation.ViolationSeverity.Suggestion;
violations.Add(violation);
}
if(lockStats.CallsToMembersQty > MaxCallsToMembers)
{
RuleViolation violation = new RuleViolation(this,ResourceManager.GetLocalizedString("ExcessiveLockingRuleViolation|ExcessiveLocking|CallsToMembers",lockStats.CallsToMembersQty,MaxCallsToMembers),lockStatement);
violation.Severity = RuleViolation.ViolationSeverity.Suggestion;
violations.Add(violation);
}
if(lockStats.ProtectedStatementsQty > MaxStatements)
{
RuleViolation violation = new RuleViolation(this,ResourceManager.GetLocalizedString("ExcessiveLockingRuleViolation|ExcessiveLocking|ProtectedStatements",lockStats.ProtectedStatementsQty,MaxStatements),lockStatement);
violation.Severity = RuleViolation.ViolationSeverity.Suggestion;
violations.Add(violation);
}
}
return violations.ToArray();
}
return emptyViolationsList;
}
public CodeDomWalker.WalkerCallbackReturn TypeDeclarationAnalyzer(CodeElement codeElement,CodeDomWalker.CallBackNotificationType notificationType, CodeDomWalkerContext walkerContext,object applicationData)
{
if(notificationType == CodeDomWalker.CallBackNotificationType.OnElement)
{
if(codeElement is CodeTypeDeclaration)
return CodeDomWalker.WalkerCallbackReturn.Next;
if(codeElement is CodeTypeMethodDeclaration ||
codeElement is CodeTypeOperatorDeclaration ||
codeElement is CodeTypePropertyDeclaration)
{
RuleData ruleData = applicationData as RuleData;
if(!ruleData.TypeMembers.Contains(codeElement))
ruleData.TypeMembers.Add(codeElement);
return CodeDomWalker.WalkerCallbackReturn.Next;
}
if(codeElement is CodeLockStatement)
{
if(!IsCodeElementInRuleApplicabilityScope(CodeTypeMemberUtils.GetContainingTypeMember(codeElement as CodeLockStatement)))
return CodeDomWalker.WalkerCallbackReturn.Next;
LockStats lockStats = new LockStats();
CodeElementTrace trace = CodeElementTrace.GetCodeElementTrace(codeElement);
RuleData ruleData = applicationData as RuleData;
for(int traceFrameIndex = trace.Trace.Length-1; traceFrameIndex >= 0;traceFrameIndex--)
{
CodeElement traceElement = trace.Trace[traceFrameIndex];
if(traceElement is CodeTypeMemberDeclaration)
{
if(!ruleData.TypeMembersWithLockQty.Contains(traceElement))
ruleData.TypeMembersWithLockQty.Add(traceElement);
break;
}
if(traceElement is CodeIterationStatements)
{
lockStats.OuterLoops++;
}
}
ruleData.LockStats.Add(codeElement,lockStats);
CodeDomWalker.WalkCodeElement((codeElement as CodeLockStatement).Statement,new CodeDomWalker.WalkerCallback(LockStatementAnalyzer),lockStats);
return CodeDomWalker.WalkerCallbackReturn.Next;
}
if(codeElement is CodeTypeMemberDeclaration)
return CodeDomWalker.WalkerCallbackReturn.NextSibling;
else
return CodeDomWalker.WalkerCallbackReturn.Next;
}
return CodeDomWalker.WalkerCallbackReturn.Next;
}
public CodeDomWalker.WalkerCallbackReturn LockStatementAnalyzer(CodeElement codeElement,CodeDomWalker.CallBackNotificationType notificationType, CodeDomWalkerContext walkerContext,object applicationData)
{
if(notificationType == CodeDomWalker.CallBackNotificationType.OnElement)
{
LockStats lockStats = applicationData as LockStats;
if(codeElement is CodeStatement && !(codeElement is CodeStatementBlock))
lockStats.ProtectedStatementsQty++;
if(codeElement is CodeIterationStatements)
lockStats.InnerLoops++;
if(codeElement is CodeLockStatement)
lockStats.NestedLocksQty++;
if(codeElement is CodeMethodInvokeExpression)
{
CodeNamedReferenceExpression referencedMethod = (codeElement as CodeMethodInvokeExpression).MethodReferenceExpression as CodeNamedReferenceExpression;
if(referencedMethod != null && (referencedMethod.TargetObject == null || referencedMethod.TargetObject is CodeThisReferenceExpression))
lockStats.CallsToMembersQty++;
}
}
return CodeDomWalker.WalkerCallbackReturn.Next;
}
private RuleViolation[] AnalyzeLockStatement(CodeLockStatement lockStatement)
{
return emptyViolationsList;
}
public override void Correct(RuleViolationCorrection[] requestedCorrections, AnticipatingMinds.Genesis.Effectors.CodeEffector codeEffector, System.Threading.ManualResetEvent cancelCorrectionEvent)
{
// TODO: Add ExcessiveLockingRule.Correct implementation
}
public override Type[] TargetedCodeElements
{
get
{
return targtedCodeElements;
}
}
public int MaxOuterLoops
{
get
{
return (int) GetProperty(PropertyName.MaxOuterLoops,0);
}
set
{
SetProperty(PropertyName.MaxOuterLoops,value);
}
}
public int MaxInnerLoops
{
get
{
return (int) GetProperty(PropertyName.MaxInnerLoops,0);
}
set
{
SetProperty(PropertyName.MaxInnerLoops,value);
}
}
public int MaxStatements
{
get
{
return (int) GetProperty(PropertyName.MaxStatements,0);
}
set
{
SetProperty(PropertyName.MaxStatements,value);
}
}
public int MaxNestedLocks
{
get
{
return (int) GetProperty(PropertyName.MaxNestedLocks,0);
}
set
{
SetProperty(PropertyName.MaxNestedLocks,value);
}
}
public int MaxMembersWithLocksRatio
{
get
{
return (int) GetProperty(PropertyName.MaxMembersWithLocksRatio,0);
}
set
{
SetProperty(PropertyName.MaxMembersWithLocksRatio,value);
}
}
public int MaxCallsToMembers
{
get
{
return (int) GetProperty(PropertyName.MaxCallsToMembers,0);
}
set
{
SetProperty(PropertyName.MaxCallsToMembers,value);
}
}
public override Type[] ApplicableApplicabilityScopeTypes
{
get
{
return applicableApplicabilityScopeTypes;
}
}
private Type[] targtedCodeElements = new Type[1] {typeof(CodeTypeDeclaration)};
private static RuleViolation[] emptyViolationsList = new RuleViolation[0];
private static Type[] applicableApplicabilityScopeTypes = {typeof(MethodApplicabilityScope),typeof(PropertyApplicabilityScope),typeof(EventApplicabilityScope),typeof(FileApplicabilityScope)};
}
}
|