Archive for the ‘How-To's’ Category

Highlighting Custom Patterns with ReSharper

Thursday, August 19th, 2010

A new feature that has shipped with ReSharper 5 is the Structural Search and Replace. It is a way for us to locate certain patterns in our code, and optionally replace them. However, it is more than just a Find and Replace. It allows us to somehow extend ReSharper’s inspection settings by offering us means to identify patterns and highlight them.

As many of you know, ReSharper offers a series of Suggestions, Hints, Warnings and Errors when it detects certain code patterns. For instance, when explicitly declaring a variable, ReSharper suggests you use var (and with good reason)

image

These are configurable, in that you can tell ReSharper whether you want them to be displayed as hints, suggestions, warnings or errors, which is done via ReSharper | Options | Inspection Severity

image

Setting it to Show as error for instance will display a red (or whatever color you have configured) underlining and the right-hand side border will display the a Red box indicating an error in the file.

SNAGHTML12140a89

If we now combine this with Solution Wide-Analysis, ReSharper will also indicate an error in the solution.

image

 

Extending Inspections

Have you ever encountered the following?

image

This is a perfect candidate for using String.Format. How about this?

image

Did you know StringBuilder has an AppendFormat? You might know that, I might, but maybe other developers don’t. It would be good to provide developers with a hint or suggestion that they could use AppendFormat. Up to version 5 of ReSharper, the inspections were limited to what ReSharper provided out of the box and the only thing we could do to extend this functionality was create/use a plug-in We can now use Structural Search and Replace to accomplish this. Let’s see how it works.

1. Open up a Solution (I’m using BlogEngine.NET but feel free to create your own with some sb.Append calls).

2. Select ReSharper | Tools | Pattern Catalog.

SNAGHTML1228e7ce

By default, the Pattern Catalog is empty.

3. Click on the Add Pattern

SNAGHTML122b7d0a

4. In this first sample, all we want to do is highlight code, so click on the Find button at the top to switch the dialog to Find mode only.

SNAGHTML122d5169

The Search Pattern is what we’ll use to define what we are looking for. The Description is a text which helps us identify the pattern easily in the Catalog. The box on the right is for place holders which we’ll see in a moment.

5. Enter the following pattern in the Search Pattern editor

image

What this does is indicate the pattern we are looking for. The values surrounded with $’s (same notation as that used in Live Templates) represent placeholders. A placeholder can be an expression, statement, type, etc. If it is red, it means it has not yet been defined (next step).

6. Click on the Add Placeholder button on the right box and select Expression, and enter the following values:

SNAGHTML12c3cb9a

We are indicating that the placeholder sb (first one used) is an expression of type System.Text.StringBuilder

7. Click on the Add Placeholder button to define the second placeholder, args. Select Argument and enter the following values:

SNAGHTML12c63dfb

We can optionally indicate whether we want to limit the number of minimum or maximum arguments.

If both placeholders have been defined correctly, the Search pattern box should now look like this:

SNAGHTML12c9a0e2

(we’ve entered a description at the bottom)

8. We need to define the type of severity we want. In this case we want it to be marked as a Suggestion. We do that using the Pattern severity dropdown and then click Save

Our Pattern Catalog should now be updated to reflect this new pattern

SNAGHTML12caa7e4

9. At this stage we can either close the Patterns dialog or Search for a pattern. Let’s see what happens if we click Search now button.

SNAGHTML1376eb2e

A Find Results window is displayed highlighting everywhere where ReSharper can find a pattern match. But what about the Pattern severity? Where does that come into play? Let’s double-click on one of the entries:

image

See the highlighting of the sb.Append call? Set the Pattern Severity to Error and that will display in Red.

image

Turn on Solution-Wide Analysis and that will list as an error!

So as we can see, the Structural Search (we haven’t replaced yet), allows us to monitor for certain code patterns in our projects. Potentially we could use it to detect certain code smells.

Fixing things up

Now that we have certain patterns located, and even highlighted, how do we go about fixing things? As we saw in the previous screenshots, we have a little icon pop up when placing the cursor on the line:

image

This context action however doesn’t offer us anything in order to fix the situation, i.e. there is no QuickFix. The reason is obvious: ReSharper doesn’t know what a fix is. Let’s show it!

1. Open up the Patterns Catalog and Edit the previously created Pattern

2. Click on the Replace button to open up the Replace editor at the bottom

SNAGHTML1384f656

3. Enter the following text in the Replace pattern section

image

4. Provide a description (this is what the hint of the QuickFix will dispaly)

image

5. Click on the Save button

Locate the previous sb.Append call and place the cursor on top of the line. We can now see a QuickFix icon appear (A red bulb in this case since it’s an Error)

image

