Chapter 20
Code Analysis, Code Metrics, Code Clone Analysis, and CodeLens

What's in this chapter?

  • Enabling and running code analysis in Visual Studio 2013
  • Correcting code analysis rule violations
  • Understanding code metrics and how to use them
  • Using Code Clone Analysis to find similar code fragments in the code base
  • Using CodeLens to better understand the code base

Wrox.com Code Downloads for this Chapter

The wrox.com code downloads for this chapter are found at www.wrox.com/go/proalm3ed on the Download Code tab. The files are in the Chapter 20 download folder and individually named as shown throughout this chapter.

This chapter describes the code analysis, code metrics, code clone analysis, and CodeLens features included with the Visual Studio 2013. Code analysis is available in Visual Studio 2013 Professional and higher SKUs. Code metrics and code clone analysis are available in Visual Studio 2013 Premium and higher SKUs. And CodeLens is available in Visual Studio 2013 Ultimate. 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 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 2013.

Then you explore the code analysis a bit and learn how to take advantage of its full integration with Visual Studio 2013. This includes enabling 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 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. After that, you learn about code clone analysis, and how it enables you to find fragments of similar code throughout your code base, making it easier to apply changes or refactor your code.

The chapter wraps up with a look at a new feature in Visual Studio 2013: CodeLens. CodeLens enables you to see information about your code directly in the code editor, such as method references and code changes, without having to navigate through multiple windows in Visual Studio.

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 “Framework Design Guidelines.” These guidelines document Microsoft's best practices for using the .NET Framework, 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 2013

For Visual Studio 2013, the focus was on fixing bugs in response to user feedback. That did not stop the team, however, from adding a couple of new improvements to the user experience.

Visual Studio 2013 has added categories for the native code analysis rules, and now exposes the existing managed code analysis categories in the user interface. These categories provide a more fine-grained grouping of defects to indicate, for example, if a defect is related to a logic error or a syntax error. Categories can also be helpful when dealing with a large list of warnings, allowing you to focus on the more relevant categories.

Another new user interface feature allows you to sort the code analysis results by various properties, including Rule ID and Category. Support has been added for sorting the defect list by six common properties.

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 runtime 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 20.1 describes the groups of rules included with Visual Studio 2013.

Table 20.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 2013, 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 20.2 shows the rule sets included with Visual Studio 2013.

Table 20.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 ⇒ New ⇒ 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 one.

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-side tabs. You see a drop-down of the different rule sets available for use with code analysis, as shown in Figure 20.1.

image

Figure 20.1

To enable code analysis upon build, select the Enable Code Analysis on Build check box. Select the desired rule set in the drop-down listbox, 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 drop-down listbox 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 check boxes.

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 drop-down 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 20.2 illustrates how to enable and disable specific rules and how each can be set to Warning or Error as necessary.

image

Figure 20.2

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 drop-down menu and then review your settings. To make changes that affect 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.

The output window includes details about your build, including results from calling code analysis. After the build, the Code Analysis window may appear. If you do not see the Code Analysis window, choose Analyze⇒Windows⇒Code Analysis. By default this window appears as a tab in the 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 20.3 shows the Code Analysis window displaying code analysis results for the SampleLibrary assembly.

image

Figure 20.3

The 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 drop-down 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. The Sort drop-down box is a new feature, allowing you to sort the results by one of six different options:

  • By Rule ID
  • By Rule Name
  • By File Path
  • By File Name
  • By Line Number
  • By Category

You also have the ability to then sort in ascending or descending order by clicking a small arrow on the menu.

Directly below the search box are two drop-down filter boxes. The first enables you to filter the results based on the project name. The second enables you to filter based on the rule category, such as Design or Performance.

Analysis of the SampleLibrary code indicates nine 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, as well as navigates you to the offending line of code in the code editor.

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.

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 20.4.

image

Figure 20.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 20.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, 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 11) 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 PayCalculator 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 26). 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 four warnings are addressed shortly.

Suppressing Messages

Visual Studio 2013 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.

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")]

Now build the project, and you should now see an empty Code Analysis window. This indicates all enabled code analysis rules have either been passed or suppressed.

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 2013 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 20.3 shows some of the options that FxCopCmd.exe supports.

Table 20.3 FxCopCmd Options

