Chapter 19

Code Analysis, Code Metrics, and Code Clone Analysis

What's In This Chapter?

  • Enabling and running code analysis in Visual Studio 2012
  • Correcting code analysis rule violations
  • Understanding code metrics and how to use them
  • Using Code Clone Analysis to find similar code fragments in your code base

Wrox.com Code Downloads for this Chapter

The wrox.com code downloads for this chapter are found at www.wrox.com/remtitle.cgi?isbn=1118314081 on the Download Code tab. The files are in the Chapter 19 download folder and individually named as shown throughout this chapter.

This chapter describes the code analysis, code metric, and code clone analysis features included with the Visual Studio 2012 Premium and Ultimate editions. These tools can quickly and easily inspect your code to find common mistakes, make suggestions for improvements, and even indicate violations of standards.

The discussion begins by examining the origins of the Static Code Analysis tool. You find out about Microsoft's .NET “Design Guidelines for Class Library Developers” and how it is related to the tools. You also take a brief look at what is new with these tools in Visual Studio 2012.

Then you do a bit of exploration into the code analysis itself and how to take advantage of its full integration with Visual Studio 2012. This includes enabling static code analysis review for your projects, selecting rules to apply, and working with the results of the analysis.

However, using the IDE is not always an option, and sometimes you need additional flexibility. The Static Code Analysis tool is available to you from the command line. You find out how to use the command line for code analysis and how to include code analysis with your automated builds.

Next, you look at Code Metrics, a tool in Visual Studio that can provide insight into how maintainable your code is. Each code metric is examined in detail, and you learn how to understand what code metrics are trying to tell you.

The chapter wraps up with a look at a new feature in Visual Studio 2012: Code Clone Analysis. Fragments of code, called code clones, happen throughout all projects as code is copied and pasted into different areas. Code clone analysis enables you to find these similar fragments of code, which makes it easier to apply changes or refactor your code base.

The Need for Analysis Tools

Ensuring that developers follow best practices and write consistent code is a major challenge in today's software development projects. The act of documenting standards and practices is often skipped or overlooked. However, even in projects for which standards have been established, getting developers to read and follow those practices is another major challenge.

One of the best resources available for .NET developers is Microsoft's .NET Framework “Design Guidelines for Class Library Developers” (Design Guidelines). These guidelines document Microsoft's (formerly) internal practices for developing class libraries, and are freely available at http://msdn.microsoft.com/en-us/library/ms229042.aspx.

The guidelines cover a range of subjects, including naming conventions, usage guidelines, and performance and security considerations. When you put them into practice, they help ensure that your approach is consistent with that of other developers. In addition, they have evolved over a number of years to reflect a considerable amount of knowledge, best practices, and lessons learned.

As useful as the design guidelines are, the reality of software creation is that many developers are not familiar with their contents. Most times, this is not a fault of the developer, but rather the process that the developer must follow. For some companies, design guidelines are not as important as simply getting the project finished, regardless of the long-term benefit that following those guidelines will have. The desire to automate the process of evaluating code for compliance with these guidelines led to the creation of FxCop, a tool that was used internally at Microsoft and later evolved into the Code Analysis tool in Visual Studio.

What's New for Code Analysis in Visual Studio 2012

One of the most important updates is that code analysis is now available in all editions of Visual Studio 2012, including a subset of the most critical warnings in the Express editions of Visual Studio. All the code analysis rules are available in the Professional, Premium, and Ultimate editions.

Support has also been provided for 64-bit C++ projects, as well as the ability to create custom rule sets for C++ projects.

One of the most difficult areas around code analysis has been managing the large result sets it can return. Visual Studio 2012 addresses this through the use of a new Code Analysis results window, which includes filtering to quickly and easily narrow result information.

Finally, code editor highlighting has been added for code analysis results. Selecting a message in the Code Analysis results window highlights the line of code in the source code editor that triggered the message. This makes it easy to correlate the message to the offending line of code.

Using Code Analysis

An example project that demonstrates the use of managed code analysis is presented throughout this chapter. To begin the project, create a new C# Class Library project and name it SampleLibrary. Rename the Class1.cs file to PayCalculator.cs and insert the following code, which fails to meet several code analysis guidelines:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
        
namespace SampleLibrary
{
    public class PayCalculator
    {
        public enum Pay_Level
        {
            EntryLevel = 20,
            Normal = 35,
            Senior = 50
        }
        
        public static int MaximumHours;
        public const double BONUS = 0.10;
        
        static PayCalculator()
        {
            MaximumHours = 100;
        }
        
        public static double ComputePayment(int hours, Pay_Level level)
        {
            if (hours > MaximumHours)
            {
                throw new ArgumentOutOfRangeException("Employee works too much");
            }
        
            return ((int)level * hours);
        }
    }
}

While this code compiles and runs as expected, you can make several improvements to it, and the Code Analysis tool helps you find them. These improvements help make your code easier to understand, and possibly catch potential run-time errors (such as buffer overflows).

