Introduction
Peer code reviews are a proven way to improve software quality. ReviewMyCode
helps you overcome some barriers to this best practice with a simple Visual Studio 2008 add-in that fits your process. The team members can contribute to the review process without leaving the development environment.
The add-in works well within a team development environment by integrating the review process with the SVN source control management system.
Background
Getting Started with Extending Visual Studio is a good starting point for Visual Studio add-in development.
Using the Code
An add-in must have at least two files, the add-in descriptor XML file and the assembly which implements the actual add-in. The descriptor file describes the add-in assembly and is located in the user's %USERPROFILE%\Documents\Documents\Visual Studio 2008\Addins folder.
A typical add-in descriptor XML file looks like this:
<Extensibility xmlns="http://schemas.microsoft.com/AutomationExtensibility">
<HostApplication>
<Name>Microsoft Visual Studio</Name>
<Version>9.0</Version>
</HostApplication>
<Addin>
<FriendlyName>ReviewMyCode</FriendlyName>
<Description>Review My Code</Description>
<Assembly>ReviewMyCode.dll</Assembly>
<FullClassName>ReviewMyCode.View.Connect</FullClassName>
<LoadBehavior>1</LoadBehavior>
<CommandPreload>0</CommandPreload>
<CommandLineSafe>0</CommandLineSafe>
</Addin>
</Extensibility>
The Extensibility\Addin\Assembly
gives the path to the add-in assembly. With just the file name, Visual Studio will load the add-in assembly from the add-in descriptor folder. If you need to debug the add-in, you need to point it to the debug build of your add-in. Also you need to set up debug properties of the Visual Studio project to start Visual Studio as an external program. Make sure to specify:/resetaddin ReviewMyCode.View.Connect
as the command line arguments.
The entry point of an add-in is the Connect
class. It implements Extensibility.IDTExtensibility2
interface. The OnConnection
method receives notification that the add-in is being loaded and we perform our initialization code here, such as creation of the solution event (Solution Open, Solution Before Closing) delegates. In order to handle solution level events the delegates must be defined in the Connect
class.
The OnStartupComplete
method receives notification that the host application has completed loading, in which we create our tool window (add-in window) and shows it. The add-in window is a UserControl
.
The rest of the classes are just implementing the logic and the UI. Retrieving information about the code being reviewed depends on the selected line. The following code snippet shows the details:
private void ToolStripReviewItemAddNew_Click(object sender, EventArgs e)
{
TextPoint textPoint = null;
TextSelection selection =
Connect.ApplicationObject.ActiveDocument.Selection as TextSelection;
if (selection != null)
{
textPoint = selection.ActivePoint as TextPoint;
if (textPoint != null)
{
this.textBoxLineNumber.Text =
textPoint.Line.ToString(CultureInfo.CurrentCulture);
}
}
CodeElement codeElement = null;
FileCodeModel2 fileCodeModel =
Connect.ApplicationObject.ActiveDocument.ProjectItem.FileCodeModel
as VCFileCodeModel;
if (fileCodeModel == null)
{
fileCodeModel = Connect.ApplicationObject.ActiveDocument.
ProjectItem.FileCodeModel as FileCodeModel2;
}
if (textPoint != null && fileCodeModel != null)
{
vsCMElement[] scopes =
{
vsCMElement.vsCMElementFunction,
vsCMElement.vsCMElementProperty,
vsCMElement.vsCMElementVariable,
vsCMElement.vsCMElementEvent,
vsCMElement.vsCMElementClass,
vsCMElement.vsCMElementInterface,
vsCMElement.vsCMElementStruct,
vsCMElement.vsCMElementEnum,
vsCMElement.vsCMElementDefineStmt,
vsCMElement.vsCMElementImportStmt,
vsCMElement.vsCMElementIncludeStmt,
vsCMElement.vsCMElementModule,
vsCMElement.vsCMElementOther
};
foreach (vsCMElement scope in scopes)
{
try
{
codeElement = fileCodeModel.CodeElementFromPoint(textPoint, scope);
if (codeElement != null)
{
break;
}
}
catch
{
}
}
}
if (codeElement != null)
{
this.textBoxMethodName.Text = codeElement.FullName;
this.textBoxProjectName.Text =
codeElement.ProjectItem.ContainingProject.UniqueName;
this.textBoxFileName.Text = codeElement.ProjectItem.Name;
}
else
{
this.textBoxMethodName.Enabled = true;
this.textBoxProjectName.Enabled = true;
this.textBoxFileName.Enabled = true;
}
this.textBoxCreatedBy.Text = ReviewWindow.TextToTitleCase(Environment.UserName);
this.toolStripReviewItemSave.Enabled = true;
}
Points of Interest
Using the Add-in
- Add-in must be loaded from the Visual Studio IDE. To do this, select Add-in Manager from the Tools menu.
- To initiate a review, click on "Send to Review" button. This will bring up a new mail message window. Fill in the "To" field and send the mail message to the team members.
- Reviewers can add review items by selecting review item tab. To modify an item, click on the item in the review list and then select review item tab.
- A review item can contain comments, such as a rejection comment or comments about the fix.
- Loading a solution from the Visual Studio automatically loads the current review log from SVN. When closing the solution, the updated review log will be saved in the SVN.
Screenshots
The Review List
Adding a Review Comment
Adding a Comment for a Review Comment
History
- Oct 5 2011 - Version 1.0.0.0 - Initial version
- Oct 7 2011 - Added screenshots