Alt+Enter and we’re done!

image

 

Global Fix

What we’ve just done is a manual local fix, that is, locate the offending entry and hit Alt+Enter to apply a QuickFix. We can do this at a global scope by using the Pattern Catalog tool window.

1. Undo the prefix fix (so as to have several instances)

2. Open up the Patterns Catalog

3. Select the recently created Pattern and click on Search now. This time, instead of the Find Results dialog, we get a Replace dialog which displays all matching patterns and a Replace button

SNAGHTML138b5c29 

4. We can select the entries we want replacing (by default all checked). Click Replace

We’re done! ReSharper will now replace all occurrences. So we’ve applied a QuickFix globally.

 

There’s more

What we’ve seen here is just a simple example of how to improve on a call to a class. We can of course do more complex searches, allowing us to identify code smells, etc. The pattern we created in this tutorial is actually included in a Patterns catalog you can download from the documentation section of our web site (or click here for direct link). All you need to do is unzip it and import the XML from the Patterns Catalog window (Import button). Currently, Pattern Catalogs are PER solution.

There’s much more planned for Structural Search and Replace in vNext and we are always happy to receive feedback, so please try it out, and let us know what you think.

Losing templates on ReSharper upgrade

Monday, August 16th, 2010

Derick Bailey pointed out today on Twitter that during an upgrade, he lost his ReSharper templates.

image

 

ReSharper should import the existing templates during an upgrade. However, for some odd reason, sometimes this does not occur. We managed to sort out Derick’s issue relatively quickly, but in case others might run into the same problem, here’s how to solve it:

Scenario: Upgrading from 5.0 to 5.1 in VS2010 and settings lost.

1. Close down Visual Studio 2010.

2. Go to the %AppData%\JetBrains\ReSharper folder. In there you should find subfolders for each version of ReSharper. Select v5.0.

 image

Inside each folder there are subfolders corresponding to the different versions of Visual Studio you have installed on your machine. Select vs10.0 (corresponds to VS 2010).

image

3. Select the files UserSettings.xml and Workspace.xml.

4. Copy the selected files to %AppData%\JetBrains\ReSharper\v5.1\vs10.0

5. Re-start Visual Studio

 

If all goes well, you should now have your settings correctly imported. If you have run into this problem, please feel free to contact me. We need information on setups to try and see what the common denominator is for when this fails (also please store the contents of these folders since it might help us figure out what’s wrong).

Templates Galore: Live Templates

Friday, August 6th, 2010

A couple of months ago I was doing a talk at DevSum, Stockholm. It was a room full of developers, 90% of whom had heard of ReSharper and 80% of them used it. What surprised me however was that only a couple of folks knew about Live Templates, which left me wondering how many outside of the that group actually knew about them too. Thus, in an attempt to expand the reach, we’ll take a look at what Live Templates and in future posts look at Surround and File Templates

Snippets on Speed

Live Templates enhances the Visual Studio Code Snippets by providing more functionality and easier management. To open up the Live Templates manager, we click on the ReSharper menu and select Live Templates:

SNAGHTMLa24f3d5 

ReSharper has four groups of templates:

  • Predefined: Predefined by ReSharper
  • User Templates: Templates defined by the user
  • Personal Solution Templates: Templates that are specific to a solution
  • Shared Solution Templates: Templates that are specific to a solution and can be shared with others

Each group consists of various categories based on the type of project/files we are working on. Many of these also import the default Snippets that are available in Visual Studio. From this screen there are various operations we can perform such as adding, removing, editing templates, as well as importing and them. Editing and Creating Templates is where some of the juice is, so let’s see how we can create a new template.

Creating Templates

Templates consists of literal strings and variables. The idea is to combine these to maximize efficiency when typing. They can be used for a variety of things, from creating classes, DTO’s or skeletons for unit tests, among others. Let’s say we like to create entities that usually have an Id field prefixed (this is not personal!) with the name of the class, along with some other properties. The type of my Id is not necessarily known beforehand. It can be of type string, GUID, etc. Here’s a sample:

public class Customer
{
    public string CustomerId { get; private set; }
    public string Name { get; private set; }
    public string Email { get; private set; }
}

Let’s see the step-by-step process to create a template for this:

1. Open up the Live Template Editor and select User Templates

2. Click New Template to add a new template

image

3. This opens up the editor where we can type our text (literal strings and variables).

image

4. We need to provide a shortcut for our template, which will be used to invoke it (we’ll see how later). Type “be” in the Shortcut field. In the Description type “Business Entity”

5. Type the following in the text area (black in the figure above)

image

The different colors have meanings (these Colors can be configured under Tools | Options | Fonts and Color. Look for “ReSharper Live xxxxx” entries). There are 3 types of elements in the text:

  • text literal
  • template keyword
  • variables