Built-in Code Analysis Rules

As mentioned earlier, Visual Studio ships with nearly 200 rules for managed Code Analysis, as well as more than 300 rules for native code, each of which helps to enforce the practices documented in the .NET Framework Design Guidelines, as well as other practices recommended by Microsoft. This section briefly describes each of the 12 rule groups to help you understand when you might apply them to your projects.

Table 19.1 describes the groups of rules included with Visual Studio 2012.

Table 19.1 Groups of Rules

Rule Group (Number of Rules) Description
Design (67) Typically focused on the interfaces and structure of code, this group enforces proper implementation of common concepts such as classes, events, collections, namespaces, and parameters. These rules revolve around the Microsoft .NET Framework Design Guidelines.
Globalization (11) This group includes practices to support the internationalization of code. This can include avoiding strings of literal text, correct use of CultureInfo, and formatting.
Interoperability (16) This group is focused on the correct use of COM Interop. Included are rules for proper use of PInvoke, the ComVisible attribute, and marshalling.
Maintainability (6) These are rules to help make your code easier to maintain. This group identifies potential problems such as complexity and overuse of inheritance.
Mobility (2) These are rules to help detect code that will not run effectively in mobile or disconnected environments.
Naming (24) This group enforces naming standards as described in the Design Guidelines. Using these rules verifies that names of items such as assemblies, classes, members, and variables conform to standards. Some rules even help to detect misspellings in your assigned names.
Performance (16) These rules help to detect places in your code that may be optimized for performance. They detect a variety of wasteful or extraneous code.
Portability (3) These are rules to find code that might not be easily portable between operating environments.
Reliability (6) The rules in this group help detect problems with your code that may lead to intermittent failures, including failure to dispose of objects, improper use of the garbage collector, bad threading use, and more. These rules can be extremely useful because intermittent errors are frequently the most difficult to identify and correct.
Security (44) These rules help to identify insufficient or incorrect security practices. Rules exist to find missing attributes, improper use of permissions, and opportunities for SQL injection attacks.
Usage (42) These rules cover a broad spectrum of recommended practices. Whereas the design group rules typically involve API structure, these rules govern the methodologies of code. Practices include proper exception management, handling of arithmetic overflow, serialization, and inheritance.
Native (362) These rules cover information related to C/C++ source code, including buffer overruns, uninitialized memory, null pointer dereferences, and memory and resource leaks.

Of course, the rules that ship with Visual Studio are only a starting point. Microsoft and others will certainly make additional rules available, and you can add your own custom rules and rule groups as well.

Code Analysis Rule Sets

With Visual Studio 2012, you can group code analysis rules into rule sets, making it easy for everyone to get started using code analysis. The code analysis rules that ship by default are already grouped into specified rule sets, but you have the capability to create your own custom rule sets as needed.

Table 19.2 shows the rule sets included with Visual Studio 2012.

Table 19.2 Rule Sets

Rule Set Description
Microsoft All Rules This rule set contains all code analysis rules.
Microsoft Basic Correctness Rules This rule set focuses on logic errors and common mistakes made when using the .NET framework APIs.
Microsoft Basic Design Guideline Rules This rule set focuses on enforcing best practices to make code easy to understand and use.
Microsoft Extended Correctness Rules This rule set expands on the basic correctness rules to maximize the reported logic and framework usage errors.
Microsoft Extended Design Guideline Rules This rule set expands on the basic design guideline rules to maximize the number of reported usability and maintainability issues.
Microsoft Globalization Rules This rule set focuses on problems that may occur if your application has not been properly localized.
Microsoft Managed Minimum Rules This rule set focuses on the most critical problems in your code for which Code Analysis is most accurate. It contains a small number of rules and is intended for use in Visual Studio Express editions.
Microsoft Managed Recommended Rules This rule set focuses on the most critical problems in your code, including security holes and application crashes. This is the default rule set applied to newly created projects and is recommended for inclusion in any custom rule set you create.
Microsoft Security Rules This rule set contains all Microsoft security rules.
Microsoft Mixed (C++/CLR) Minimum Rules This rule set focuses on the most critical problems in C++ projects, including security holes and application crashes.
Microsoft Mixed (C++/CLR) Recommended Rules This rule set focuses on the most common and critical problems in C++ projects, including security holes, application crashes, and important logic and design errors. It is designed for use in Visual Studio Professional and higher.

To create a new rule set, in Visual Studio, select File ⇒ File…, and then select Code Analysis Rule Set under the General tab. Using this new rule set, you can use the Add or Remove child rule set buttons to add existing rule sets to your custom rule set.

Enabling Code Analysis

By default, code analysis is disabled for projects in Visual Studio. To enable analysis, open your project's Properties window and select Code Analysis from the left-hand side tabs. You see a drop-down of the different rule sets available for use with code analysis. You no longer see a collapsed list of rules as with previous versions, but instead you see the new menu showing the selected rule set, as shown in Figure 19.1.


