NOTE ** This is a repost from my old blog, it may or may not be relevant any more, I'm posting it to keep it alive for people who may have been struggling to find it from other links on the web **

Today I hope to clarify how one might go about implementing a check in policy which ensures that Option Strict is turned on for VB projects.

Rather than rehashing a perfectly good walk through, I suggest you read this article from MSDN to get the basics of Check In Policy creation.

Once we have our check in policy project and have derived a class from Microsoft.TeamFoundation.VersionControl.Client.PolicyBase it is time to start overriding the behaviour of the base rule.

```vb Imports Microsoft.TeamFoundation.VersionControl.Client _ Public Class OptionStrictPolicy Inherits PolicyBase ```

Once we are over that little hurdle we want to:

  • Get the set of pending changes that have been selected by the user to check in
  • For each pending change find the project file that the change belongs to
  • For each VB project decide if Option Strict has been turned on
  • For each project that hasn't got option strict turned on, create a policy warning.

For extra fun I'll do this all with VS2008 & VB9. I love my C# but to be honest VB9 kicks its ass when dealing with XML.

1: Get the set of pending changes that have been selected by the user to check in

Everything from here on out extends the Evaluate method of PolicyBase. Getting the set pending changes selected by the user is a cinch. I've filtered by vb code files, but you could just as easily go for more file types.

[sourcecode language="vb"]

Public Overrides Function Evaluate() As PolicyFailure()

Dim pendingChanges = PendingCheckin.PendingChanges.CheckedPendingChanges
Dim vbCodeFiles = _
From c In pendingChanges _
Let extension = Path.GetExtension(c.FileName) _
Where extension = _VBFileExtension OrElse extension = _VBProjectFileExtension _
Select c.LocalOrServerFolder, c.FileName
[/sourcecode]

2: For each pending change find the project file that the change belongs to

This step is a little trickier and basically involves drilling up the folder structure until we find a project file, and then checking the project file for a compilation reference to the pending change. This seems like a good place to refactor into a recursive function...

*SIDE NOTE* Am thinking of starting a petition to all relevant Dictionary makers to make the word "Refactor" a real word. Whose with me?

I'm sure we are all capable of looking for .vbproj files recursively up the folder chain. However we do need to allow for the possibility that there may be two vbproj files in a folder and if so, is our pending change referenced by either of them? To do this I need to go through the project file looking for tags that include my pending change. For example in C# we might do it like this

[sourcecode language="csharp"]
var doc = XDocument.Load(XmlReader.Create(projectFilename));
var compileItems =
from e in doc.Descendants()
where e.Name.LocalName == "Compile"
select e;
return
(from c in compileItems
where c.Attribute("Include") != null && c.Attribute("Include").Value.Contains(filename)
select c).Any();
[/sourcecode]

But since Im using VB today I can do it like this...

[sourcecode language="vb"]
Dim doc = XDocument.Load(XmlReader.Create(projectFilename))
Return doc...<Compile>.@Include.Contains(filename)
[/sourcecode]

Not bad...but for this to work I do need to import the namespace of the project file schema, since the syntax that allows for <Compile> is checking qualified names, not local names.

[sourcecode language="vb"]
Imports <xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
[/sourcecode]

3: For each VB project decide if Option Strict has been turned on

Once I have a list of projects that are loosely associated with a check in, I can easily check for the existence of OptionStrict tags in the vbproj file. Option Strict still defaults to off, so a lack of OptionStrict tags implies the setting is OFF. However it is perfectly valid to have an OptionStrict tag that is set to OFF so I need to account for those.

[sourcecode language="vb"]
Private Shared Function IsOptionStrictOn(ByVal project As XDocument) As Boolean
Return project...<OptionStrict>.Value = "On"
End Function
[/sourcecode]

4. For each project that hasn't got option strict turned on, create a policy warning.

Creating policy warnings is a breeze and you can return as many as you want, in this scenario I want to make sure that one is created for each project that is in violation of my rule. The Evaluate function looks like this...

[sourcecode language="vb"]
Public Overrides Function Evaluate() As Microsoft.TeamFoundation.VersionControl.Client.PolicyFailure()
Dim pendingChanges = PendingCheckin.PendingChanges.CheckedPendingChanges

Dim vbCodeFiles = _
From c In pendingChanges _
Let extension = Path.GetExtension(c.FileName) _
Where extension = _VBFileExtension OrElse extension = _VBProjectFileExtension _
Select c.LocalOrServerFolder, c.FileName

Dim vbProjects = _
From c In vbCodeFiles _
Select GetProjectFile(c.LocalOrServerFolder, c.FileName)

Dim strictOffprojects = _
From p In vbProjects _
Where Not IsOptionStrictOn(p)

Dim policyFailures = New List(Of PolicyFailure)
Dim messageFormat = "Please turn option strict on in the project file: {0}"

For Each s In strictOffprojects.Distinct
policyFailures.Add(New PolicyFailure(String.Format(CultureInfo.InvariantCulture, messageFormat, s), Me))
Next

Return policyFailures.ToArray()
End Function
[/sourcecode]

So there you have it, VB9 to make coding an Option Strict ON policy nice and easy. Seems appropriate doesn't it?