The text literal is everything that is in white text, such as “public class” and “{ get; private set;}”. Anything literal will appear as is when we invoke the template. The second type of element is the $END$ keyword. This is used to tell ReSharper where we want the cursor to be positioned once we have finished invoking and interacting with the template. Finally we have the variables. These are elements that can be used to interact with the template. A variable is designated using the $ prefix and suffix. That is, anytime we type a word prefixed and suffixed with a $ sign, ReSharper will automatically convert it to a variable. The effect that this has is that when we invoke the template, we can iterate through the different variables to type a value. In our case, since we want to establish the classname during its invocation, we make the $className$ a variable. The same occurs with $idType$, since we don’t know what type we want the Id to be (this is for demonstration purposes, normally most entities have the same type for their Id). Finally comes the Id property. We said we want this to resemble the classname suffixed with Id. As such we just suffix it with the word Id.

6. Close the Editor.

7. Open up an existing file and locate an empty are where we can create a new class. Now type “b” and we should get Intellisense for all templates that start with “b”. Locate “be” and hit TAB (or ENTER)

image

ending up with:

image

ReSharper has generated the core code of the template and is now ready for our input. The cursor is currently positioned at className, where can type in the class name. Notice that as we type, the value of the property name is automatically updated, as expected. Once we finish typing className we hit TAB (or ENTER) and ReSharper positions us at the IdType entry where we can type in the type of the property (with the corresponding IntelliseSense).

8. Once the process is complete, we should end up with the following class (for the value “Customer”):

image

Classifying the Template

Currently the newly created template has been classified under “No Languages”. The main issue with this is that this template will be available pretty much everywhere, even places where it wouldn’t make sense to create a new class.

image

Let’s proceed in limiting it in scope and defining a category:

1. Select ReSharper | Live Templates and Click on Edit on the newly created template

2. Select the link at the top of the editor next to the “Available” text

image

The Template Availability dialog box will appear

SNAGHTMLb3ffe17

3. Select the Language-Specific option and choose C# from the dropdown list. The dialog box should now change to show language specific options:

SNAGHTMLb40cf5a

4. We can now choose the minimum version of the compiler for which this template is available (for example if it contains lambda expressions, we cannot use it versions below 3) and also choose where we want the declaration to be available. In our case we can choose Everywhere.

5. Last thing left to do is define a New Category for this template. We can do this by selecting it in the Live Templates tree, right-clicking and selecting New Category. In our case we would type C#

With this change we restrict where this template will be available and have a better classification when viewing templates.

Extending Functionality with Macros

We saw that when multiple instances of a variable appear in the template definition, as one changes, others will update to reflect that change. However, sometimes we might want a slight variation of a specific variable. Say for instance, we are create a template to define a property with a backing field (this template already exists by the way). In this scenario, usually the backing field name is the same as that of the property name with a lowerCamelCase. Let’s see how we can define a template like this using the Macros in the Live Editor Template:

1. Create a new template following the steps outlined previously, ending up with the following definition:

image 

If we were to use this template as is, ReSharper would prompt us to enter a value for $className$, $IdType$ and $backingField$. Ideally what we would like is to have the latter to be a variation of the $className$, concretely, a lowercase version.

2. On the right side of the template editor, there is a Window that displays Macros that we can apply to variables. There is one for each variable. Click on the backingField entry and select the Choose Macro link

image 

A dialog box appears giving us a series of operations we can perform on the variable, from suggestions, conversions, metadata, etc. In our case we need to scroll right to the end and select “Value of another variable with the first character in lower case”:

SNAGHTMLc8bc8fb

3. Once we click OK, the Macro window will then be updated to reflect the change and allow us to define the value of the variable. Click “another variable” link and select one className.

image

4. Save the template.

5. Invoke the template by typing “be” as before. We should end up with:

image

We can now type the className. As we do, we see that the backing field will automatically update to reflect the changes.

image

This is just a simple case of applying a Macro. We can have multiple Macros in the same template and combine them to achieve powerful templates.

Additional Template Options

At the top of the template editor, there are two additional check boxes:

image

The first one is used to indicate whether we want the template to be reformatted according to the defined styles we have set up in ReSharper once completed. The second option is useful when we are referencing namespaces that are not in the using directives. Let’s imagine for instance that we generate a template to spit out some Unit Test fixtures for NUnit. If we were to decorate the class with a [TestCase] attribute in a blank file, ReSharper would indicate an error saying the the namespace is not imported. The way to solve this issue is to fully qualify the attribute when defining the template and select this checkbox. ReSharper will then make sure it imports the correct namespaces and shorten the attribute.

image

 

Sharing Templates