Warning
To enable and configure Code Analysis for ASP.NET applications, from the main menu in Visual Studio, select Website ⇒ Code Analysis Configuration. You can also enable (but not configure) Code Analysis from the Build page of the ASP.NET project's Property Pages.

To enable code analysis upon build, select the Enable Code Analysis on Build checkbox. Select the desired rule set in the dropdown list box, or choose multiple rule sets. Save your settings via Save Selected Items on the File menu, or by pressing Ctrl+S.

To view the rules contained in an individual rule set, select the rule set in the dropdown list box and then click the Open button. The individual rules that comprise that rule set open. You can disable rules or entire groups of rules by deselecting their checkboxes.

In addition, you can set each rule in a rule set to one of the following:

  • Warning (the default) — Warnings serve as an advisory that something may need to be corrected, but they do not prevent the project's build from succeeding.
  • Error — Errors prevent a build when those rules are violated, so you may want to set certain rules or groups of rules to Error if they are critically important.
  • Inherit — Inherit means this rule uses the same indicator that the group it is contained in uses.
  • None — This means no setting.

Use the dropdown list in the Action column to choose among Warning, Error, None, or Inherit. As with enabling rules, you can set these actions for specific rules or for entire groups of rules.

Figure 19.2 illustrates how to enable and disable specific rules and how each can be set to Warning or Error as necessary.

Finally, you can specify different sets of code analysis properties for each configuration. By default, settings apply to the Active build configuration, but you can be more specific. For example, you might want to treat certain critical rules as Errors in your Release builds, but treat those same rules as Warnings in Debug. You might instead decide to disable code analysis entirely for your Release builds. Simply choose a build type from the Configuration dropdown menu and then review your settings. To make changes affecting all build configurations, select the All Configurations option and then modify and save your settings.

Executing Code Analysis

After you have enabled code analysis and configured the rules to reflect your development standards, code analysis is performed each time you build your project. Go ahead and build your sample project now.


Note
You can also execute code analysis on your project by choosing Build ⇒ Run Code Analysis on [Project Name] or by right-clicking the desired project within Solution Explorer and selecting Run Code Analysis.

The output window includes details about your build, including results from calling code analysis. After the build, the Code Analysis window (a new window in Visual Studio 2012) may appear, displaying a number of warnings and possibly some errors. If you do not see the Code Analysis window, choose Analyze ⇒ Windows ⇒ Code Analysis. By default this window appears as a tab in the same well as Solution Explorer.

By default, the Microsoft Minimum Recommended Rules rule set is selected, and thus, no warnings are generated. For the purpose of this example, return to the rule set selection and choose the Microsoft All Rules rule set.

Figure 19.3 shows the Code Analysis window displaying code analysis results for the SampleLibrary assembly.

The new Code Analysis window provides some nice features for working with code analysis results. There is a search box at the top of the window that enables you to search for specific results. The Analyze dropdown box enables you to rerun code analysis for the entire solution or for specific files in the solution. The Settings button enables you to change the rule set used by a particular project in the solution.

Directly below the search box are two dropdown filter boxes. The first enables you to filter the results based off the project name. The second enables you to filter based off the result type, such as error or warning.

Analysis of the SampleLibrary code indicates ten potential rule violations. Selecting an item in the list displays the full description of the violation indicating how your code is in violation of a rule. It also displays the file and line number indicating (when appropriate) specific source files and code related to each warning.

Some warnings do not relate to specific code, but perhaps to a lack of an attribute or security setting. Other warnings may refer directly to problem code, perhaps naming violations or performance issues. You can double-click the warning, and the code editor switches to the related code.

Each time you run code analysis, the results are stored in an XML file. This file is named <Project Name>.CodeAnalysisLog.xml, and is located in your project's build output directory (that is, inDebug or inRelease). For the SampleLibrary project, the file is SampleLibrary.dll.CodeAnalysisLog.xml.

If you open the file from within the IDE, you see the raw, unformatted XML. However, the XML has an associated XSL template that formats the data into HTML, similar to what is shown in Figure 19.4.

To see this view, open the XML file with Internet Explorer. To customize rendering, you can supply your own XSL templates. If you choose to do this, you should make a copy of the included template and modify the copy to suit your needs. The base template is in your Visual Studio installation directory as Team ToolsStatic Analysis ToolsFxCopXmlCodeAnalysisReport.xsl.

Working with Rule Violations

Several issues should be addressed in the sample PayCalculator class. For each warning or error, you must determine whether the rule actually applies to your project or a specific section of code.

If it does, you must modify the project to address the issue; otherwise, you may choose to ignore the rule. This section describes how to act on identified issues and how to ignore, or suppress, a given rule.

As part of this discussion, you immediately go into the code and make corrections as necessary, but your organization or project may require the use of work items to track any changes. Or perhaps you don't have time to immediately address an identified problem but would like to use a work item as a reminder. Fortunately, you can easily create work items directly from Code Analysis rule violations. Simply right-click the warning or error and choose Create Work Item from the menu. Choose the type of work item you want to create, and the New Work Item dialog displays. Make any necessary changes and save your new work item.

