Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Diving Into Visual Studio 2015, Day 2: Code Analyzers

DZone's Guide to

Diving Into Visual Studio 2015, Day 2: Code Analyzers

In this article, author Akhil Mittal covers the Live Static Code Analysis feature in Visual Studio 2015, using practical examples to show you how it works.

· Web Dev Zone
Free Resource

Get deep insight into Node.js applications with real-time metrics, CPU profiling, and heap snapshots with N|Solid from NodeSource. Learn more.

This is the second article in my Diving into Visual Studio 2015 series. In the first article of the series, we learned about Visual Studio’s capability of code suggestions and code optimizations. You can read more about code suggestion in Day #1. In this article, we’ll cover another interesting and very useful feature of Visual Studio 2015: Live Static Code Analysis. The feature’s name is self-explanatory. Visual Studio provides a developer with the ability to know about optimization techniques as well as compile time errors while coding (i.e. a developer is not supposed to compile the code, again and again, to know about compile time errors or code optimizations; instead he can view all of these on the fly while coding and fix it then and there.) Let’s cover the topic in detail with practical examples.

Live Static Code Analysis

Live Static Code Analysis is not a sentence or a phrase; each and every word has a unique meaning that adds value to the overall feature. Live means you can get the code analysis on the fly while you type your code. You get a real-time code check facility without even compiling the code explicitly. Static means analyzing the code when it is not in running state. This feature is intended to save a lot of development time while coding. The code is checked through pre-defined analyzers while you type and you don’t have to build/compile the application again and again. Moreover, these analyzers (apart from just showing errors) also provide certain warnings or suggestions while coding that improves a developer’s coding skills, enabling him to follow best coding practices. These built-in analyzers work on a specific set of rules, and the code when written is validated while typing against these rules.

Analyzers can be availed via Nuget Packages installed in Visual Studio. There are numerous analyzers available in Visual Studio 2015. In earlier versions of Visual Studio there were very few of them available, but now you can get analyzers for each and every approach that you use in Visual Studio for development. There are analyzers available for Azure, Unit tests, Exception handling, Mocks, ORM etc. You can choose analyzers as per your need.

The best thing that this feature provides is that you can build your own analyzer against the type of code you want. This means you can define your own set of rules for coding and these rules will be invoked against the live code that you or any other developer is writing. The rules may include warnings, errors, suggestions, automated code fixes, etc. Let's look at some examples on how to leverage this capability.

Code Analyzers

Create a console application that contains simple arithmetic operations as methods. I have created one in Day#1 of this article series and will use the same. The name of the console application used in this article is VS2015ConsoleApplication. It contains an interface named ICalculator and a class named Calculator that inherits from mentioned interface as shown below.

ICalculator

 1: using System;
 2: using System.Collections.Generic;
 3: using System.Linq;
 4: using System.Text;
 5: using System.Threading.Tasks;
 6:
 7: namespace VS2015ConsoleApplication
 8: {
 9:     interface ICalculator
10:     {
11:         int Add(int a, int b);
12:         int Subtract(int a, int b);
13:         int Multiply(int a, int b);
14:         float Divide(float a, float b);
15:     }
16: }

Calculator

 1: using System;
 2: using System.Collections.Generic;
 3: using System.Linq;
 4: using System.Text;
 5: using System.Threading.Tasks;
 6:
 7: namespace VS2015ConsoleApplication
 8: {
 9:     public class Calculator : ICalculator
10:     {
11:         public int Add(int a, int b)
12:         {
13:            throw new NotImplementedException();
14:         }
15:
16:         public float Divide(float a, float b)
17:         {
18:             throw new NotImplementedException();
19:         }
20:
21:         public int Multiply(int a, int b)
22:         {
23:            throw new NotImplementedException();
24:
25:         }
26:
27:         public int Subtract(int a, int b)
28:         {
29:             throw new NotImplementedException();
30:         }
31:     }
32: }
33:

As one can see there is not enough code. We’ll use this code just to check out and understand the feature and concepts behind Live Static Code Analysis.

Right-click on the project file in Visual Studio and click on Manage Nuget Packages... option from the context menu.

When you click on this option a window will be launched in the IDE where you get an option to check for installed packages, updates for existing packages, or browse for new Nuget Packages. Use search box to search for a keyword named "Analyzer" as shown below.


You’ll see that a number of code analyzers will appear on the window. When you click them, they show the description in the right side window. Here we get a choice to use whatever analyzer we need to use with our existing project. We’ll use one of the analyzers to check its capability. I have chosen "codecracker.CSharp" analyzer for further explanation and detailing. Scroll down to this analyzer and click on codecracker.CSharp and install it by clicking install button as shown in below image.

Once installed, the package manager console in visual studio will show the message for successful installation as shown below.

And in Visual Studio, under References a new reference will be named saying "Analyzers->CodeCracker.Common,CodeCracker.CSharp". Analyzers is the root reference where multiple analyzers can lie.