Any template created under the User Templates is visible to the current Windows user for any solution. If we want to have templates specific to a particular solution, we would need to create them under the Personal Solution Templates. These however again are restricted to the current user. If we want them shared across multiple users we need to place them under Shared Solution Templates.

When it comes to sharing templates across machines with team members, the cumbersome way would be to export templates and have each team member import it. The preferable way is to place these templates under network drive and then mount them using the Mount File Storage

image 

By doing this, ReSharper is aware that these templates are shared across machines and makes sure they are updated accordingly.

Summary

Live Templates in ReSharper offer us a lot of opportunities to be more effective when writing code. It is not about code generation but about not wasting time having to type repetitive things. It is also important to understand that they should not replace good programming practices. For example, using templates to write out repetitive code for logging is not the best way to approach the problem. A better solution would be to use Aspect Orientated Programming. However, there are many case where templates are very efficient. In future blog posts we’ll examine the Surround and File templates that ReSharper also offers us.

Advanced scenarios with dotCover Console Runner

Thursday, August 5th, 2010

In an earlier post, we saw how to use dotCover in simple scenarios, whereby we have a single unit test project for which we want to obtain coverage reports on. There are times however, when this is not the case; that is, we might have multiple tests projects. It is very common (and recommended practice) to separate Unit test projects from Integration test projects, allowing us to run the former more frequently during development and the latter during an Automated Continuous Integration setup. In these cases, running the dotCover analyse command, as shown in the previous post might not be ideal.

Fine tuning the coverage steps

For the scenarios described, whereas we have multiple test projects, dotCover allows us to fine-tune the coverage process by offering us a series of commands that breakdown the coverage, merging and reporting into individual steps. Suppose we have the following Project Layout

image

The AppCode is our application code that we want to run coverage for, and TestProject1 and TestProject2 are specific the test projects that cover AppCode. These can be Unit Test or Integration Test projects. The process we need to follow is shown in the figure below:

image

We run coverage on each of the tests projects by using the cover (c) command using the following configuration file (corresponds to testProject1.xml. testProject2.xml is similar)

<?xml version=”1.0” encoding=”utf-8“?>
<CoverageParams>
<Executable>
X:\Libraries\nUnit\nunit-console.exe
</Executable>
<Arguments>TestProject1.dll</Arguments>
<WorkingDir>TestProject1\bin\debug</WorkingDir>
<Output>output1.xml</Output>
<Filters>
<IncludeFilters>
<FilterEntry>
<ModuleMask>AppCode</ModuleMask>
<ClassMask>*</ClassMask>
<FunctionMask>*</FunctionMask>
</FilterEntry>
</IncludeFilters>
<ExcludeFilters>
</ExcludeFilters>
</Filters>
</CoverageParams>

[Command to execute: dotcover c testProject1.xml]

Executing this command generates a snapshot file with coverage data, the Coverage Results Descriptor (by default, unless specified in the configuration file using the TempDir element, the snapshots are saved in the User temporary folder). These snapshots are not the final XML report that we are after but intermediate information that dotCover uses to generate reports from. There is a correspondence between snapshots and processes, such that each process generates a single snapshot. In our case, since we are calling a unit testing framework to launch a single test project, there will only be one snapshot. However there are cases, for instance when running coverage report on an application, whereby the application can launch another process  itself. In this case, multiple snapshots will be generated.

When we run this command, once for each Project, we end up with two snapshot files. We now need to merge the snapshots in order to generate the XML report. This is accomplished using the merge (m) command

<?xml version=”1.0” encoding=”utf-8“?>
<MergeParams>
<Source>
<string>output1.xml</string>
<string>output2.xml</string>
</Source>
<Output>output_merged.xml</Output>
</MergeParams>

[Command to execute: dotcover m merge.xml]

which takes the output of the two cover commands (output1.xml and output2.xml) and generates a single snapshot file. The only thing remaining is to generate an XML coverage report based off of this data, using the report command

<?xml version=”1.0” encoding=”utf-8“?>
<ReportParams>
<Source>output_merged.xml</Source>
<Output>results_merged.xml</Output>
</ReportParams>

[Command to execute: dotcover r report.xml]

providing us with the XML report containing coverage information (percentage of code covered, statements covered), which like in the previous post we can apply an XSLT to format into HTML or JSON.

Other Coverage Commands

dotCover provides two more commands:

  • list
  • delete

The list command simply obtains a list of all snapshot files given the coverage descriptors, that is, the output of the different cover commands. The configuration file lists these descriptors:

