Extending Intellisense: Namespace lookup with a macro

Namespaces in .NET are great! But how many times do you find yourself typing "Private r As xmlreader", and then noticing that there is no Imports/using statement for the System.Xml Namespace? Then you would have to scroll to the top of your document and add the Imports/using statement by hand. Alternatively you could choose to add the namespace to your declaration: "Private r As System.Xml.XmlReader". Since we are all developers, why not develop something to help developers with this tedious task of namespace lookups?

I've created the macro below that does the namespace lookup trick. The macro has 3 public methods you can assign for example to a shortcut key:

  • AddNamespace
    This method will search the corresponding namespace for the typename you've just typed in your code, and add it to your type. So if you type for example "textreader", the macro will convert it to "System.IO.TextReader".
  • AddImports
    This method will search the corresponding namespace for the typename you've just typed in your code and add an Imports statement at the top of your code. So, if you've typed "textreader", the marco will add "Imports System.IO" at the top of your code. Additionaly the "textreader" will by replaced by "TextReader".
  • AddUsing
    This method is the same as the AddImports method, but can be used for the C# "using" keyword.

Since this is the first version of the macro, I would appriciate if you can give some feedback if you find it usefull, or if there are any bugs/problems! Here is the complete source code (I suggest you create a new macro module for it, and call it TypeFinder):
Imports EnvDTE
Imports System.Diagnostics
Imports System

Public Module TypeFinder
    Private Function SearchTypeInAssembly(ByVal typename As String, ByVal ass As Reflection.Assembly)
        DTE.StatusBar.Text = "Searching for '" & typename & "' " & ass.GetName.Name & "..."
        Dim t As Type
        For Each t In ass.GetTypes
            If t.Name.ToLower = typename Then
                Return t
            End If
        Next
    End Function
    Private Function SearchType(ByVal typename As String) As Type
        typename = typename.ToLower
        Dim projs As System.Array = DTE.ActiveSolutionProjects
        Dim ass As Reflection.Assembly = Reflection.Assembly.LoadWithPartialName("mscorlib")
        Dim t As Type = SearchTypeInAssembly(typename, ass)
        If Not t Is Nothing Then Return t
        Dim proj As Project
        For Each proj In projs
            Dim o As VSLangProj.VSProject = proj.Object
            Dim ref As VSLangProj.Reference
            For Each ref In o.References
                ass = Reflection.Assembly.LoadFile(ref.Path)
                t = SearchTypeInAssembly(typename, ass)
                If Not t Is Nothing Then Return t
            Next
        Next
        DTE.StatusBar.Text = "Could not find type '" & typename & "' in the referenced libraries."
        DTE.StatusBar.Highlight(True)
        Return Nothing
    End Function
    Public Sub AddNamespace()
        Dim text As TextSelection = DTE.ActiveDocument.Selection
        text.WordLeft(True)
        Dim t As Type = SearchType(text.Text)
        If Not t Is Nothing Then
            text.Text = t.FullName
            text.EndOfLine()
            DTE.StatusBar.Text = "Ready"
        End If
    End Sub
    Public Sub AddImports()
        Dim text As TextSelection = DTE.ActiveDocument.Selection
        text.WordLeft(True)
        Dim t As Type = SearchType(text.Text)
        If Not t Is Nothing Then
            Dim line As Integer = text.AnchorPoint.Line
            text.Text = t.Name
            text.StartOfDocument()
            text.Insert("Imports " & t.Namespace & vbCrLf)
            text.MoveToLineAndOffset(line + 1, 1)
            text.EndOfLine()
            DTE.StatusBar.Text = "'Imports " & t.Namespace & "' added to the document."
            DTE.StatusBar.Highlight(True)
        End If
    End Sub
    Public Sub AddUsing()
        Dim text As TextSelection = DTE.ActiveDocument.Selection
        text.WordLeft(True)
        Dim t As Type = SearchType(text.Text)
        If Not t Is Nothing Then
            Dim line As Integer = text.AnchorPoint.Line
            text.Text = t.Name
            text.StartOfDocument()
            text.Insert("using " & t.Namespace & ";" & vbCrLf)
            text.MoveToLineAndOffset(line + 1, 1)
            text.EndOfLine()
            DTE.StatusBar.Text = "'using " & t.Namespace & ";' added to the document."
            DTE.StatusBar.Highlight(True)
        End If
    End Sub
End Module

4 Comments

  • Nice. Thanks





    By the way, this only works in VS 2003.


    In VS 2002 it chokes on


    ass = Reflection.Assembly.LoadFile(ref.Path)





    LoadFile is not a member of Assembly.

  • Sorry Jan,


    I have some problems in vs.NET 2003. I keep getting a "Could not find file "" in the referenced libraries."


    Even with

  • Sorry Jan,


    I have some problems in vs.NET 2003. I keep getting a "Could not find file "" in the referenced libraries."


    Even with your own example of xmlreader.


    And in C# and in VB.net

  • Hi Yves,





    I think you have a small problem with the selection of the Type to be found. My macro is written so that it searches for the type that is typed in front of the cursor. So you don't need to select anything. Just type the name of the type, without a space after it, and call your macro.





    Let me know if you have any problems,


    Jan





    Btw: I'm really looking forward to your blog!

Comments have been disabled for this content.