Microsoft Visual Studio 2010 Advance Code Analysis: Write Custom Static Code Analysis Rules Using FxCop

Introduction

Microsoft’s FxCop was released in 2002 as a static code analysis tool. After this initial released version, Microsoft has added new features and updated this tool very frequently. FxCop has now become the most amazing tool in Microsoft Visual Studio environment. It’s now integrated with Microsoft Visual Studio 2010 (premium and ultimate editions only) and developer’s community may better know this as ‘Code Analysis‘ or ‘Code Review‘ tool. FxCop perform static code analysis of your application source code without executing the program. Microsoft has divided almost 200 + code analysis rules in different groups or categories in Microsoft Visual Studio 2010; for example basic correctness rules, basic design guideline rules, globalization rules etc. Other then these predefined static rule sets developer can write their own customized FxCop rules as per requirement. In this article I will show you how a custom rule can be defined with an example.

Writing Custom Code Analysis Rules

FxCop uses an introspection engine to perform extensive code analysis of assemblies of different versions of the .NET framework. To write custom analysis rules your project should have FxCopSdk.dll and Microsoft.Cci.dll assemblies (as reference) added. By default Visual Studio 2010 installs these assemblies in ‘C:Program FilesMicrosoft Visual Studio 10.0Team ToolsStatic Analysis ToolsFxCop’ path.

First create a class library type project using Microsoft Visual Studio 2010 with target framework 4.0; add FxCopSdk.dll and Microsoft.Cci.dll references. To avoid path resolution issues of 2 added assemblies when the project will be built on different computers you need to use the $(CodeAnalysisPath) MSBuild property. Replace the following section of the project file (XML code).

  <Reference Include="FxCopSdk">
        <HintPath>C:Program FilesMicrosoft Visual Studio 10.0Team ToolsStatic Analysis ToolsFxCopFxCopSdk.dll</HintPath>
      </Reference>
      <Reference Include="Microsoft.Cci">
        <HintPath>C:Program FilesMicrosoft Visual Studio 10.0Team ToolsStatic Analysis ToolsFxCopMicrosoft.Cci.dll</HintPath>
  </Reference>

The new XML code snipped should be as follows.

  <Reference Include="FxCopSdk">
      <HintPath>$(CodeAnalysisPath)FxCopSdk.dll</HintPath>
      <Private>False</Private>
  </Reference>
  <Reference Include="Microsoft.Cci">
      <HintPath>$(CodeAnalysisPath)Microsoft.Cci.dll</HintPath>
      <Private>False</Private>
  </Reference>

Next you have to add a rule metadata file (a .xml file) to the project. This metadata file will contain various properties of the rules you want to define for the project. These properties are rule name, description, resolutions, message level, owner contact info, etc. The following is an example of XML rule file defined in my sample project.

  <?xml version="1.0" encoding="utf-8" ?>
  <Rules FriendlyName="My Custom Test Rule">
    <Rule TypeName="AllTypeNamesShouldStartwithXYZ" Category="CustomRules.Naming" CheckId="CR0001">
      <Name>All type names defined in this project should start with XYZ - That is Client Name</Name>
      <Description>as per coding standard specification I want to mention client name for all the types  
      Defined. </Description>
      <Url>http://foobar.com</Url>
      <Resolution>The name of type {0} does not start with the prefix 'XYZ'. Add the prefix to the type
       name.</Resolution>
      <MessageLevel Certainty="95">Warning</MessageLevel>
      <FixCategories>Breaking</FixCategories>
      <Email />
      <Owner />
    </Rule>
  </Rules>

Using the above rule I validate all the types defined in my code. The types should contain an ‘XYZ’ prefix. I will show the code rule violation warning if that is not followed. You also need to set the ‘Build Action’ property of the rule metadata file to EmbeddedResource so that it’s get included to the compiled DLL.

Next create a base rule class. Below is the sample:

  using Microsoft.FxCop.Sdk;
  namespace TestCustomFxCop
  {
    internal abstract class BaseFxCopRule : BaseIntrospectionRule     
     {
          protected BaseFxCopRule(string myruleName)
              : base(myruleName, "MyFirstFxCopRule.CheckXYZClientName", typeof(BaseFxCopRule).Assembly)
          { }
      }
  }

‘BaseFxCopRule’ is an abstract class that inherits ‘BaseIntrospectionRule‘ class defined in the FxCop SDK. In the above example I am passing three parameters to the base constructor. The first parameter is the type name of the rule, second is the resource name and the last one is the assembly.

Next add another class that will inherit BaseFxCopRule with the following function.

  using System;
  using Microsoft.FxCop.Sdk;
  using Microsoft.VisualStudio.CodeAnalysis;

  namespace TestCustomFxCop
  {
      public class AllTypeNamesShouldStartwithXYZ: BaseRule
      {
          public AllTypeNamesShouldStartwithXYZ ()
              : base("AllTypeNamesShouldStartwithXYZ")
          {
          }

          public override ProblemCollection Check(TypeNode type)
          {
              if (!type.Name.Name.StartsWith("XYZ", StringComparison.Ordinal))
              {
                  var resolution = GetResolution(type.Name.Name);
                  var problem = new Problem(resolution, type)
                                    {
                                        Certainty = 99,
                                        FixCategory = FixCategories.DependsOnFix,
                                        MessageLevel = MessageLevel.Warning
                                    };
                  Problems.Add(problem);
              }

              return Problems;
          }
      }
  }

The above check method is checking the name of the type, and then adding a problem object to a collection. The GetResolution method formats an array of parameters into the resolution text defined in the XML file. Now compile your rules project.

Now create another class library type project to test above custom code analysis rule set. Add a new code analysis rule set file to this project and open that using the XML editor (right click on the rule set file choose open with and select XML editor). Ignore the already existing content of the file and copy paste the following code.

  <?xml version="1.0" encoding="utf-8"?>
  <RuleSet Name="Custom Rule Set" Description=" " ToolsVersion="10.0">
    <RuleHintPaths>
      <Path>E:my workVS 2010 ProjectsCustomCodeAnalysisRulesbinDebug</Path>
    </RuleHintPaths>
   <Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
      <Rule Id="CR0001" Action="Warning" />
    </Rules>
  </RuleSet>

RuleHintPaths‘ in the above code can be absolute, or relative to the location of the previous rule set project output dll file. It should point at the exact folder that your compiled rules dll sit in.

Now open the rule set file using the code analysis rule set editor; you will be able to see the new custom rule with ID CR0001. Select that rule and save the file. Next open the project properties window of your class library project, go to the Code Analysis tab, enable code analysis and select the new rule set. Now if you build the project; output of the new custom rule will be shown in the warning list if a type doesn’t satisfy the rule.

Conclusion

Your written custom code analysis rules runs against a project but you can also debug rules through FxCopCmd.exe. By default exe is installed by Microsoft Visual Studio in the following path C:Program FilesMicrosoft Visual Studio 10.0Team ToolsStatic Analysis ToolsFxCop. While using FXCop developers should always focus on the most critical issues (run code analysis with Microsoft recommended minimum rules). Use the code analysis early in the development cycle and you should build up a practice to use that often. Microsoft recommends enabling code analysis in your team builds.

Related Articles

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read