<?xml version=”1.0” encoding=”utf-8“?>
<ListParams>
<Source><!– Required. At least one child element expected. –>
<string><!– Coverage results descriptor 1 file name –></string>
<string><!– Coverage results descriptor 2 file name –></string>
<string><!– Coverage results descriptor N file name –></string>
</Source>
<Output><!– Required. Resulting file name. Stores plain list of all snapshot files. –></Output>
</ListParams>

The delete command deletes the list of given snapshots:

<?xml version=”1.0” encoding=”utf-8“?>
<DeleteParams>
<Source><!– Required. At least one child element expected. –>
<string><!– Coverage results descriptor 1 file name –></string>
<string><!– Coverage results descriptor 2 file name –></string>
<string><!– Coverage results descriptor N file name –></string>
</Source>
</DeleteParams>

Summary

As we can see, dotCover allows us to fine-tune the coverage process by letting us control the different steps. One question that might arise is why couldn’t we have done the same by running the analyse command twice, once for each Test Project. If we were to do that, we would get two independent reports, whereas here the results are all merged into a single report. The analyse command is a great fit for simple scenarios that only have a single project. Once we move onto more complex setups, having a finer control over the coverage process has its benefits.

Running Code Coverage from the Console with dotCover

Wednesday, July 28th, 2010

As of the beta* of dotCover, we included a Console runner to run coverage using the command line, allowing for instance, setup of dotCover in a Continuous Integration environment. Let’s see how it works.

*To get all these features in this post, you need to download the latest nightly build

 

Console Runner

The Console runner is located under the installation folder (%Program Files%\JetBrains\dotCover\v1.0\bin\dotCover.exe). The best option is to add it to the system path so as to be able to run it from anywhere. The runner accepts several commands based on the operation we want to perform. Each of these commands in turn takes one parameter, which is an XML configuration file. The commands are:

  • cover: Coverage of specified application
  • merge: Merges snapshots
  • report: Creates an XML report of the coverage results
  • list: Lists snapshots
  • delete: Deletes snapshots
  • analyse: Provides an all-in-one analysis and output

We can also obtain a list of commands by typing dotCover.exe help on the command line:

image

As shown in the figure above, we can find out more about each command by typing help followed by the command. All commands (including help) have corresponding shortcuts. For instance, to get information about analyse, we can type:

dotCover.exe help analyse

or

dotCover.exe h a

Since all commands take as parameter an XML file, when requesting help, all they do is generate a sample XML with comments indicating what each element means. The previous command would therefore output:

image

The obvious advantage to this is that we can easily get a new configuration file setup by just asking for help and piping the output to some file. In fact, adding a third filename parameter, dotCover will do this for us, without us having to touch up the output (remove headers, etc.).

Coverage in one command

The dotCover console runner is flexible in that it complies with most common requirements in a Continuous Integration setup. Normally in projects, we have multiple test projects we need to cover. We might then want to see the results separately or merge them as one report. dotCover allows for this kind of flexibility. However, in many cases, all we want to do is run coverage on a single test project and see the results. We’ll see how to do that in a single step in this blog post and in a future post we’ll get into the details or merging, listing, etc.

Let’s see how to do this step by step. I’ll be using a sample app that I’ve prepared for this blog post (using MSpec). You can adjust the parameters to your own project paths and unit testing framework as required.

 

  1. Type dotcover help analyse coverage.xml on the command line. I’m doing this in the root folder of my solution.

    image

  2. Add coverage.xml to the Solution and open it up in Visual Studio
  3. Eliminate all elements except the following

     image

  4. Fill in the elements with the corresponding values:

    Executable: Is the path to the unit testing framework runner (in this case mspec.exe)
    Arguments: Arguments passed to the runner, the test assemblies (specs.dll)
    WorkingDir: Optional path to the working folder (provide this to not have to fully qualify test assemblies)
    Output: XML Report containing coverage information. Relative to the coverage.xml path (output.xml)

     image

  5. That’s it in terms of configuration. Now all we need to do is run it by typing dotCover analyse coverage.xml. If all is configured correctly, we should see the following output:

    image

    and there should be an output.xml file located in the same folder. Opening it up we can see the coverage results

    image

 

Filtering from the Console

Looking at the results, we can see that there is a lot of noise, that is, assemblies that we’re not interested in such as the tests, MSpec assemblies, etc. In a previous blog post, we saw how to filter these out using dotCover GUI. Let’s see how we can do this via the command line. If we generate the default coverage configuration, we can see that there is a filter section:

image

These are used to filter assemblies. We can indicate which assemblies we want covered and which we don’t. In order to filter out all assemblies and concentrate only on our actual code (ClassLib), we can do one of two things:

  1. Filter out all non-required assemblies individually by adding them to the ExcludeFilters section, as in:

     image

  2. Exclude everything that’s not specifically in the Include section. This is done by leaving an ExcludeFilter section blank and placing what we want covered in the IncludeFilter:

    image

