Writing a Custom Code Analysis Rule for Guard Classes

CA1062 does essentially check for parameter validation in public methods. That’s nice and really a good practice, but the way CA1062 implements the check enforces you to write at least one if-statement per parameter, which leads to unreadable code. A better approach are Guard-classes and of course CodeContracts in Visual Studio 2010. Unfortunately both are not recognized by CA1062.
I’ve implemented a little Code Analysis Rule to perform a check for usage of guard classes, which I will extend to cover CodeContracts, too.
First of all, to see how that works, we need to know how to implement a Code Analysis Rule at all – and how to debug it. The easy part of that is to reference FxCopSdk and Microsoft.Cci in a new Class Library project. To implement a Code Analysis Rule you will need to inherit from the abstract class BaseIntrospectionRule and override one of the Check methods.
When trying to follow these steps you will get the first problem: you will need to implement a parameter less constructor – performing “the right” actions. In my implementation I’ve created a base class with a handy one parameter constructor:

The base class calls the BaseIntrospectionRule constructor specifying the name of the rule, the name of the embedded xml file resource to lookup the strings for the messages and the assembly to look for the xml. This xml file is another thing you need to add to your project. It defines the name and description of the rule as well as the text for the solution of the rule problem:

<Rule TypeName="PublicMethodParametersMustBeCheckedByGuardClassMethod" Category="BestPractice.Robustnes" CheckId="SEM1001">
<Name>PublicMethodParametersMustBeCheckedByGuardClassMethod</Name>
<Description>All parameters of public members must be checked with a method of a guard class (that class must have the GuardClassAttribute)</Description>
<Url></Url>
<Resolution>The parameter {0} must be checked for a valid value.</Resolution>
<MessageLevel Certainty="95">Warning</MessageLevel>
<FixCategories>NonBreaking</FixCategories>
<Email />
<Owner />
</Rule>

You still have to supply the “name” parameter to the constructor. This is done in a parameterless constructor of the rule implementation class:

It looks up the name from its own type. Unfortunately we cannot us the “this” keyword in this context, because the class instance has not been created at this point.
My base class also implements another AddProblem overload, so you can add a problem using only two simple parameters:

protected void AddProblem(string faultyElement, Node target)
{
// Get the message text that is shown in the error-list.
// Works like string.Format and inserts the given faulty element string
// into the error text defined in the Rules.xml
var resolution = GetResolution(faultyElement);
// Create a new Problem with the resolution and the target node given
var problem = new Problem(resolution, target)
{
Certainty = 100,
FixCategory = FixCategories.NonBreaking,
MessageLevel = MessageLevel.Warning,
};
// Add the Problem to the Problemlist
Problems.Add(problem);
}

So first we exclude abstract, framework and guard class methods from the analysis, then we determine the checked parameters and finally we check each method parameter to be in the list of checked parameters. For each parameter we don’t have in the list, we generate a new “Problem”.
Building the list of checked parameters in GetCheckedParameters involves some code parsing. Code Analysis Rules do work with the IL code instead of the source files, so we have to deal with the IL code, too. In our case we will simply parse calls to the guard class methods – that will limit the amount of IL op-codes to parse. An interesting detail here is that non-static methods do have one parameter that you don’t see in C#: the “this”-pointer. Each non-static method does have the pointer to the current instance data of the object as the first parameter. Unfortunately FxCop does not show this parameter, so to lookup the name of the parameters, we have to subtract 1 from the parameter index determined from the IL code in case of non-static methods (in static methods the 1st parameter in IL code is the same as the first parameter in C# and FxCop). I will not show the code here, because it’s mainly a huge switch statement.
My implementation does detect Guard-Classes simply by name – you will have to name the class or its base class “GuardClass”.
Debugging Code Analysis Rules is also fun. The easiest way (IMHO) is this:

Add command options like this:
/rule:”C:\{path to your bin folder}\{your code analysis assembly}” /file:”C:\ {path to your bin folder}\{an assembly you want to analyze}” /console
I’m usually using “..\bin” as the build folder, so both {path to your bin folder} are the same. {an assembly you want to analyze} can be an executable or library with code that will be analyzed.

This way you will start the command line version of FxCop with your rule running against some test code you have under control ({your code analysis assembly}).
To see such code in action, have a look at http://semprojectsettings.codeplex.com/. There I’ve a solution with that rule implemented (Visual Studio 2008).