In addition to that a new "packages.config" file will be added having following code that contains package’s information.

1: <?xml version="1.0" encoding="utf-8"?>
2: <packages>
3:   <package id="codecracker.CSharp" version="1.0.0" targetFramework="net45" />
4: </packages>

Since we can see the packages.config and a reference added in the solution that means the analyzer we downloaded from Nuget is successfully installed for the console application project. You can check all set of rules of the chosen analyzer by clicking on the arrow of analyzer under reference in Visual Studio. Click on "CodeCracker.CSharp" and get a list of all the messages, info, suggestions, warnings and errors that this set contains.

Each rule has a particular syntax like a unique code associated to it, with a descriptive symbol like a warning, error, information, suggestion and a descriptive text. For an example, if we check the first rule, it signifies that it is a sort of warning/suggestion with unique code CC0001 having a description as, "You should use ‘var’ whenever possible." This means that, while coding, if any such situation occurs where this rule violates, we’ll be shown a message like that with a warning symbol.

Code Analysis

Let us write some code to check how analyzers work. The following is some code I have written to implement Divide method in Calculator class.

 1: public float Divide(float a, float b)
 2:        {
 3:            try
 4:            {
 5:                float result;
 6:                result = a / b;
 7:                Console.WriteLine(String.Format("Results", result));
 8:                return result;
 9:
10:            }
11:
12:            catch { }
13:
14:        }

The above-mentioned code block is purposely written in a way that may result in some compile time error. While writing the code, keep the Error List window open. You’ll notice that while writing the code, whenever you violate any of the Code Analyzer rules, it immediately flashes in the Error List window. It shows that you are getting the feedback and optimizations options on the fly while coding, and you do not have to depend upon compiling the code. For example, check the following image. I have written the code and till now not compiled the project.

We see that two warnings are shown that means while writing the code we broke two rules of installed code analyzer. The first one says it is warning with code CC0111 with a description that number of arguments for "String.Format" method is incorrect. I purposely wrote the code in this way to explain how code analyzers work. As we can see and compare that the rule shown to us in Error List window matches exactly to that of shown in Code Analyzer's set of rules list at right side. This proves the code analyzer is working as desired. Here we see that we need not have to compile the application and as soon as we fix the code, the error/warning of code analyzer is gone. I purposely left catch block empty so that the code analyzer may validate the code against its defined rule for catch block and suggest us. It clearly says CC0004 Empty catch Block rule is violated.

Case Study

Let us take another scenario and see how analyzers help in providing constructive suggestions w.r.t. code fix or optimization. The following code implements "Multiply" method, there are few errors, some un-optimized code in this method.

 1: public int Multiply(int a, int b)
 2:  {
 3:      try
 4:      {
 5:          int times = 7;
 6:          int result = 0;
 7:          result = a * b;
 8:          return result;
 9:
10:      }
11:
12:      catch { }
13:
14:
15:  }

While writing this code I got following messages, warnings and errors in Error List window.

Note that the Error List window here is configured for Current Document. You can change that to Current Project or all open documents as per your requirement. It shows 1 error, 4 warnings and 1 message. The error is displayed by compiler, but the warnings and message are displayed through the analyzer that we have used in this project. The warnings are self-explanatory. If you don’t know how to fix them, the light bulb icon helps you to fix those. For CC0105, for example, use var instead of specifying a type name, if you click on int times=7; the light bulb icon will be shown with few suggestions as shown below.

We see here that Light bulb icon is smart enough to take care of analyzer’s suggestions and provide constructive workarounds to fix the code. The first suggestion is use ‘var’. You can have a preview before you actually apply it, and it’s your choice whether you want to make this fix in the opened document, project or solution. Another suggestion that the light bulb icon gives is making the variable as constant. It suggests so because it is smart enough to analyze that the variable is having a fixed value throughout the method. Since the variable is not used anywhere in the method, it suggests to remove that unused variable therefore optimizing the code.

There are other suggestions like Suppress CC0105, CC0030, CS 0219. Light bulb icon provides you an option for what to do with similar kind of warnings and errors in the future. In case you do not want a suggestion to be shown for a particular analyzer warning or message, then you can opt to suppress that message which means it will not be shown again.

There are two ways in which you can perform suppression and code suggestion gives you the option to choose any of two with a preview.