Based on the needs and depending on which of the two lists (Include or Exclude) are smaller, we can opt for option 1 or 2. The ouput should now be filtered:

image

 

Giving it some style

Only thing left to do is to format the output so that it can be viewed nicely inside a browser. This can be done easily using XSLT and some appropriate design skills (something I lack).

image 

Included in the project you have an XSLT to create some HTML as well as one to covert the XML to JSON. Having JSON output allows us to combine it with something like jQuery to display a nice treeview or grid with the results.

Writing plug-ins for ReSharper: Part 2 of N

Tuesday, July 20th, 2010

Finally I’ve managed to get the second part of the post on plug-ins. Sorry for the delay to everyone that was waiting. Appreciate your patience.  And now we’ll resume my holidays!

In the previous part of this series, we saw the basics of how to create a plug-in for ReSharper, install it and run it. We created a context action that would allow us to mark a public method as virtual (where applicable). However, this was done as an explicit action by the user, as such, you didn’t get any kind of hint or suggestion to do this. What we want to do now is make this a hint, so that highlighting appears under methods that could be made virtual. In this part we are going to expand on the same plug-in and convert it into a QuickFix.

What is a QuickFix?

Have you seen the little squiggly lines that appear in Visual Studio?

image

They usually indicate a Suggestion (field can be made read-only), Warning (possible null reference) or Error. ReSharper analyzes and can detect potential issues in the code (similar to what static checker of Code Contracts does). These are known as Highlights and they are related to QuickFixes in that usually a highlight has an QuickFix associated to it, which invokes a context action. This is usually done by placing the cursor on top of the highlighting and press Alt+Enter

image

 

Highlighting Daemons

In the gutter of the Visual Studio editor (right-side), ReSharper displays a series of warnings, errors and hints, which indicate potential issues on a specific file. These issues are detected by background processes known as Daemons. Since what we are looking for is for ReSharper to warn us of existing methods that could be made virtual, what we need to do is somehow hook into these daemons.

image

 

Step by Step Guide

The Daemons in ReSharper use the Visitor pattern to use act on elements, be it code, files, etc. The first step is to implement an IDaemonStage interface, which hold metadata about our daemon stage at at the same time acts as a factory for the actual process we are implementing.

[DaemonStage(StagesBefore = new[]  { typeof(LanguageSpecificDaemonStage) })]
 public class MakeMethodVirtualDaemonStage: IDaemonStage
 {
     public IDaemonStageProcess CreateProcess(IDaemonProcess process, DaemonProcessKind processKind)
     {
         return new MakeMethodVirtualDaemonStageProcess(process);
     }

     public ErrorStripeRequest NeedsErrorStripe(IProjectFile projectFile)
     {
         return ErrorStripeRequest.STRIPE_AND_ERRORS;
     }
 }

There are two main methods to implement. The CreateProcess is what creates the actual process for us and the NeedsErrorStrip which indicates whether this daemon uses the gutter to display strips. The DaemonProcessKind parameter passed into the first method helps us discriminate on when this process should be executed, i.e. only during checking of visible (current) document, during solution wide analysis, etc.

The next step is to implement the process via the IDaemonStageProcess interface:

  public class MakeMethodVirtualDaemonStageProcess : IDaemonStageProcess
  {
      readonly IDaemonProcess _process;

      public MakeMethodVirtualDaemonStageProcess(IDaemonProcess process)
      {
          _process = process;
          
      }

      public void Execute(Action<DaemonStageResult> commiter)
      {
          if (_process.InterruptFlag)
          {
              return;
          }

          var file = _process.ProjectFile.GetPsiFile(CSharpLanguageService.CSHARP) as ICSharpFile;

          if (file != null)
          {
              var highlights = new List<HighlightingInfo>();

              var processor = new RecursiveElementProcessor<IMethodDeclaration>(declaration =>
              {

                  var accessRights = declaration.GetAccessRights();

                  if (accessRights == AccessRights.PUBLIC && !declaration.IsStatic && !declaration.IsVirtual &&
                      !declaration.IsOverride)
                  {
                      var docRange = declaration.GetNameDocumentRange();

                      highlights.Add(new HighlightingInfo(docRange, new MakeMethodVirtualSuggestion(declaration)));
                  }
              });

              file.ProcessDescendants(processor);
              
              commiter(new DaemonStageResult(highlights));
          }

      }

      
  }

The main meat of this class is in the Execute method. We first check to make sure that we’ve not received an interruption (Interrupt Flag raised) due to some external action. Next step is to get access to the current file (remember that we are visiting the entire visible document, not just a specific method). Having the file, we can now create a RecusiveElementProcessor* to perform a tree walk of the AST and perform the specific action on each element. The action to perform is declared as the lambda expression. Since we’re interested in the method declaration, the type is IMethodDeclaration (there are many others). If we look at the expression, we can see that it’s pretty much the same as that of Part 1, the only difference is that we add the results to the highlighting variable.

