29 January 2009

format all documents in a visual studio solution

Here's a handy macro script for visual studio I knocked together today.
It runs "edit, format document" on every document of the listed file types.

You have to keep an eye on it as it's interactive and does sometimes pop up a message and wait for an answer.

You can get the vb file at http://github.com/timabell/vs-formatter-macro
More info at http://wiki.github.com/timabell/vs-formatter-macro

Below is the original code. Note that this is older than the version available on github above.


Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.Text

Public Module Formatting

Dim allowed As List(Of String) = New List(Of String)
Dim processed As Integer = 0
Dim ignored As Integer = 0
Dim errors As StringBuilder = New StringBuilder()
Dim skippedExtensions As List(Of String) = New List(Of String)

Public Sub FormatProject()
allowed.Add(".master")
allowed.Add(".aspx")
allowed.Add(".ascx")
allowed.Add(".asmx")
allowed.Add(".cs")
allowed.Add(".vb")
allowed.Add(".config")
allowed.Add(".css")
allowed.Add(".htm")
allowed.Add(".html")
allowed.Add(".js")
Try
recurseSolution(AddressOf processItem)
Catch ex As Exception
Debug.Print("error in main loop: " + ex.ToString())
End Try
Debug.Print("processed items: " + processed.ToString())
Debug.Print("ignored items: " + ignored.ToString())
Debug.Print("ignored extensions: " + String.Join(" ", skippedExtensions.ToArray()))
Debug.Print(errors.ToString())
End Sub

Private Sub processItem(ByVal Item As ProjectItem)
If Not Item.Name.Contains(".") Then
'Debug.Print("no file extension. ignoring.")
ignored += 1
Return
End If
Dim ext As String
ext = Item.Name.Substring(Item.Name.LastIndexOf(".")) 'get file extension
If allowed.Contains(ext) Then
formatItem(Item)
processed += 1
Else
'Debug.Print("ignoring file with extension: " + ext)
If Not skippedExtensions.Contains(ext) Then
skippedExtensions.Add(ext)
End If
ignored += 1
End If
End Sub

Private Sub formatItem(ByVal Item As ProjectItem)
Debug.Print("processing file " + Item.Name)
Try
Dim window As EnvDTE.Window
window = Item.Open()
window.Activate()
DTE.ExecuteCommand("Edit.FormatDocument", "")
window.Document.Save()
window.Close()
Catch ex As Exception
Debug.Print("error processing file." + ex.ToString())
errors.Append("error processing file " + Item.Name + " " + ex.ToString())
End Try
End Sub

Private Delegate Sub task(ByVal Item As ProjectItem)

Private Sub recurseSolution(ByVal taskRoutine As task)
For Each Proj As Project In DTE.Solution.Projects
Debug.Print("project " + Proj.Name)
For Each Item As ProjectItem In Proj.ProjectItems
recurseItems(Item, 0, taskRoutine)
Next
Next
End Sub

Private Sub recurseItems(ByVal Item As ProjectItem, ByVal depth As Integer, ByVal taskRoutine As task)
Dim indent As String = New String("-", depth)
Debug.Print(indent + " " + Item.Name)
If Not Item.ProjectItems Is Nothing Then
For Each Child As ProjectItem In Item.ProjectItems
taskRoutine(Child)
recurseItems(Child, depth + 1, taskRoutine)
Next
End If
End Sub

End Module

6 comments:

Andy Brook said...

Great posting! I know that badly formatted docs was one of your pet hates!

Visual Studio macro script looks suspiciously like Visual basic to me.

Andy

Tim Abell said...

Yes it is vb, sadly.
You can probably write macros in any .net language, but I wasn't planning on writing that much, so I stuck with the vb.net from the original code. With hindsight I might have converted to C#. At least I could have initialized the list of string in one line then.

Vasile said...

Thanks for the Macro Tim, it is very useful for example when you are assigned on a new project and the code has a mess in terms of indentation.

Good work!

Anonymous said...

Very useful! However, it doesn't work correctly with solution folders.

Edwin said...

Thanks Tim, this saved me a lot of time.

Anonymous said...

Thank you, this really helped me. I inherited a large project that is a total mess. The first thing I wanted to accomplish was to check everything out of source code control, re-format the documents for consistency, and check them back in. Then I'd be able to do "real" diff checks on just my changes, rather than have a ton of formatting changes show up. Thanks again.