Advanced Code Diff from within Visual Studio

This document explains how to use the NDepend build comparison features, in the context of the interactive UI.
The document Reporting Code Diff explains how to use the NDepend build comparison features, in the context of reporting.

Focusing on code changes since a baseline from Visual Studio (4 minutes)


Code evolution and code maintenance are some of the most prominent characteristics of software engineering. Visual Studio doesn’t deal directly with code evolution. To explore code changes one needs to plug a Source Control Manager (like TFS) to Visual Studio. Source Control Manager can tell that a source file has been changed and it can trace text change history. But there is an impedance mismatch : Source Control Manager deals with text files while Visual Studio deals with code. Source Control Manager won’t make subtle difference between comments change, code in method refactored, type added, method visibility change or field removed.

NDepend comes with some advanced code evolution and code diff features since mid 2007. One of the coolest results of NDepend integrated in Visual Studio, is that now, developers benefit from several fine-grained code diff features, one click away from their natural developing environment. Let‘s expose 3 typical code diff scenarios.

▲▲ Go to Top ▲▲

Code Diff from within Code Source

Since NDepend recognizes the code element currently edited in source, the user can, for instance, right click a method and see if it has been changed. If the method code has indeed been changed, several options appear on the right click NDepend menu. One of the option is Compare Older and Newer version of source file, which leads to opening a diff textual application to see changes

In the screenshot below, we plugged the VS2013 code diff feature to the NDepend > Options > Source File Compare Tool. This diff tool is opened from clicking Compare Older and newer version of source file on the NUnit v2.5.3 vs. v2.5.8 type RuntimeFramework.

Notice that from NDepend > Options > Source File Compare Tool pretty much any diff tools can be plugged to NDepend, and the most popular ones are already referenced.

Look back in the first screenshot above, and you’ll see several other interesting options, including Open my declaration in older source code and Compare older and newer version disassembled with Reflector. With this last option (with Reflector) the language used for disassembling can be chosen (choosing IL is especially interesting). Also, comparing disassembled version can work, even from just 2 different versions of an assembly, the source code is not required.

Note that not only method changes are taken account but namespace, type and field changes as well. For example, one can right click a namespace source code declaration and ask for types or methods of the namespace that have been refactored or added.

At this point you might wonder how NDepend/Visual Studio knows about the previous version of the code to compare against to (what is called the Baseline for Comparison). This concept is explained later in this article, let’s jump to the second VS code diff scenario.

▲▲ Go to Top ▲▲

Code Diff from within Solution Exlorer or Solution Navigator

As we just saw, there is an NDepend menu in source code right-click menu, but there is also an NDepend menu in Solution Explorer (and in Solution Navigator) right-click menu. So for example one can right-click a project in the Solution Explorer and ask for Select Methods (of the project) where Code was Changed.

This will result in a CQLinq query generated that Select Methods (of the project) where Code was Changed. Naturally, for each method listed, one can jump straight to source code declaration or ask for diff.

One interesting point, is that NDepend comes with a heuristic to infer namespace from Solution Explorer folders. Indeed, it is a popular good practice to organize source code in a folders hierarchy that mirrors the namespace hierarchy. So right-clicking a folder can result in asking for code changes in a namespace, a narrower scope than project.

▲▲ Go to Top ▲▲

Code Change Review through Global Code Diff

The third scenario to expose, is Global Code Diff. NDepend has its own global Visual Studio menu that comes with a sub-menu Diff.

This sub-menu Diff provides several options, including Review Diff. This option opens the NDepend Search panel with the option Search Change. The Search Change Panel is actually a CQLinq query generator related to Code change. For example, in the screenshot below, we can see that asking for Method + Change + Code was Changed or was Added generates the CQLinq query:
from m in Application.Methods 
where m.CodeWasChanged() 
let newLoc = m.NbLinesOfCode
let oldLoc = m.OlderVersion().NbLinesOfCode
select new { m, 
delta = newLoc >= oldLoc ? newLoc - oldLoc : -(oldLoc - newLoc)

The result shown is ideal to do efficient Code Diff Review: not only all code changes are nicely organized at a glance, but for each methods refactored, the developer is just one click away to observe diff in source files.

The Search Change Panel’s options offers various possibilities to explore diff, including searching for code elements where code and only code (not comment) was changed or where comment and only comment was changed, where visibility was changed, where methods or classes were added or removed etc….

A bonus option is to search diff in third(party code, like asking for which library types is not used anymore for example.

Typically, developers like to write tests for testing automatically refactored and new code. Another useful option is to search for diff coupled with code coverage by tests ratio, like asking for methods where code was changed (i.e refactored methods) and where it is not actually properly covered by tests. Reviewing how diff are covered by tests is made easy thanks to the search facility: Search by Coverage of Changes

▲▲ Go to Top ▲▲

Defining the Baseline for Comparison

Earlier in the post we introduced the concept of Baseline for Comparison. This represents the previous snapshot version of the code base against which the comparison is done. Typically, the Baseline for Comparison represents the latest version of the code in production.

The Baseline for Comparison can be specified through the menu: Visual Studio > NDepend > Diff > Define the Two Snapshots to Diff > Define a Baseline for Comparison. The dialog below appears and lets us choose different options to define the baseline. The Baseline for Comparison option is then persisted in the NDepend project file.

To harness all the diff capabilities we presented, it is important that the Baseline for Comparison points to a previous analysis result with .NET assemblies, PDB files and source code, all available somewhere on the local machine. If PDB files point to a different root folders (typically because .NET assemblies have been created on a different machine) NDepend comes with a source file rebasing option. If older version of source files is not available, it is still possible to query for what was changed, but of course, this won’t be possible to compare the missing older version of source files with the newer version. However, the option Compare older and newer version disassembled with Reflector will still be available as long as the older version of the .NET assemblies is available (no matter if PDB files and source files are absent).

Enjoy live code diffing in Visual Studio!

▲▲ Go to Top ▲▲