Option Description
/f[ile]: <directory/file> Assembly file(s) or directory(ies) to analyze. If a directory is used without a file name, 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 file name 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>] Override time-out 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 stylesheet.
/applyoutxsl [Short form: /axsl] Apply the XSL stylesheet to the output.
/reference:<file> [Short form: /ref:<file>] Reference assemblies required for analysis.

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="US-ASCII" standalone="no"?><!DOCTYPE WileyML3G [<!ENTITY % wileyml3g.ent SYSTEM "http://v.wiley.com:3535/dtds/wileyml3g/wiley.ent">%wileyml3g.ent;]>
<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="US-ASCII" standalone="no"?><!DOCTYPE WileyML3G [<!ENTITY % wileyml3g.ent SYSTEM "http://v.wiley.com:3535/dtds/wileyml3g/wiley.ent">%wileyml3g.ent;]>
<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 Foundation Build, Visual Studio 2013'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 2013 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.

Code Metrics

The Code Metrics tool is a set of software metrics that provide insight into the code that is being developed. Code metrics provide 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 2013 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, 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 whitespace 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:
equation

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 20.4 shows the Maintainability Index ranges and what they indicate.

Table 20.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.

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 20.5.

image

Figure 20.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 drop-down box contains the names of all the results columns. Select a column in the drop-down box and then enter a minimum number value. The results are then filtered accordingly. The drop-down 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 Metrics 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.

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 2013. Figure 20.6 shows the results of the analysis, shown in the Code Clone Analysis Results window.

image

Figure 20.6

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 20.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 code 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 provided 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 comparison tool in Visual Studio 2013 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 on 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 CodeCloneSettings 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.

Using CodeLens

CodeLens is a new feature in Visual Studio 2013 that shows you information about your code, directly in the code editor. Before, you had to dig through several different windows to retrieve information such as method references, tests associated with a method, how many times a line of code has been changed, and when it was last changed. Researching this information pulls you away from actually writing code, and can impact productivity. With CodeLens, this information is literally at your fingertips.

CodeLens is turned on by default in Visual Studio 2013. You can control the information that will be displayed in the code editor through the Visual Studio options menu. In Visual Studio, select Tools ⇒ Options⇒to open the Options window (shown in Figure 20.7), then select Text Editor ⇒ All Languages ⇒ CodeLens to modify what information is shown. By default, CodeLens will show the following:

  • Test Status
  • References
  • Tested By
  • Authors
  • Changes
  • Bugs
  • Work Items
  • Code Reviews
image

Figure 20.7

Figure 20.8 shows a code file with CodeLens information displayed. The CodeLens information appears in light grey above each method. In Figure 20.8 you can see that the public class CustomersController has three references, has been recently edited by Brian Keller, as well as two other people, and has been included in four changesets. To see where this class is referenced, click the 3 References link. A pop-up window (Figure 20.9) will open, showing the references to this class.

image

Figure 20.8

image

Figure 20.9

In Figure 20.8, clicking the Brian Keller + 2 or the 4 Changes links displays a list of information, including the changeset ID, the changeset description, the changeset author, and when the changesets were created. From within this window (shown in Figure 20.10), you can right-click a row and view changeset detail information, and view the diff information for the changeset. You also have presence information for the author of the changeset, and can contact her via email.

image

Figure 20.10

Another CodeLens indicator is the Tested By indicator, which shows the tests available that test a particular method. To enable this data, you need to first open the Test Explorer window. You can do this by selecting Test ⇒ Windows ⇒ Test Explorer. Once the Test Explorer window is open, a new indicator will be added to the CodeLens information, showing information on the tests associated with the method. In Figure 20.11, you can see there are two tests associated with this method, and that neither test has been executed yet. To execute the tests, simply click the Run All link. The CodeLens information will then be updated with the pass/fail results of the tests.

image

Figure 20.11

Summary

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

You also learned about the Code Analysis tool, including how it integrates with Visual Studio 2013 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.

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

Finally, you learned about CodeLens, a new feature that enables you to see information about your code, directly in the code editor, such as method references and code changes, without having to navigate through multiple windows in Visual Studio.

Chapter 21 looks at the code-profiling capabilities of Visual Studio 2013, 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
52.15.42.128