Correcting Problems

Looking through the Error List shown in Figure 19.3, you should see item CA1810, with a description of “Initialize Reference Type Static Fields Inline PayCalculator.cs (Line 22)”.

Click the error number (CA1810) to display the documentation for the rule that triggered this warning, including suggestions for resolving the issue. You are currently assigning the value of 100 to MaximumHours inside the static constructor of PayCalculator. The rule's Help text states that your code may perform more efficiently if you make that assignment when the variable is defined.

To address this issue, double-click this warning to see the static constructor of the PayCalculator class. Change the code to assign the value in the declaration as follows:

public static int MaximumHours = 100;

Next, delete the static PayCalculator constructor entirely. Build the project and look at the Code Analysis window. The specific warning should no longer be in the list.

There is another easy problem to correct. Many of the code analysis rules relate to standard naming conventions. Find the warning CA1707 “Identifiers Should Not Contain Underscores PayCalculator.cs (Line 9)” and double-click. The rule helps to enforce the naming convention that underscores should not be used in type names. Use the built-in refactoring support to rename it. Right-click the Pay_Level enumeration and choose Refactor ⇒ Rename. Change the name to PayLevel, click OK, and then Apply.

Mark the PayCaclulator class definition static as follows:

public static class PayCalculator

Rules can also help ensure that you're using the Framework correctly. You can see from the following warning that the rule has detected that you might not be creating the ArgumentOutOfRangeException correctly; CA 2208 “Instantiate Argument Exceptions Correctly PayCalculator.cs (Line 30)”. Replace this argument with one of the method's parameter names. Note that the provided parameter name should have the exact casing as declared on the method. To fix this, change the line that throws the exception to the following:

    if (hours > MaximumHours)
    {
        
     throw new ArgumentOutOfRangeException("hours", "Employee works too much");
    }

One of the remaining warnings, CA1014 “Mark Assemblies with CLSCompliantAttribute (Global)” is a fairly common suggestion. Consider addressing this when creating a reusable library assembly that might be consumed by code of more than one .NET language. Common Language Specification (CLS) compliance specifies that your assembly must meet the common structure and syntax supported by all .NET languages as defined in the CLS. Keep in mind that there may be times when CLS compliance is not possible, such as when exposing unsigned types.

To address this warning, open AssemblyInfo.cs and add the following line:

[assembly: System.CLSCompliant(true)]

The assembly: notation is used because the attribute applies to the entire assembly, and not to a specific class or member. You can find other assembly-level attributes in the AssemblyInfo.cs file.

Now, build the project. The violations you corrected should no longer generate messages in the Error List. The remaining six warnings are addressed shortly.

Suppressing Messages

Visual Studio 2012 ships with many rules, and not all of them are appropriate for every project. There is a chance that some rules trigger warnings that simply don't apply to certain parts of your project. To prevent these irrelevant messages from recurring, right-click the rule violation and choose Suppress Message ⇒ In Source.

When you suppress a message, Visual Studio automatically adds an attribute to your code to indicate that a rule should not apply. You can apply the SuppressMessage attribute to a code construct, such as a field, method, or class, and to an entire assembly.


Warning
Suppressing a message is not the same as disabling a rule. Suppression prevents the specific violation of a rule from recurring, but other violations of the same rule are still identified. You should disable a rule only if you're certain it could never be meaningfully applied to any part of your project.

Let's continue with the SampleLibrary example and use message suppression to clean up more of the code analysis violation messages.

The warnings for CA1709 states, “Identifiers Should Be Cased Correctly PayCalculator.cs (Line 19)” Assume that your organization has different naming conventions for constants, and you know that this rule does not apply to this BONUS constant. Right-click the message and choose Suppress Message ⇒ In Source. The message is crossed out in the Code Analysis window, and the PayCalculator class is modified to include the following attribute immediately before the declaration of BONUS:

[System.Diagnostics.CodeAnalysis.SuppressMessage(
    "Microsoft.Naming",
    "CA1709: IdentifiersShouldBeCasedCorrectly",    MessageId = "BONUS")]

The next time Code Analysis is run, the engine recognizes this attribute. Moreover, even when the CA1709 rule is violated at this point, no message is created. Messages for any other violations of this rule elsewhere in the code are still reported as normal.

“Two more messages don't apply to the project. CA2211 “Non-constant Fields Should Not Be Visible PayCalculator.cs (Line 18)” reminds you that external users of the class could change the value of PaymentCalculator.MaximumHours. This is the behavior you want, so right-click the message and choose Suppress Message ⇒ In Source. The message CA1008 “Enums Should Have Zero Value PayCalculator.cs (Line 11)” also does not apply, as all employees are required to have an employee level, so there is no reason to set a zero value for PaymentCalculator.PayLevel. Suppress this message in source as well.

