using System;
using System.Collections;
using System.Xml;
using AnticipatingMinds.Genesis.KnowledgeManagement;
using AnticipatingMinds.Genesis.CodeDOM;
using AnticipatingMinds.Genesis.CodeDOM.Utilities;
namespace AnticipatingMinds.KnowledgePack.Performance{
/// <summary>
/// Summary description for StarterRuleTemplate.
/// </summary>
public class TestForEmptyStringsUsingStringLengthTemplate : RuleTemplate
{
public TestForEmptyStringsUsingStringLengthTemplate(string templateId, IDictionary templateProperties):base(templateId,templateProperties)
{
}
public override string Name
{
get
{
return ResourceManager.GetLocalizedString("TestForEmptyStringsUsingStringLengthRule|Name");
}
}
public override string Description
{
get
{
return ResourceManager.GetLocalizedString("TestForEmptyStringsUsingStringLengthRule|Description");
}
}
public override Rule CreateRule(string ruleId, IDictionary ruleProperties)
{
return new TestForEmptyStringsUsingStringLengthRule(ruleId, Id, ruleProperties);
}
}
public class TestForEmptyStringsUsingStringLengthRule : Rule
{
/// <summary>
/// This is used for declaring all code elements you want to analyze
/// Note that this started only declares one.
/// </summary>
private Type[] targetedCodeElements = {typeof(CodeBinaryExpression)};
internal TestForEmptyStringsUsingStringLengthRule(string id, string templateId, IDictionary ruleProperties) : base(id,templateId,ruleProperties)
{
}
public override Type[] TargetedCodeElements
{
get
{
return targetedCodeElements;
}
}
public override RuleViolation[] Analyze(object codeElement, System.Threading.ManualResetEvent cancelAnalysisEvent)
{
RuleViolationCollection violationsFound = new RuleViolationCollection();
bool violationFound = false;
CodeBinaryExpression condition = (CodeBinaryExpression)codeElement;
if(!IsStringComparisonOperator(condition.Operator))
return emptyViolationsList;
string violationMessage = string.Empty;
#region Test for == or != string.empty
if(condition.RightOperand is CodeNamedReferenceExpression)
{
CodeNamedReferenceExpression rightOperand = condition.RightOperand as CodeNamedReferenceExpression;
if(rightOperand.TargetObject is CodeTypeReferenceExpression)
{
CodeTypeReferenceExpression typeRef = rightOperand.TargetObject as CodeTypeReferenceExpression;
if(typeRef.ReferencedType.TypeName.ToLower() == "string" && rightOperand.Name.ToLower() == "empty")
{
violationFound = true;
violationMessage = string.Format(ResourceManager.GetLocalizedString( "TestForEmptyStringsUsingStringLengthRule|Violation|Empty"));
}
}
else
{
string target = CodeNamedReferenceExpressionUtils.GetTargetReferencesAsString(rightOperand);
if(target.ToLower() == "string.empty" || target.ToLower() == "system.string.empty")
{
violationFound = true;
violationMessage = string.Format(ResourceManager.GetLocalizedString( "TestForEmptyStringsUsingStringLengthRule|Violation|Empty"));
}
}
}
#endregion
#region Test for != or == ""
if(!violationFound && condition.RightOperand is CodePrimitiveExpression)
{
CodePrimitiveExpression rightOperand = condition.RightOperand as CodePrimitiveExpression;
if(rightOperand.Value.ToString().Length == 0)
{
violationFound = true;
violationMessage = string.Format(ResourceManager.GetLocalizedString( "TestForEmptyStringsUsingStringLengthRule|Violation|Quotes"));
}
}
#endregion
if(violationFound)
{
RuleViolation violation = new RuleViolation(this , violationMessage , condition);
violation.Severity = RuleViolation.ViolationSeverity.Suggestion;
violation.AddCorrection(ResourceManager.GetLocalizedString("TestForEmptyStringsUsingStringLengthRule|Correction"),true,false);
CodeElement parent = condition.Parent;
while(parent is CodeParenthesizedExpression)
parent = parent.Parent;
if(parent is CodeTypeCastExpression &&
(parent as CodeTypeCastExpression).TargetType.TypeInfo != null &&
(parent as CodeTypeCastExpression).TargetType.TypeInfo.FullName == "System.String")
{
violation.ViolationData["CastingExpression"] = parent;
}
else
{
violation.ViolationData["CastingExpression"] = null;
}
violation.ViolationData["Expression"] = condition;
if(violation.ViolationData["CastingExpression"] == null)
violation.LocationAnchor = condition.Parent;
else
violation.LocationAnchor = parent.Parent;
violationsFound.Add(violation);
}
if(violationsFound.Count == 0)
return emptyViolationsList;
else
return violationsFound.ToArray();
}
private bool IsStringComparisonOperator(CodeBinaryOperatorType binaryOperator)
{
return binaryOperator == CodeBinaryOperatorType.Equality || binaryOperator == CodeBinaryOperatorType.Inequality;
}
public override void Correct(RuleViolationCorrection[] requestedCorrections, AnticipatingMinds.Genesis.Effectors.CodeEffector codeEffector, System.Threading.ManualResetEvent cancelCorrectionEvent)
{
codeEffector.BeginCodeChanges(ResourceManager.GetLocalizedString("TestForEmptyStringsUsingStringLengthTemplate|CorrectionDescription"));
foreach(RuleViolationCorrection requestedCorrection in requestedCorrections)
{
if(requestedCorrection.Violation.IsFixed)
continue;
CodeBinaryExpression originalCondition = requestedCorrection.Violation.ViolationData["Expression"] as CodeBinaryExpression;
CodeTypeCastExpression castingExpression = requestedCorrection.Violation.ViolationData["CastingExpression"] as CodeTypeCastExpression;
CodeBinaryExpression comparisonToNullExpression = new CodeBinaryExpression(CodeBinaryOperatorType.Inequality,originalCondition.LeftOperand.Clone() as CodeExpression,new CodeNullReferenceExpression());
CodeNamedReferenceExpression lengthPropertyReferenceExpression;
if(castingExpression == null)
{
lengthPropertyReferenceExpression = new CodePropertyReferenceExpression(originalCondition.LeftOperand.Clone() as CodeExpression,"Length");
}
else
{
CodeTypeCastExpression newCastExpression = new CodeTypeCastExpression();
newCastExpression.TargetType = new CodeTypeReference("string");
newCastExpression.Expression = originalCondition.LeftOperand.Clone() as CodeExpression;
lengthPropertyReferenceExpression = new CodePropertyReferenceExpression(new CodeParenthesizedExpression(newCastExpression),"Length");
}
CodeBinaryExpression lengthComparisonExpression = new CodeBinaryExpression(originalCondition.Operator,lengthPropertyReferenceExpression,new CodePrimitiveExpression(0));
CodeBinaryExpression newCondition = new CodeBinaryExpression(CodeBinaryOperatorType.LogicalAnd,comparisonToNullExpression,lengthComparisonExpression);
if(castingExpression == null)
{
codeEffector.ReplaceCodeElement(originalCondition,new CodeParenthesizedExpression(newCondition));
}
else
{
codeEffector.ReplaceCodeElement(castingExpression,new CodeParenthesizedExpression(newCondition));
}
requestedCorrection.Violation.IsFixed = true;
}
codeEffector.CommitCodeChanges();
}
public override Type[] ApplicableApplicabilityScopeTypes
{
get
{
return applicableApplicabilityScopeTypes;
}
}
private static Type[] applicableApplicabilityScopeTypes = {typeof(MethodApplicabilityScope),typeof(PropertyApplicabilityScope),typeof(EventApplicabilityScope),typeof(FileApplicabilityScope)};
private static RuleViolation[] emptyViolationsList = new RuleViolation[0];
}
}
|