1. In Source. You can suppress the warning/message/error for that particular line of code as shown in above image. In this case, a #pragma statement will encapsulate the underlying code and you’ll not be shown the message again. The code becomes like shown below.

 1: public int Multiply(int a, int b)
 2:        {
 3:            try
 4:            {
 5: pragma warning disable CC0105 // You should use 'var' whenever possible.
 6:                int times = 7;
 7: pragma warning restore CC0105 // You should use 'var' whenever possible.
 8:                int result = 0;
 9:                result = a * b;
10:                return result;
11:
12:            }

2. In suppression file. Another option is to put that suppression in a separate file, which means the suppression is at project level and you’ll not be shown the message/warning for this rule throughout the code in this particular project. This option creates a separate class file and adds to your project.

The file is named GlobalSuppressions.cs and contains following format for the suppressed messages.

1:
2: // This file is used by Code Analysis to maintain SuppressMessage
3: // attributes that are applied to this project.
4: // Project-level suppressions either have no target or are given
5: // a specific target and scoped to a namespace, type, member, etc.
6:
7: [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "CC0105:You should use 'var' whenever possible.", Justification = "<Pending>", Scope = "member", Target = "~M:VS2015ConsoleApplication.Calculator.Multiply(System.Int32,System.Int32)~System.Int32")]
8:

In this particular example I am not opting to suppress the message, instead I’ll go for fixing as per code analyzer’s recommendations. Let us make a fix for CC0105 first.

 1: public int Multiply(int a, int b)
 2:        {
 3:            try
 4:            {
 5:                var times = 7;
 6:                var result = 0;
 7:                result = a * b;
 8:                return result;
 9:
10:            }
11:
12:            catch { }
13:
14:
15:        }

Therefore, the Error List window becomes as shown below.

We see here that the first warning has been taken care of and now not shown here. Now fix the CS0219.

Since we are not using the variable I’ll go for removing the unused variable as suggested by Light Bulb Icon.preview the changes and apply it to code. This will remove the times variable from the code. now we are left with following code.

 1: public int Multiply(int a, int b)
 2:        {
 3:            try
 4:            {
 5:                var result = 0;
 6:                result = a * b;
 7:                return result;
 8:
 9:            }
10:
11:            catch { }
12:
13:
14:        }

And the following Error List which shows one error and one is warning. The warning is regarding an empty catch block that we are using i.e. CC0004 marked in analyzer’s rule list.

Again, when you click on the light bulb icon that shows while you click on catch block code, you’ll see multiple code suggestion options to fix this code as shown below.

There are various options you can choose for your empty catch block code like 1. Removing the try catch block. You can choose this option if you have nothing to do with exceptions or maybe you accidently applied try catch block. If you go for option 2 (Remove Empty catch Block and put a Documentation) this option will remove the try-catch block and mark a TODO item there. If you preview the option and apply the fix, you’ll get following code for this method.

1: public int Multiply(int a, int b)
2:        {
3:            {
4:                var result = 0;
5:                result = a * b;
6:                return result;
7:
8:            }
9:            //TODO: Consider reading MSDN Documentation about how to use Try...Catch => http://msdn.microsoft.com/en-us/library/0yd65esw.aspx

The method puts a commented TODO item stating to read MSDN documentation to read about how to use try-catch.

We have already seen how to suppress a message and warning, so let us try the third option i.e. Insert Exception class to catch. Note that you don’t have to explicitly write catch block unless you have some custom requirement in the case. Just choose the third option and preview changes.

You can see the option will insert implementation for catch block with Exception class object as a parameter and throw as exception in case catch block gets invoked. Therefore, the code becomes as follows:

 1: public int Multiply(int a, int b)
 2:        {
 3:            try
 4:            {
 5:                var result = 0;
 6:                result = a * b;
 7:                return result;
 8:
 9:            }
10:
11:            catch (Exception ex)
12:            {
13:                throw;
14:            }

But as soon as you make this change, you’ll see that error that was shown earlier has been taken care of because now there is return at every exit point of method but a new warning is introduced as shown below.

This image shows that we are trying to declare a variable in catch block that we are not using. Again, you can take help from the light bulb icon.

There are two options, either remove the variable or suppress the message. Alternatively, you can also apply your coding skills and do something with that variable in the code block itself, like displaying the error message, logging etc. I’ll choose first option i.e. remove the unused variable. Immediately after choosing that option the variable gets removed and our code becomes cleaner as shown below with absolutely no error, warnings or messages.

 1: public int Multiply(int a, int b)
 2:  {
 3:      try
 4:      {
 5:          var result = 0;
 6:          result = a * b;
 7:          return result;
 8:      }
 9:      catch (Exception)
10:      {
11:          throw;
12:      }
13:  }

Conclusion

In this article we covered another great feature of Visual Studio 2015: Live Static Code Analysis. I explained a case study in detail but you may explore other rules and code scenarios while you play around with this feature. I again want to mention that you can try this feature and explore its capability of helping in code analysis and optimization and that too on the fly while you write without even compiling the code. You can try out with more code analyzers available on Nuget. In the next article, I’ll cover new enhanced renaming and refactoring features that Visual Studio 2015 provides.

For more technical articles you can reach out to my personal blog, CodeTeddy.

Node.js application metrics sent directly to any statsd-compliant system. Get N|Solid

Topics:
visual studio ,.net ,c# ,code analyzer

Published at DZone with permission of Akhil Mittal. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}