In my last article on opening a file in Visual Studio, I have described how to write a macro to open a file given it's name. Now we can take it one step further. How about opening a file containing a type name.
Unlike opening a file, where there is a built in function, searching for a type is a complicated task. We need to loop over all projects, all items, and then analyze the code. Other than that, the code is rather simple if you understand recursion:
Sub OpenType() Dim typeName As String = InputBox("Type name:").ToLower() If String.IsNullOrEmpty(typeName) Then Return End If Dim str As String Dim projectItemContainingType As ProjectItem For Each project As Project In DTE.Solution.Projects projectItemContainingType = FindProjectItemWithType(typeName, project.ProjectItems) If projectItemContainingType IsNot Nothing Then projectItemContainingType.Open() projectItemContainingType.Document.Activate() Return End If Next MsgBox("Type not found", MsgBoxStyle.Information) End Sub Private Function FindProjectItemWithType(ByVal typeName As String, ByVal projectItems As ProjectItems) As ProjectItem Dim projectItemContainingType As ProjectItem For Each projectItem As ProjectItem In projectItems Dim codeModel As FileCodeModel = projectItem.FileCodeModel If codeModel IsNot Nothing Then projectItemContainingType = FindProjectItemWithType(typeName, codeModel.CodeElements) End If If projectItemContainingType Is Nothing AndAlso projectItem.ProjectItems IsNot Nothing AndAlso projectItem.ProjectItems.Count > 0 Then projectItemContainingType = FindProjectItemWithType(typeName, projectItem.ProjectItems) End If If projectItemContainingType IsNot Nothing Then Return projectItemContainingType End If Next Return Nothing End Function Private Function FindProjectItemWithType(ByVal typeName As String, ByVal codeElements As CodeElements) As ProjectItem Dim projectItem As ProjectItem For Each codeElement As CodeElement In codeElements If codeElement.Kind = vsCMElement.vsCMElementClass OrElse codeElement.Kind = vsCMElement.vsCMElementEnum Then If codeElement.Name.ToLower() = typeName Then projectItem = codeElement.ProjectItem Return projectItem End If Continue For End If If (codeElement.Children.Count > 0) Then projectItem = FindProjectItemWithType(typeName, codeElement.Children) If projectItem IsNot Nothing Then Return projectItem End If End If Next Return Nothing End Function
Some shortcut to OpenType procedure (like Ctrl + o, Ctrl + t) and you are ready (I describe how to assign a shortcut in my previous article). It finds top level classes and enums. I have found that searching for inner types - like class or enum defined inside another class, makes it run very slowly - but that is nothing we cannot handle.
If you think you like working with macros and need a bit of practice, there is one thing that can be done that will speed things a lot: instead of searching the whole solution for a type, every time, just build a dictionary of typename/projectitem. That will make your searches lightning fast. Just keep in mind that you have to update this cache every time someone adds or removes types. This is not an easy thing to do! Not by far!s
Remember Me
a@href@title, strike
Powered by: newtelligence dasBlog 2.0.7226.0
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2010, Michal Talaga
E-mail