As you can see, suppressing messages can quickly add a number of attributes to your code. If you find that you always suppress a given message, it is probably better to exclude the rule altogether; then your code does not require the additional SuppressMessage attributes. However, as noted previously, use caution when doing this, because you could unintentionally be missing valid violations that should be addressed.

The warning CA2210 “Assemblies Should Have Valid Strong Names (Global)” applies to the overall assembly. If you know that you'll never use this assembly in the Global Assembly Cache (GAC), and will have no other need for strong names, you can suppress this message. Right-click the warning and select Suppress Message ⇒ In Suppression File. Do this for all the remaining warnings. However, because there is no specific code to which the SuppressMessage attribute can be applied, a new file, GlobalSuppressions.cs, is added to the project with the following code:

 [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(
    "Microsoft.Design",
    "CA2210:AssembliesShouldHaveValidStrongNames")]

There are two warnings left: CA 1034 “Nested Types Should Not Be Visible” and CA1053 “Static Holder Types Should Not Have Constructors PayCalculator.cs (Line 9)”. Suppress both warning messages, build the project, and you should now see an empty Code Analysis. This indicates all enabled Code Analysis rules have either been passed or suppressed.


Note
The effect of assembly-level suppression is basically the same as if you had excluded the rule altogether. The advantage of the attribute-based approach is that it is easy to see which rules have been suppressed project-wide by viewing the GlobalSuppressions.cs file. In addition, you could add comments to that file to indicate the reason for suppressing the rule to other developers. Excluding a rule by not selecting it in the Code Analysis section of the project's properties has the same effect but does not offer a way to document why certain exclusions were made.

Using the Command-Line Analysis Tool

A command-line interface is available for code analysis. You can find this tool, called FxCopCmd.exe, in your Visual Studio 2012 installation directory under Team ToolsStatic Analysis ToolsFxCop.

FxCopCmd can perform any of the code analysis functions that are available to you in the Visual Studio IDE. In fact, the IDE uses FxCopCmd under the covers to execute analysis and generate reports.

FxCopCmd Options

Table 19.3 shows some of the options that FxCopCmd.exe supports.

Table 19.3 FxCopCmd Options

Option Description
/f[ile]: <directory/file> Assembly file(s) or directory(ies) to analyze. If a directory is used without a filename, Code Analysis tries to analyze all files in that directory with .dll or .exe extensions. You can specify this option more than once. It is required, unless you specify a project file with the /project option.
/r[ule]: <directory/file> A rule assembly file or a directory to browse for rule assemblies. If a directory without a filename is supplied, Code Analysis looks for rules in any files with a .dll extension. You can specify this option more than once.
/r[ule]id:<[+|-] Enables or disables a specific rule, supplying its Category and Category#CheckId> values — for example, /rid: +!Microsoft.Usage#CA2225.
/ruleset:<<+|-|=>file> Specifies the rule set to be used for the analysis.
/rulesetdirectory:<directory> Specifies a directory to search for rule set files specified by the /ruleset switch.
/o[ut]:<file> Names a file in which the results of the analysis are stored in XML form. Required, unless the /console option is used.
/p[roject]:<file> Loads a project file that contains the settings for FxCopCmd to use (discussed shortly). Required if you do not use both the /file and /rules options.
/t[ypes]:<type list> Used to constrain analysis to only the specified type(s). Supply a list of comma-delimited type names. Wildcards can be used to specify multiple types. (Optional)
/i[mport]:<directory/file> Loads analysis reports or project files to exclude items from the current test that appear as excluded in the imported file. You may specify a file or a directory. If a directory is specified, Code Analysis attempts to load all files with an .xml extension. (Optional)
/s[ummary] Displays a summary after analysis. (Optional)
/v[erbose] Gives more detailed status output. (Optional)
/q[uiet] Suppresses output of status details. (Optional)
/u[pdate] Saves the results of the current analysis to the specified project file. Ignored if you do not supply the /project option. (Optional)
/c[onsole] Uses the console to display the analysis results. This is required unless you have specified the /out option.
/c[onsole]xsl:<file> Applies an XSL file to transform XML output before displaying.
/plat[form]:<directory> Location of platform assemblies. (Optional)
/d[irectory]: <directory> Location to search for assembly dependencies. (Optional)
/help (or) /? Help about command-line options.
/fo[rceoutput] Write output XML and project files, even in the case where no violations occurred.
/dic[tionary]:<file> Use a custom dictionary file.
/ignoreinvalidtargets [Short form: /iit] Silently ignore invalid target files.
/asp[net] Analyze only ASP.NET generated binaries, and honor global suppressions in App_Code.dll for all assemblies under analysis.
/searchgac [Short form: /gac] Search Global Assembly Cache for missing references.
/successfile [Short form: /sf] Create .lastcodeanalysissucceeded file in output report directory if no build-breaking messages occur during analysis.
/timeout:<seconds> [Short form: /to:<seconds>] Overrride timeout for analysis deadlock detection. Analysis is aborted when analysis of a single item by a single rule exceeds the specified amount of time. Specify a value of 0 to disable deadlock detection.
/savemessagestoreport: <Active|Excluded|Absent (default: Active)> [Short form: /smr:<Active|Excluded|Absent (default: Active)>] Save messages of specified kind to output report.
/ignoregeneratedcode [Short form: /igc] Suppress analysis results against generated code.
/overriderulevisibilities [Short form: /orv] Run all overridable rules against all targets.
/failonmissingrules [Short form: /fmr] Treat missing rules or rule sets as an error, and halt execution.
/cul[ture] Culture for spelling rules.
/outxsl:<file> [Short form: /oxsl:<file>] Reference the specified XSL in the XML report file; use /outxsl:none to generate an XML report with no XSL style sheet.
/applyoutxsl [Short form: /axsl] Apply the XSL style sheet to the output.

