locked
FXCop Custom Rules for testing accessibility

    Question

  • HI ,

    has anyone has a sample of  FXCop rule  that checks that all classes derived from Windows.Forms.Controls have the AccessibleName..


    • Edited by Lanapled Thursday, March 15, 2012 11:08 PM
    Thursday, March 15, 2012 5:06 PM

Answers

  • This sort of thing is possible, but far from trivial to do properly.  For example, it's quite easy to check that at least one assigment to the property exists within the code.  It's a lot harder to check that the property would actually end up assigned a meaningful value at runtime.  If you really care about this, it's probably something that you should be incorporating into automated testing.  However, if you want just a quick check that it looks like the developer probably provided an explicit AccessibleName somewhere in the code, even if that value might not actually be available at runtime, that's pretty easy:

    public override ProblemCollection Check(TypeNode type)
    {
    	if (type.IsAssignableTo(FrameworkTypes.Control))
    	{
    		var visitor = new ControlVisitor(type);
    		if (!visitor.FindPropertyAssignment())
    		{
    			this.Problems.Add(new Problem(this.GetResolution(), type));
    		}
    	}
    
    	return this.Problems;
    }
    
    private sealed class ControlVisitor : BinaryReadOnlyVisitor
    {
    	private readonly TypeNode _type;
    
    	internal ControlVisitor(TypeNode type)
    	{
    		this._type = type;
    	}
    
    	private bool PropertyAssignmentFound { get; set; }
    
    	internal bool FindPropertyAssignment()
    	{
    		this.PropertyAssignmentFound = false;
    
    		this.Visit(this._type);
    		return this.PropertyAssignmentFound;
    	}
    
    	public override void VisitMethodCall(MethodCall call)
    	{
    		if (!this.PropertyAssignmentFound)
    		{
    			MemberBinding callee = (MemberBinding)call.Callee;
    			This targetObject = callee.TargetObject as This;
    			if ((targetObject != null) && (targetObject.Type == this._type))
    			{
    				Method targetMethod = (Method)callee.BoundMember;
    				if (targetMethod.Name.Name.Equals("set_AccessibleName", StringComparison.Ordinal))
    				{
    					if (targetMethod.Parameters.Count == 1)
    					{
    						Literal passedLiteral = call.Operands[0] as Literal;
    						if (passedLiteral != null)
    						{
    							string passedValue = passedLiteral.Value as string;
    							if (!string.IsNullOrWhiteSpace(passedValue))
    							{
    								this.PropertyAssignmentFound = true;
    							}
    						}
    					}
    				}
    			}
    
    			base.VisitMethodCall(call);
    		}
    	}
    }
    Please note that the above checks only for literal assignments.  If you want to allow non-literal assignments to pass the rule, this is possible, but the rule won't be able to check the content of the value passed to the property (unless you want to get fancy and allow for lookup based on resources located in the same assembly).

    Monday, March 19, 2012 1:38 PM

All replies

  • Hi Lanapled,

    Thank you for posting in the MSDN forum.

    If you want to write a custom rule, please refer:

    A document about FxCop and Code Analysis: Writing Your Own Custom Rules, seehttp://www.binarycoder.net/fxcop/pdf/fxcop.pdf.

    A blog http://blogs.msdn.com/b/codeanalysis/archive/2010/03/26/how-to-write-custom-static-code-analysis-rules-and-integrate-them-into-visual-studio-2010.aspx

    Since this forum is about the product tool, so you need to write your own code about this issue. If no help, I suggest you could submit the suggestions and ideas: http://visualstudio.uservoice.com/forums/121579-visual-studio. Microsoft engineers will evaluate them seriously, thanks for your understanding.

    Have a nice day,


    Jack Zhai [MSFT]
    MSDN Community Support | Feedback to us

    Monday, March 19, 2012 6:01 AM
    Moderator
  • This sort of thing is possible, but far from trivial to do properly.  For example, it's quite easy to check that at least one assigment to the property exists within the code.  It's a lot harder to check that the property would actually end up assigned a meaningful value at runtime.  If you really care about this, it's probably something that you should be incorporating into automated testing.  However, if you want just a quick check that it looks like the developer probably provided an explicit AccessibleName somewhere in the code, even if that value might not actually be available at runtime, that's pretty easy:

    public override ProblemCollection Check(TypeNode type)
    {
    	if (type.IsAssignableTo(FrameworkTypes.Control))
    	{
    		var visitor = new ControlVisitor(type);
    		if (!visitor.FindPropertyAssignment())
    		{
    			this.Problems.Add(new Problem(this.GetResolution(), type));
    		}
    	}
    
    	return this.Problems;
    }
    
    private sealed class ControlVisitor : BinaryReadOnlyVisitor
    {
    	private readonly TypeNode _type;
    
    	internal ControlVisitor(TypeNode type)
    	{
    		this._type = type;
    	}
    
    	private bool PropertyAssignmentFound { get; set; }
    
    	internal bool FindPropertyAssignment()
    	{
    		this.PropertyAssignmentFound = false;
    
    		this.Visit(this._type);
    		return this.PropertyAssignmentFound;
    	}
    
    	public override void VisitMethodCall(MethodCall call)
    	{
    		if (!this.PropertyAssignmentFound)
    		{
    			MemberBinding callee = (MemberBinding)call.Callee;
    			This targetObject = callee.TargetObject as This;
    			if ((targetObject != null) && (targetObject.Type == this._type))
    			{
    				Method targetMethod = (Method)callee.BoundMember;
    				if (targetMethod.Name.Name.Equals("set_AccessibleName", StringComparison.Ordinal))
    				{
    					if (targetMethod.Parameters.Count == 1)
    					{
    						Literal passedLiteral = call.Operands[0] as Literal;
    						if (passedLiteral != null)
    						{
    							string passedValue = passedLiteral.Value as string;
    							if (!string.IsNullOrWhiteSpace(passedValue))
    							{
    								this.PropertyAssignmentFound = true;
    							}
    						}
    					}
    				}
    			}
    
    			base.VisitMethodCall(call);
    		}
    	}
    }
    Please note that the above checks only for literal assignments.  If you want to allow non-literal assignments to pass the rule, this is possible, but the rule won't be able to check the content of the value passed to the property (unless you want to get fancy and allow for lookup based on resources located in the same assembly).

    Monday, March 19, 2012 1:38 PM
  • Thanks for Nicole’s help.

    Hi Lanapled,

    Any update? Could you get useful information from our replies?

    Would you mind letting us know the result of the suggestion?

    Best Regards,


    Jack Zhai [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, March 21, 2012 4:36 AM
    Moderator