The HighlightingInfo class has a parameter which can be a Suggestion, Warning or Error, as explained previously. Since in our case we need a suggestion, we pass in the MakeMethodVirtualSuggestion:

[StaticSeverityHighlighting(Severity.SUGGESTION)]
 public class MakeMethodVirtualSuggestion : CSharpHighlightingBase, IHighlighting
 {
     public ICSharpTypeMemberDeclaration Declaration { get; private set; }

     public MakeMethodVirtualSuggestion(ICSharpTypeMemberDeclaration memberDeclaration)
     {
         Declaration = memberDeclaration;
     }

     public string ToolTip
     {
         get { return "Method could be marked as virtual"; }
     }

     public string ErrorStripeToolTip
     {
         get { return ToolTip; }

     }

     public override bool IsValid()
     {
         return Declaration.IsValid();
     }

     public int NavigationOffsetPatch
     {
         get { return 0; }
     }
 }

This class is pretty simple. The main property to define is the ToolTip, which is the text that will show when we hover of the highlighting. The ErrorStripeToolTip is what’s displayed in the right-hand side gutter. Finally the Attribute StaticSeverityHighlighting is to indicate what type of tip it is (Warning, Error, etc.).

 

[*Note: In this case, the operation we want to perform is very simple. If we want a more complex scenario where we need to do some processing before and after each element is visited or have a more fine-grained control, we can implement the IRecurisveElementProcessor. I’ll cover this in another post]. 

 

To recap, right now we would have everything place to display highlighting when a method that could be made virtual is encountered. The only remaining part is to now be able to apply a QuickFix. This is in many ways similar to the ContextAction we saw in Part 1:

[QuickFix]
public class MakeMethodVirtualQuickFix : BulbItemImpl, IQuickFix
{
    readonly MakeMethodVirtualSuggestion _highlighter;

    // Takes as parameter the Highlighter the quickfix refers to
    public MakeMethodVirtualQuickFix(MakeMethodVirtualSuggestion highlighter)
    {
        _highlighter = highlighter;
    }

    // In the transaction we make the necessary changes to the code
    protected override Action<ITextControl> ExecuteTransaction(ISolution solution, IProgressIndicator progress)
    {
        _highlighter.Declaration.SetVirtual(true);

        return null;
    }

    // Text that appears in the context menu
    public override string Text
    {
        get { return "Make Method Virtual"; }
    }

    // Indicates when the option is available
    public bool IsAvailable(IUserDataHolder cache)
    {
        return _highlighter.IsValid();
    }
}

The MakeMethodVirtualQuickFix needs to implement the IBulbItem and IQuickFix interfaces. For ease of implementation we can inherit from BulbItemImpl. The constructor should take as parameter always the actual highlighting that has given way to invoking the QuickFix, in our case the MakeMethodVirtualSuggestion. Similar to the ContextAction we implemented in Part 1, the actual fix itself is pretty trivial. All we need to do is make the method virtual. How do we get access to the method? The easiest way is via the Declaration property of the highlighting passed in (this is a property we added before). The only thing left is to call the SetVirtual method on it. Since we are in the ExecuteTransaction method, ReSharper makes sure that any change made is executed as a whole.

The rest of the properties are trivial. Text returns the text of the QuickFix (what appears in the menu), and IsAvailable indicates when the QuickFix is available, which in our case is whenever the highlighting is valid.

 

The End Result

Once we compile the plug-in and place it in the corresponding Plugins folder under ReSharper\Bin, we’re done. Here’s the end result:

image

and invoking Alt+Enter on the highlighting gives us:

 

image

 

Summary

Extending ReSharper to create highlightings and quick fixes is pretty simple once you understand how all the pieces fall into place. Most of the code will usually be the same and what will vary will be the actual element processing to be performed and the corresponding QuickFix. As mentioned previously (in the Note), for complex scenarios, we can have more control over the tree walk and that’s something we’ll examine in a future post.

I’ve placed the code up on my github account so feel free to download it, play with it and ping me if you have any comments or questions. The code is updated to work with ReSharper 5.1

[Thanks to Howard for his valuable input]

Screencast: Overview of dotCover

Tuesday, July 13th, 2010

In this short screencast you can see the basics of dotCover and how to get up and running in a matter of minutes.

 

Filtering with dotCover

Thursday, July 8th, 2010