Notice that most of the commands have long and short forms available. For example, /summary and /s are equivalent. Arguments support the use of wildcards (*) to specify multiple items. Arguments with spaces in them must be surrounded with double quotes.

For example, to conduct analysis of a single assembly CustomLibrary.dll, use the following command:

FxCopCmd /f:SampleLibrary.dll /o:"FxCop Results.xml" /s

The /f (or /file) argument indicates which assembly to analyze, and the /o (or /output) option indicates that analysis output should be stored as XML in FxCop Results.xml. Finally, the /s (or /summary) option displays a short summary of the results of the analysis.

FxCopCmd Project Files

FxCopCmd's command-line options offer a good deal of flexibility, but to fine-tune your analysis you should consider using a project file. A project file enables you to set options such as targets and rule assemblies, exclusions, and output preferences. You can then simply use the /project option to tell FxCopCmd to use those settings, instead of supplying a detailed list of arguments.

You should create a default FxCopCmd project file that you can copy and customize for each project. Create a new file named EmptyCodeAnalysisProject.fxcop and enter the following:

<?xml version="1.0" encoding="UTF-8"?>
<FxCopProject Version="1.36" Name="Temporary FxCop Project">
        <ProjectOptions>
        </ProjectOptions>
        <Targets>
        <Target Name="$(TargetFile)" Analyze="True" AnalyzeAllChildren="True" />
        </Targets>
        <RuleFiles>
        </RuleFiles>
        <FxCopReport Version="1.36" LastAnalysis="2004-04-20 22:08:53Z">
        </FxCopReport>
 </FxCopProject>

Copy this to a new file and add your project's settings. The rules and files specified in your project file serve as the basis for FxCopCmd execution. You can specify additional rules and target files on the command line with the /rules and /file options.

For example, here is a simple project file that specifies a target assembly, SampleLibrary.dll, and includes one rule assembly, the default Code Analysis naming conventions assembly:

<?xml version="1.0" encoding="UTF-8"?>
<FxCopProject Version="1.36" Name="Sample Library Code Analysis Project">
        <ProjectOptions>
        </ProjectOptions>
        <Targets>
        
             <Target Name="C:SampleLibraryinDebugSampleLibrary.dll"
                  Analyze="True"
                  AnalyzeAllChildren="True" />
        </Targets>
        <RuleFiles>
             <RuleFile Name="$(FxCopDir)RulesNamingRules.dll" Enabled="True"
                  AllRulesEnabled="True" />
        </RuleFiles>
        <FxCopReport Version="1.36" LastAnalysis="2004-04-20 22:08:53Z">
        </FxCopReport>
</FxCopProject>

Save this to a file named SampleLibrary.fxcop. To execute Code Analysis for SampleLibrary using this project file, use the following command:

FxCopCmd /p:SampleLibrary.fxcop /o:"FxCop Results.xml" /s

Build Process Code Analysis Integration

You have now seen how to use FxCopCmd from the command line to analyze your code and report potential defects. However, with the full integration of code analysis with the Visual Studio IDE, why would you need to use FxCopCmd?

A common use of FxCopCmd is to enable automated code analysis from a build process. You can do this with Team Build, Visual Studio 2012's MSBuild, or one of many other build automation packages available (such as NAnt).

By integrating Code Analysis with your builds, you can ensure that your entire team's work is being evaluated against a consistent set of rules. You quickly discover when a developer has added nonstandard code. Developers quickly learn those rules and practices, because they don't want to be the person responsible for “breaking the build.”

Creating Code Analysis Rules

Visual Studio 2012 includes many code analysis rules, but no matter how comprehensive the rules from Microsoft are, they can never fully cover the specific requirements of your own projects. Perhaps you have specific naming conventions, or a standard way to load database connection strings. In many cases, you can create a custom code analysis rule to help diagnose the issue and help developers take corrective action.


Note
Creating custom code analysis rules is not for the faint of heart and is beyond the scope of this book. For more information on creating custom code analysis rules, including a step-by-step example, refer to the Microsoft Code Analysis Team Blog at 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.

