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.
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.
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.
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
. Rename the SampleLibrary
file to Class1.cs
and insert the following code, which fails to meet several code analysis guidelines:PayCalculator.cs
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).
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 , and formatting. |
Interoperability (16) | This group is focused on the correct use of COM Interop. Included are rules for proper use of , the 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.
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.
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.
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:
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.
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.
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
assembly.SampleLibrary
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:
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
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.SampleLibrary
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
, and is located in your project's build output directory (that is, >.CodeAnalysisLog.xml
or inDebug
). For the inRelease
project, the file is SampleLibrary
.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.
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
Several issues should be addressed in the sample
class. For each warning or error, you must determine whether the rule actually applies to your project or a specific section of code.PayCalculator
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.
Looking through the Error List shown in Figure 20.3, you should see item
, with a description of CA1810
.Initialize reference type static fields inline PayCalculator.cs (Line 22)
Click the error number (
) to display the documentation for the rule that triggered this warning, including suggestions for resolving the issue. You are currently assigning the value of CA1810
to 100
inside the static constructor of MaximumHours
. The rule's Help text states that your code may perform more efficiently if you make that assignment when the variable is defined.PayCalculator
To address this issue, click this warning to see the static constructor of the
class. Change the code to assign the value in the declaration as follows:PayCalculator
public static int MaximumHours = 100;
Next, delete the static
constructor entirely. Build the project and look at the Code Analysis window. The specific warning should no longer be in the list.PayCalculator
There is another easy problem to correct. Many of the code analysis rules relate to standard naming conventions. Find the warning CA1707
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 Identifiers should not contain underscores PayCalculator.cs (Line 11)
enumeration and choose Refactor⇒Rename. Change the name to Pay_Level
, click OK, and then Apply.PayLevel
Mark the
class definition static as follows:PayCalculator
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
correctly; CA ArgumentOutOfRangeException
2208
. 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:Instantiate argument exceptions correctly PayCalculator.cs (Line 26)
if (hours > MaximumHours)
{
throw new ArgumentOutOfRangeException(“hours”, “Employee works too much”);
}
One of the remaining warnings, CA1014
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.Mark assemblies with CLSCompliantAttribute (Global)
To address this warning, open
and add the following line:AssemblyInfo.cs
[assembly: System.CLSCompliant(true)]
The
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 assembly:
file.AssemblyInfo.cs
Now, build the project. The violations you corrected should no longer generate messages in the Error List. The remaining four warnings are addressed shortly.
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
attribute to a code construct, such as a field, method, or class, and to an entire assembly.SuppressMessage
Let's continue with the
example and use message suppression to clean up more of the code analysis violation messages.SampleLibrary
The warnings for
statesCA1709
. Assume that your organization has different naming conventions for constants, and you know that this rule does not apply to this , Identifiers should be cased correctly PayCalculator.cs (Line 19)
constant. Right-click the message and choose Suppress Message⇒In Source. The message is crossed out in the Code Analysis window, and the BONUS
class is modified to include the following attribute immediately before the declaration of PayCalculator
: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
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.CA1709
Two more messages don't apply to the project. CA2211
reminds you that external users of the class could change the value of Non-constant fields should not be visible PayCalculator.cs (Line 18)
. This is the behavior you want, so right-click the message and choose Suppress Message⇒In Source. The message PaymentCalculator.MaximumHours
CA1008
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 Enums should have zero value PayCalculator.cs (Line 11)
. Suppress this message in source as well.PaymentCalculator.PayLevel
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
attributes. However, as noted previously, use caution when doing this, because you could unintentionally be missing valid violations that should be addressed.SuppressMessage
The warning
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 CA2210 Assemblies should have valid strong names (Global)
attribute can be applied, a new file, SuppressMessage
, is added to the project with the following code:GlobalSuppressions.cs
[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.
A command-line interface is available for code analysis. You can find this tool, called
, in your Visual Studio 2013 installation directory under FxCopCmd.exe
.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.
Table 20.3 shows some of the options that
supports.FxCopCmd.exe
Table 20.3 FxCopCmd Options
Option | Description |
|
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 . or . extensions. You can specify this option more than once. It is required, unless you specify a project file with the option. |
|
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 . extension. You can specify this option more than once. |
|
Enables or disables a specific rule, supplying its and values — for example, . |
|
Specifies the rule set to be used for the analysis. |
|
Specifies a directory to search for rule set files specified by the switch. |
|
Names a file in which the results of the analysis are stored in XML form. Required, unless the option is used. |
|
Loads a project file that contains the settings for FxCopCmd to use (discussed shortly). Required if you do not use both the and options. |
|
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) |
|
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 . extension. (Optional) |
|
Displays a summary after analysis. (Optional) |
|
Gives more detailed status output. (Optional) |
|
Suppresses output of status details. (Optional) |
|
Saves the results of the current analysis to the specified project file. Ignored if you do not supply the option. (Optional) |
|
Uses the console to display the analysis results. This is required unless you have specified the option. |
|
Applies an XSL file to transform XML output before displaying. |
|
Location of platform assemblies. (Optional) |
|
Location to search for assembly dependencies. (Optional) |
|
Help about command-line options. |
|
Write output XML and project files, even in the case where no violations occurred. |
|
Use a custom dictionary file. |
|
Silently ignore invalid target files. |
|
Analyze only ASP.NET generated binaries, and honor global suppressions in for all assemblies under analysis. |
|
Search Global Assembly Cache for missing references. |
|
Create . file in output report directory if no build-breaking messages occur during analysis. |
|
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 to disable deadlock detection. |
|
Save messages of specified kind to output report. |
|
Suppress analysis results against generated code. |
|
Run all overridable rules against all targets. |
|
Treat missing rules or rule sets as an error, and halt execution. |
|
Culture for spelling rules. |
|
Reference the specified XSL in the XML report file; use to generate an XML report with no XSL stylesheet. |
|
Apply the XSL stylesheet to the output. |
|
Reference assemblies required for analysis. |
Notice that most of the commands have long and short forms available. For example,
and /summary
are equivalent. Arguments support the use of wildcards (/s
) to specify multiple items. Arguments with spaces in them must be surrounded with double quotes.*
For example, to conduct analysis of a single assembly
, use the following command:CustomLibrary.dll
FxCopCmd /f:SampleLibrary.dll /o:"FxCop Results.xml" /s
The
(or /f
) argument indicates which assembly to analyze, and the /file
(or /o
) option indicates that analysis output should be stored as XML in /output
. Finally, the FxCop Results.xml
(or /s
) option displays a short summary of the results of the analysis./summary
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
option to tell FxCopCmd to use those settings, instead of supplying a detailed list of arguments./project
You should create a default FxCopCmd project file that you can copy and customize for each project. Create a new file named
and enter the following:EmptyCodeAnalysisProject.fxcop
<?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
and /rules
options./file
For example, here is a simple project file that specifies a target assembly,
, and includes one rule assembly, the default Code Analysis naming conventions assembly:SampleLibrary.dll
<?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
. To execute Code Analysis for SampleLibrary.fxcop
using this project file, use the following command:SampleLibrary
FxCopCmd /p:SampleLibrary.fxcop /o:"FxCop Results.xml" /s
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.
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.
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:
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.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:
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:
The Code Metrics Results window displays with the results, as shown in 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.
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.
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.
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.
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.
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:
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:
.codeclonesettings
file.designer.cs
files, .designer.vb
files, and InitializeComponent
methodsAt the project level you can exclude items from code clone analysis by using a
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..codeclonesettings
The base elements of the exclusion file consists of a
element with an CodeCloneSettings
child:Exclusions
<CodeCloneSettings> <Exclusions> . . . </Exclusions> </CodeCloneSettings>
Within the
element, you list the different exclusions, including Exclusions
, File
, Namespace
, and Type
: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.
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:
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
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 CustomersController
link. A pop-up window (Figure 20.9) will open, showing the references to this class.3 References
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.
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.
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.