using System;
using System.Collections;
using AnticipatingMinds.Genesis.KnowledgeManagement;
using AnticipatingMinds.Genesis.CodeDOM;
using AnticipatingMinds.Genesis.CodeDOM.Utilities;
using AnticipatingMinds.Genesis.CodeParser;
using System.Runtime.Serialization;
namespace AnticipatingMinds.KnowledgePack.ErrorHandling{
public class UsingTryCatchAroundSpecificReferencesTemplate : RuleTemplate
{
public UsingTryCatchAroundSpecificReferencesTemplate(string templateId, IDictionary templateProperties):base(templateId,templateProperties)
{
KnowledgePackLicense.Validate();
}
public override string Name
{
get
{
return ResourceManager.GetLocalizedString("UsingTryCatchAroundSpecificReferencesTemplate|Name");
}
}
public override string Description
{
get
{
return ResourceManager.GetLocalizedString("UsingTryCatchAroundSpecificReferencesTemplate|Description");
}
}
public override Rule CreateRule(string ruleId, IDictionary ruleProperties)
{
return new UsingTryCatchAroundSpecificReferencesRule(ruleId, Id, ruleProperties);
}
public override AnticipatingMinds.CommonUIControls.PropertyPage[] GetRulePropertiesUI(IDictionary ruleProperties)
{
AnticipatingMinds.CommonUIControls.PropertyPage[] pages = new AnticipatingMinds.CommonUIControls.PropertyPage[1];
pages[0] = new TryCatchSpecificReferencePropertyPage(ruleProperties);
return pages;
}
}
public class UsingTryCatchAroundSpecificReferencesRule : Rule
{
internal UsingTryCatchAroundSpecificReferencesRule(string id, string templateId, IDictionary ruleProperties) : base(id,templateId,ruleProperties)
{
}
public override Type[] TargetedCodeElements
{
get
{
return targetedCodeElements;
}
}
#region Rule Property
public new class PropertyName : Rule.PropertyName
{
public const string SpecificTypeList = "SpecificTypeList";
}
private ArrayList SpecificTypeList
{
get
{
return GetProperty(PropertyName.SpecificTypeList, new ArrayList()) as ArrayList;
}
set
{
SetProperty(PropertyName.SpecificTypeList, value);
}
}
#endregion
private class RuleData
{
public RuleViolationCollection violations = new RuleViolationCollection();
public SpecificType SpecificType = null;
public CodeTypeMemberDeclaration MemberDeclaration = null;
public CodeTryStatement TryCatchStatement = null;
public ArrayList ExistingReferenceObject = new ArrayList();
public CodeTypeDeclaration CurrectTypeDeclaration = null;
}
#region Analyze
public override RuleViolation[] Analyze(object codeElement, System.Threading.ManualResetEvent cancelAnalysisEvent)
{
CodeTypeMemberDeclaration memberDeclaration = codeElement as CodeTypeMemberDeclaration;
if(memberDeclaration == null) return emptyViolationsList;
if(!IsCodeElementInRuleApplicabilityScope(CodeTypeMemberUtils.GetContainingTypeMember(memberDeclaration)))
return emptyViolationsList;
RuleData ruleData = new RuleData();
CodeElement typeDeclaration = memberDeclaration.Parent;
while(typeDeclaration != null && !(typeDeclaration is CodeTypeDeclaration))
{
typeDeclaration = typeDeclaration.Parent;
}
ruleData.CurrectTypeDeclaration = typeDeclaration as CodeTypeDeclaration;
ruleData.MemberDeclaration = memberDeclaration;
if(this.SpecificTypeList.Count == 0)
{
#region If rule config empty
if(memberDeclaration is CodeTypeMethodDeclaration
&& (memberDeclaration as CodeTypeMethodDeclaration).Statements != null
&& (memberDeclaration as CodeTypeMethodDeclaration).Statements.Statements.Count != 0
&& AnalizeforTryCatchStatement((memberDeclaration as CodeTypeMethodDeclaration).Statements)
)
{
CreateViolation(ruleData, (memberDeclaration as CodeTypeMethodDeclaration).Statements);
}
else if(memberDeclaration is CodeTypePropertyDeclaration)
{
if((memberDeclaration as CodeTypePropertyDeclaration).SetAccessorStatements.Statements != null
&& (memberDeclaration as CodeTypePropertyDeclaration).SetAccessorStatements.Statements.Count != 0
&& AnalizeforTryCatchStatement((memberDeclaration as CodeTypePropertyDeclaration).SetAccessorStatements)
)
{
CreateViolation(ruleData, (memberDeclaration as CodeTypePropertyDeclaration).SetAccessorStatements);
}
if((memberDeclaration as CodeTypePropertyDeclaration).GetAccessorStatements.Statements != null
&& (memberDeclaration as CodeTypePropertyDeclaration).GetAccessorStatements.Statements.Count != 0
&& AnalizeforTryCatchStatement((memberDeclaration as CodeTypePropertyDeclaration).GetAccessorStatements)
)
{
CreateViolation(ruleData, (memberDeclaration as CodeTypePropertyDeclaration).GetAccessorStatements);
}
}
else if(memberDeclaration is CodeTypeEventDeclaration)
{
if((memberDeclaration as CodeTypeEventDeclaration).RemoveAccessorStatements != null
&& (memberDeclaration as CodeTypeEventDeclaration).RemoveAccessorStatements.Statements.Count != 0
&& AnalizeforTryCatchStatement((memberDeclaration as CodeTypeEventDeclaration).RemoveAccessorStatements)
)
{
CreateViolation(ruleData, (memberDeclaration as CodeTypeEventDeclaration).RemoveAccessorStatements);
}
if((memberDeclaration as CodeTypeEventDeclaration).AddAccessorStatements != null
&& (memberDeclaration as CodeTypeEventDeclaration).AddAccessorStatements.Statements.Count != 0
&& AnalizeforTryCatchStatement((memberDeclaration as CodeTypeEventDeclaration).AddAccessorStatements)
)
{
CreateViolation(ruleData, (memberDeclaration as CodeTypeEventDeclaration).AddAccessorStatements);
}
}
#endregion
}
else
{
if(memberDeclaration is CodeTypeMethodDeclaration
&& (memberDeclaration as CodeTypeMethodDeclaration).Statements != null
)
{
ruleData.ExistingReferenceObject.Clear();
CodeDomWalker.WalkCodeElement((memberDeclaration as CodeTypeMethodDeclaration).Statements ,new CodeDomWalker.WalkerCallback(AnalyzeMemberDeclaration), ruleData);
}
else if(memberDeclaration is CodeTypePropertyDeclaration)
{
if((memberDeclaration as CodeTypePropertyDeclaration).GetAccessorStatements != null)
{
ruleData.ExistingReferenceObject.Clear();
CodeDomWalker.WalkCodeElement((memberDeclaration as CodeTypePropertyDeclaration).GetAccessorStatements ,new CodeDomWalker.WalkerCallback(AnalyzeMemberDeclaration), ruleData);
}
if((memberDeclaration as CodeTypePropertyDeclaration).SetAccessorStatements != null)
{
ruleData.ExistingReferenceObject.Clear();
CodeDomWalker.WalkCodeElement((memberDeclaration as CodeTypePropertyDeclaration).SetAccessorStatements ,new CodeDomWalker.WalkerCallback(AnalyzeMemberDeclaration), ruleData);
}
}
else if(memberDeclaration is CodeTypeEventDeclaration)
{
if((memberDeclaration as CodeTypeEventDeclaration).AddAccessorStatements != null)
{
ruleData.ExistingReferenceObject.Clear();
CodeDomWalker.WalkCodeElement((memberDeclaration as CodeTypeEventDeclaration).AddAccessorStatements ,new CodeDomWalker.WalkerCallback(AnalyzeMemberDeclaration), ruleData);
}
if((memberDeclaration as CodeTypeEventDeclaration).RemoveAccessorStatements != null)
{
ruleData.ExistingReferenceObject.Clear();
CodeDomWalker.WalkCodeElement((memberDeclaration as CodeTypeEventDeclaration).RemoveAccessorStatements ,new CodeDomWalker.WalkerCallback(AnalyzeMemberDeclaration), ruleData);
}
}
}
if(ruleData.violations.Count != 0)
return ruleData.violations.ToArray();
else
return emptyViolationsList;
}
private bool AnalizeforTryCatchStatement(CodeStatementBlock memberBlock)
{
if(memberBlock == null)
{
return false; // no create violation
}
if(memberBlock.Statements.Count == 1
&& memberBlock.Statements[0] is CodeTryStatement
)
{
return false;// no create violation
}
return true; // create violation
}
private CodeDomWalker.WalkerCallbackReturn AnalyzeMemberDeclaration(CodeElement codeElement,CodeDomWalker.CallBackNotificationType notificationType, CodeDomWalkerContext walkerContext,object applicationData)
{
if(notificationType != CodeDomWalker.CallBackNotificationType.OnElement)
{
return CodeDomWalker.WalkerCallbackReturn.Next;
}
RuleData ruleData = applicationData as RuleData;
if(codeElement is CodeReferenceExpression
&& IsSpecificType((codeElement as CodeReferenceExpression).ExpressionType, ruleData, codeElement))
{
if(!AnalyzeForInsideTryStatement(codeElement, ruleData) && !AnalizeSafeReference(codeElement as CodeReferenceExpression))
{
CreateViolation(ruleData, codeElement);
}
}
if(codeElement is CodeObjectCreateExpression
&& IsSpecificType((codeElement as CodeObjectCreateExpression).CreateType.TypeInfo , ruleData, codeElement))
{
if(!AnalyzeForInsideTryStatement(codeElement, ruleData))
{
CreateViolation(ruleData, codeElement);
}
}
return CodeDomWalker.WalkerCallbackReturn.Next;
}
private bool AnalizeSafeReference(CodeReferenceExpression parameterReference)
{
CodeElement child = parameterReference;
//skip parenthethies and type casts
while(
child.Parent is CodeParenthesizedExpression ||
child.Parent is CodeTypeCastExpression )
{
child = child.Parent;
}
if((child.Parent is CodeNamedReferenceExpression)
&& (child.Parent as CodeNamedReferenceExpression).TargetObject == child)
{
return false;
}
if(child.Parent is CodeArgument
|| child.Parent is CodeReturnStatement)
{
return true;
}
if(child.Parent is CodeBinaryExpression && (child.Parent as CodeBinaryExpression).RightOperand == child)
{
return true;
}
if(child.Parent is CodeVariableDeclarationMember)
{
return true;
}
if(child.Parent is CodeBinaryExpression
&& (child.Parent as CodeBinaryExpression).LeftOperand == child
&& ((child.Parent as CodeBinaryExpression).Operator == CodeBinaryOperatorType.Equality || (child.Parent as CodeBinaryExpression).Operator == CodeBinaryOperatorType.Assign)
)
{
return true;
}
return false;
}
private bool AnalyzeForInsideTryStatement(CodeElement codeElement, RuleData ruleData)
{
ruleData.TryCatchStatement = null;
CodeElementTrace trace = CodeElementTrace.GetCodeElementTrace(codeElement);
for(int traceFrameIndex = trace.Trace.Length-1;traceFrameIndex>=0; traceFrameIndex--)
{
if(trace.Trace[traceFrameIndex] is CodeTryStatement)
{
CodeTryStatement tryStatement = trace.Trace[traceFrameIndex] as CodeTryStatement;
if(ruleData.TryCatchStatement == null)ruleData.TryCatchStatement = tryStatement;
foreach(CodeCatchClause catchClause in tryStatement.CatchClauses)
{
if(catchClause.CatchExceptionType != null && catchClause.CatchExceptionType.TypeInfo != null)
{
foreach(CorrectionRecommendation correctionRecommendation in ruleData.SpecificType.RequireExceptionTypes)
{
if(correctionRecommendation == null) continue;
if(correctionRecommendation.Class == catchClause.CatchExceptionType.TypeInfo.FullName){return true;}
}
}
}
}
if(trace.Trace[traceFrameIndex].Equals(ruleData.MemberDeclaration)) break;
}
return false;
}
private bool IsSpecificType(CodeTypeInfo typeInfo, RuleData ruleData, CodeElement element)
{
if(typeInfo == null) return false;
CodeAssemblyTypeManager typeManager = element.GetAssemblyTypeManager();
ruleData.SpecificType = null;
foreach(SpecificType specificType in this.SpecificTypeList)
{
if(specificType == null) continue;
if(ruleData.CurrectTypeDeclaration != null && ruleData.CurrectTypeDeclaration.FullName == specificType.Class) continue;
if( typeManager.IsTypeSubclassOf((typeInfo.IsArray) ? typeInfo.FullName.Replace("[]", "") : typeInfo.FullName, specificType.Class) )
{
ruleData.SpecificType = specificType;
if(specificType.Member.Length != 0)
{
if(element.Parent is CodeParenthesizedExpression)
{
element = element.Parent;
}
if(element.Parent is CodeUnresolvedReferenceExpression
&& (element.Parent as CodeUnresolvedReferenceExpression).Name == specificType.Member)
{
return true;
}
else{ return false;}
}
else
{
return true;
}
}
}
return false;
}
private bool CurrentTypeViolationExists(CodeElement codeElement, RuleData ruleData)
{
CodeElement currentObjectToCompare = null;
if(codeElement is CodeObjectCreateExpression)
{
if(codeElement.Parent is CodeVariableDeclarationMember)
{
currentObjectToCompare = codeElement.Parent;
}
if(codeElement.Parent is CodeBinaryExpression
&& (codeElement.Parent as CodeBinaryExpression).RightOperand == codeElement
&& (codeElement.Parent as CodeBinaryExpression).Operator == CodeBinaryOperatorType.Assign
)
{
codeElement = (codeElement.Parent as CodeBinaryExpression).LeftOperand;
}
}
if(currentObjectToCompare == null)
{
if(codeElement is CodeVariableReferenceExpression)
{
foreach(CodeVariableDeclarationMember member in (codeElement as CodeVariableReferenceExpression).VariableDeclaration.DeclaredVariables)
{
if((codeElement as CodeVariableReferenceExpression).VariableName == member.Name)
currentObjectToCompare = member;
}
}
else if(codeElement is CodeMethodParameterReferenceExpression)
{
currentObjectToCompare = (codeElement as CodeMethodParameterReferenceExpression).MethodParameter;
}
else if(codeElement is CodeFieldReferenceExpression)
{
currentObjectToCompare = codeElement;
}
else if(codeElement is CodeIndexerInvokeExpression)
{
currentObjectToCompare = (codeElement as CodeIndexerInvokeExpression).IndexerReferenceExpression;
}
}
if(currentObjectToCompare == null) return false;
foreach(CodeElement existObjectToCompare in ruleData.ExistingReferenceObject)
{
if(existObjectToCompare is CodeFieldReferenceExpression
&& currentObjectToCompare is CodeFieldReferenceExpression
&& (existObjectToCompare as CodeFieldReferenceExpression ).FieldInfo == (currentObjectToCompare as CodeFieldReferenceExpression).FieldInfo
)
{
return true;
}
else if(existObjectToCompare == currentObjectToCompare)
{
return true;
}
}
ruleData.ExistingReferenceObject.Add(currentObjectToCompare);
return false;
}
private void CreateViolation(RuleData ruleData, CodeElement codeElement)
{
if(CurrentTypeViolationExists(codeElement, ruleData))
{
return;
}
string description = "";
if(ruleData.SpecificType != null)
{
if(ruleData.TryCatchStatement == null)
{
description = (ruleData.SpecificType.Member.Length == 0)
? ResourceManager.GetLocalizedString("UsingTryCatchAroundSpecificReferencesRule|ViolationMessage|Type", ruleData.SpecificType.Class)
: ResourceManager.GetLocalizedString("UsingTryCatchAroundSpecificReferencesRule|ViolationMessage|TypeMember", ruleData.SpecificType.Class+"."+ruleData.SpecificType.Member) ;
}
else
{
string requredtypeName = "";
foreach(CorrectionRecommendation requredTypes in ruleData.SpecificType.RequireExceptionTypes)
{
if(requredTypes == null) continue;
if(requredTypes.Default == "True") requredtypeName = requredTypes.Class;
}
if(requredtypeName == "" && ruleData.SpecificType.RequireExceptionTypes.Count != 0 && ruleData.SpecificType.RequireExceptionTypes[0] is CorrectionRecommendation)
{
requredtypeName = (ruleData.SpecificType.RequireExceptionTypes[0] as CorrectionRecommendation).Class;
}
description = ResourceManager.GetLocalizedString("UsingTryCatchAroundSpecificReferencesRule|ViolationMessage|TypeException", ruleData.SpecificType.Class, requredtypeName);
}
}
else
{
description = ResourceManager.GetLocalizedString("UsingTryCatchAroundSpecificReferencesRule|ViolationMessage|AllCodeInMember");
}
RuleViolation violation = new RuleViolation(this, codeElement);
violation.Description = description;
violation.Severity = RuleViolation.ViolationSeverity.Warning;
ruleData.violations.Add(violation);
}
#endregion
#region Correct
public override void Correct(RuleViolationCorrection[] requestedCorrections, AnticipatingMinds.Genesis.Effectors.CodeEffector codeEffector, System.Threading.ManualResetEvent cancelCorrectionEvent)
{
}
#endregion
private static RuleViolation[] emptyViolationsList = new RuleViolation[0];
private Type[] targetedCodeElements = {typeof(CodeTypeMemberDeclaration)};
private static Type[] applicableApplicabilityScopeTypes = {typeof(MethodApplicabilityScope),typeof(PropertyApplicabilityScope),typeof(EventApplicabilityScope),typeof(TypeMemberApplicabilityScope),typeof(FileApplicabilityScope)};
public override Type[] ApplicableApplicabilityScopeTypes
{
get
{
return applicableApplicabilityScopeTypes;
}
}
}
[Serializable]
public class SpecificType : ISerializable
{
#region Serialization Support
// A method called when serializing
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Class",this.Class);
info.AddValue("Member",this.Member);
info.AddValue("RequireExceptionTypes", this.RequireExceptionTypes,typeof(ArrayList));
}
private SpecificType(SerializationInfo info, StreamingContext context)
{
this.Class = info.GetString("Class");
this.Member = info.GetString("Member");
this.RequireExceptionTypes = info.GetValue("RequireExceptionTypes",typeof(ArrayList)) as ArrayList;
}
#endregion
public string Class;
public string Member;
public ArrayList RequireExceptionTypes = new ArrayList();
public SpecificType(string className, string member, ArrayList requireExceptionTypes)
{
this.Class = className;
this.Member = member;
this.RequireExceptionTypes = requireExceptionTypes;
}
}
}
|