Code Metrics

The Code Metrics tool is a set of software metrics that provide insight into the code that is being developed. Code Metrics provides a quick-and-easy way to determine the complexity of the code and to isolate code areas that may be difficult to maintain in the future. This can be especially helpful when maintaining a large or complex code base. Code metric information is calculated at the method level, and then rolled up all the way to the assembly level. Visual Studio 2012 calculates five different code metrics:

  • Cyclomatic Complexity — This measures the structural complexity of the code. It is created by calculating the number of different code paths through the code, including if statements, switch statements, and so on. A high number for Cyclomatic Complexity indicates that the code may be too complex and should be refactored.
  • Depth of Inheritance — This indicates the number of class definitions that extend to the root of the class hierarchy. Although inheritance in itself is not bad, having a lengthy inheritance level can make the code difficult to understand and troubleshoot. As with Cyclomatic Complexity, you want to have a low number for Depth of Inheritance.
  • Class Coupling — This indicates the total number of dependencies that a class has on other classes, based on parameters, local variables, return types, and method calls, base classes, interface implementations, fields defined on external types, and attribute decoration. This calculation does not include primitive or built-in types. A high level of Class Coupling indicates that changes in other classes could affect a specific class. You want a low number for Class Coupling.
  • Lines of Code — This indicates the number of executable lines of code in a method. This is an approximate count, based off the IL code, and only includes executable lines of code. Comments, braces, and white space are excluded. For Lines of Code, a low value is good, and a high value is bad.
  • The Maintainability Index — This is a combination of several metrics, including Cyclomatic Complexity, average Lines of Code, as well as computational complexity. This metric is calculated using the following formula:
MAX(0,(171-5.2*ln(Halstead Volume)-0.23*(Cyclomatic Complexity)-16.2*ln(Lines of Code))*100/171)
  • The Maintainability Index is a value between 1 and 100. Unlike the previous four metrics, for Maintainability Index, the higher the value, the easier the code is to maintain. Table 19.4 shows the Maintainability Index ranges and what they indicate.

Table 19.4 Maintainability Index Ranges

Color Level Range
Green High Maintainability Between 20 and 100
Yellow Moderate Maintainability Between 10 and 20
Red Low Maintainability Between 0 and 9

Some tools and compilers generate code that is automatically added to a project. Many times the developer is not aware of this code or shouldn't make changes to the generated code. For the most part, Code Metrics ignore generated code when it calculates values. This is important, because it enables the results to reflect only the code the developer can see and change.


Note
Code generated by Windows forms is not ignored, because that is code a developer can see and change.

You have the ability to generate code metrics for your entire solution, or for a selected project. To generate code metrics against the entire solution, do one of the following:

  • Click the Analyze menu option and then select Calculate Code Metrics For Solution.
  • Right-click the solution in Solution Explorer and select Calculate Code Metrics.

To generate code metrics for one or more projects in a solution, first select all the projects to be involved and then do one of the following:

  • Click the Analyze menu option and then select Calculate Code Metrics For Selected Project(s).
  • Right-click the solution in Solution Explorer and select Calculate Code Metrics.

The Code Metrics Results window displays with the results, as shown in Figure 19.5.

You can drill down into the results using the triangle controls located to left of the Hierarchy column. You can filter the results using the toolbar at the top of the window. The Filter dropdown box contains the names of all the results columns. Select a column in the dropdown box and then enter a minimum number value. The results are then filtered accordingly. The dropdown box keeps track of the last ten filters that you defined.

You can copy a row of results to the clipboard as a text string by right-clicking a row in the results window and selecting Copy. This copies both the name and value of each column on the selected row. You can also right-click a row and select Open Selection in Microsoft Excel. This takes all the information from that row, and all rows nested underneath that row, and opens them in a workbook in Microsoft Excel.

Finally, you can create a Team Foundation work item based off a row of results in the Code Metric Results window. Right-click a row of results, select Create Work Item, and then select the appropriate work item type, such as Task. This creates a new work item, with the title set to the hierarchy name of the row selected, and copies the code metric data for that line into the history tab.

Code Clone Analysis

As developers, we are often guilty of copying blocks of code from a class or project to another class or project if it provides all or most of the functionality that we need. When these separate fragments of code are very similar, they're referred to as code clones. Code clones can make it difficult to make application updates because you have to find and make the same or similar changes in multiple areas of your code base. Many times it makes sense to refactor the code clones into a single location. However, it can be very difficult to isolate all the areas where code clones exist, especially in older code bases.

This is where code clone analysis (also referred to as code clone detection) comes into play. Code clone analysis enables you to look across your entire solution for blocks of code that are similar in structure and composition. One nice feature is that the blocks of code do not have to be identical. Code clone analysis is adept at finding blocks of code that are similar but not necessarily exact. For example, blocks of code that are similar but have different variable names or parameters — or have statements in a different order — can be detected through analysis.


Note
Code clone analysis only works for Visual C# and Visual Basic projects in Visual Studio 2012.