dotCover allows us to run coverage analysis on our code. However, there are times when we do not want to perform an analysis on certain areas. This could be our test assemblies, certain third-party assemblies or even specific parts of our own project. Since the analysis has an impact on the overall statistics and potentially can take longer, it is often interesting for us to filter certain assemblies or classes out.

The figure below shows the coverage report of the default MVC project (yes, yet another MVC example, but it ships in the box and probably the ONLY template with VS that comes with tests). In this case we’re using xUnit for tests, which is mostly to demonstrate that dotCover works with other frameworks, not only MSTest (personally I’ve moved on to MSpec, which dotCover also supports).

SNAGHTMLfe87ba

If we focus on the Coverage results we can see that there are some areas in grey, which indicate that the corresponding PDB files were missing so coverage could not take place. We can also see other assemblies that have been included in the results yet might not be of interest, such as the test assemblies.

image 

In order to filter these out, we can use the Coverage Filters, which can be accessed via the dotCover menu in the IDE

SNAGHTML105d878

By default, everything is set to be covered, as shown by the Everything entry in the Allow Filters tab (which most likely will be renamed to Included). Examining this entry (clicking on Edit) we can see that it is composed of three values:

SNAGHTML107f54b

  • Module Mask indicates the project name
  • Class Mask indicates the class name
  • Function Mask indicates the method name

(All entries support wildcards as displayed by the * that appears)

We can now uses these patterns to exclude projects, assemblies, namespaces, classes and methods from out tests.

Excluding entire project

Click on Deny Filters tab (most likely will be renamed to Excluded) and click on Add, entering the following information:

SNAGHTML10eb8b9

Clicking OK  and re-running the tests, we now see that the entire test assembly has been excluded

Excluding an entire Namespace

We can exclude entire namespaces by setting it in the Class Mask as shown below:

SNAGHTML11da114

this will exclude all the classes inside the MvcApplication16.Models namespace. If we just wanted a specific class, we add it after Models instead of *.

Excluding a method

We can exclude a method, similar to how we’ve done it with the previous cases:

SNAGHTML12173ed

 

Adding a series of filters for test and auxiliary assemblies using the previous steps, we can end up with a cleaner and more accurate coverage report:

SNAGHTML1242f6e

produced by adding the following filters:

SNAGHTML1252438

Notice that by using the *.Tests (or alternatively as I call it *.Specifications), we can automatically exclude all our test projects from code coverage.

 

Beta Disclosure

Note 1: Currently these settings are Global, that is, they apply to all projects. Most likely we’ll be changing it so that they are Solution and Global scoped. This way, common libraries can be excluded for all solutions, and specific projects and/or namespaces can be solution based.

Note 2: We’re also looking at adding functionality to make it easier to define these exclusions (a la Right-Click on Folder, add to Excluded list)

As always, we’re still in beta and feedback is more than welcome!

Show Covering Tests with dotCover

Tuesday, July 6th, 2010

One of the new features dotCover has added is the ability to find tests that cover a certain piece of code. Something remotely similar has been available in ReSharper, although it has been kind of an archaic solution (i.e. Find Usages on Method calls, locate Test assemblies in Result window).

dotCover makes this easier by providing quick access to this information and extends it in functionality.

Below we can see some tests from an MVC application. Let’s run Code Coverage on it using dotCover first.

image

Now let’s switch over to the Source Code and select some random source code, in this case the MembershipService.ChangePassword line in the ChangePassword action:

image

In order to see the tests that cover this line of code, we can either press the default key combination of Ctrl+Alt+K or select the option Show Covering Tests from the dotCover:

image

dotCover will then display a small window showing all the different tests that cover that line of code.

image

At this point, we can run the selected tests or add them to the existing ReSharper Test Runner session. This allows us to easily jump from specific sections of code to the corresponding tests and execute them instantly.

One minor note: The default key mapping conflicts with KeePass, but you can easily re-assign it via Visual Studio Tools | Options | Keyboard, or do as I did and change KeePass to Ctrl+Alt+P (P as in Password…makes more sense).

SNAGHTML5841541

A Quick Update on Issues and Workarounds

Tuesday, June 29th, 2010

Users keep coming with questions whether a particular issue that they encounter in Visual Studio is related to ReSharper. Well, some of them are, some of them aren’t. Either way, we try our best to provide info on workarounds for common issues, both our own and external, in this blog post. Check it out for latest updates on GetTempFileName()-related exceptions in certain versions of Windows, and “insufficient memory” messages caused by simple cut-and-paste operations in Visual Studio — both issues fortunately not in any way related to ReSharper.

As to ReSharper’s own issues, we keep fixing them in 5.1 Nightly Builds, hoping to provide the official 5.1 bug fix update really soon. If you happen to find stop-shipping bugs in the nightly builds, hurry up to report them!