Finding Code Clones

There are two main ways for using code clone analysis: analyzing the entire solution for all potential code clones or finding instances of a selected code fragment through the solution.

Analyzing the entire solution searches through all the projects in the solution, looking for instances of code clones. This can be particularly useful during code reviews. It is important to note that code clones of fewer than ten statements are not discovered when the entire solution is being analyzed. To analyze the entire solution, select Analyze ⇒ Analyze Solution for Code Clones from the main menu in Visual Studio 2012. Figure 19.6 shows the results of the analysis, shown in the Code Clone Analysis Results window.

By default the results are grouped and sorted based on the strength of the match. Exact matches are shown first, followed by matches that are close (i.e. strong) but not necessarily exact. In Figure 19.6, you have one strong match. There are two other match terms for describing matches — Medium and Weak — each denoting a code clone that is less exact.

You can also use code clone analysis to find a particular code fragment in a solution. Unlike an analysis of the entire solution that was shown earlier, this type of search can find cone clones less than ten lines in length. To search for a specific fragment of code, highlight the code fragment, right-click it, and select Find Matching Clones in Solution from the context menu. The solution searches for a match to the code fragment and displays the results in the Code Clone Analysis Results window.

Reviewing the Code Clone Analysis Results

You have a couple of different options for analyzing the results provide by code clone analysis. In the Code Clone Analysis Results window, you can hover your mouse over a specific line to show the matching code in a pop-up window. This provides you a way to quickly see the code for that particular match. You can also double-click a line in the results window to automatically open the file containing the code clone; then you can navigate to its location within the file. Opening the file in this way automatically color codes the code clone, to make it easy to find.

You also have the ability to compare two files using the same tool that is used to compare versions in source control in Team Foundation Server. To do this, select two files listed in the Code Clone Analysis Results window, right-click the selection, and choose Compare from the context menu. This opens the new comparison tool in Visual Studio 2012 so you can view the two code clones side by side.

How Code Clone Analysis Works

Code clone analysis finds both exact copies of code and similar code that is not exact. Code clones usually result from developers copying a chunk of code and then making modifications to the code based off its new requirements. You can make the following modifications, and the clone will still be recognized:

  • Rename identifiers
  • Add new statements
  • Delete statements
  • Rearrange statements

Even if you can make any of these modifications to a code clone, the clone is still flagged during analysis. There are rules for what is not found as well, including the following:

  • Two classes with similar sets of field declarations (type declarations are not compared; only statements in methods and property definitions are compared)
  • Fragments with more than 40 percent changed tokens
  • Code elements that have been specifically excluded from code clone analysis via a.codeclonesettings file
  • Certain generated code, including .designer.cs files, .designer.vb files, and InitializeComponent methods

Excluding Items from Code Clone Analysis

At the project level you can exclude items from code clone analysis by using a .codeclonesettings file. This is an XML file that must exist in the top-level directory of the project. You can use this file to exclude specific files or specific methods from analysis.

The base elements of the exclusion file consists of a CodeCloneSetting element with an Exclusions child.

<CodeCloneSettings>  
    <Exclusions>    
    .
    .
    .
    </Exclusions>    
    </CodeCloneSettings>

Within the Exclusions element, you list the different exclusions, including File, Namespace, Type, and FunctionName.

<CodeCloneSettings>  
    <Exclusions>    

        <File>MyFile.cs</File>
        <File>MyTemplates*.cs</File>

        <Namespace>MyCompany.MyProject</Namespace>
        <Namespace>*.AProject</Namespace>

        <Type>MyCompany.MyProject.MyClass</Type>
        <Type>*.AClass*</Type>

        <FunctionName>MyCompany.MyProject.MyClass.MyMethod</FunctionName>
        <FunctionName>MyProject.*.AMethod</FunctionName>

    </Exclusions>    
</CodeCloneSettings>

As you can see, you can either use absolute names or names containing wildcards.

Summary

This chapter demonstrated the need for static analysis tools and introduced you to the .NET Framework “Design Guidelines for Class Library Developers.” These guidelines are a very important resource that Microsoft has made freely available, and they're the basis for Visual Studio 2012's included Code Analysis rules.

In this chapter, you learned about the Code Analysis tool, including how it now integrates with Visual Studio 2012 and enables rule analysis to be performed with a simple build. You learned how to configure and execute analysis, and how to work with the resulting rule violation messages.

To support projects using a repeatable build process, or those that need additional flexibility, you learned how to use the command-line Managed Code Analysis tool, and how to create FxCopCmd project files to store settings.

Next, you were introduced to Code Metrics. The five different code metric values were explained, and you saw how easy it was to run and view the results of the code metrics calculation.

Finally, you learned about Code Clone Analysis, and how you can use this tool to find code clones, or similar fragments of code, throughout your solution.

Chapter 20 looks at the code profiling capabilities of Visual Studio 2012, and how you can use them to find and fix performance problems in your code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.181.36