Thursday, November 27, 2008

Updating the DOxygen macros

So, after my interview at R* Vancouver (I have no idea what they actually call themselves) I thought I would update my Doxygen macros. The reason? I found some old source code that a co-worker of mine when I was at Radical (Neil Martin) had written and there were some tidbits in there that got me thinking about how I could update what I've got into something more manageable. I had a chance to look over the code last night and it was pretty sloppy. So the update gives me a chance to clean it up substantially. Functionality wise, not much has changed. I've created a lot more little functions that do very small things. For example, I've added a 'TimeStamp' function:
Function TimeStamp()
    Dim CurrentDate        
    CurrentDate = System.DateTime.Now.ToShortDateString()        
    Dim CurrentTime        
    CurrentTime = System.DateTime.Now.ToShortTimeString()        
    TimeStamp = "/// Time-stamp: <@(#)" & ActiveDocument.Name & "   " & CurrentDate & " - " & CurrentTime & "   " & Author() & ">"    
End Function
Which I then use like so:
Sub GenerateFileHeader()
    DTE.UndoContext.Open("Generate File Header")
    Try
        Dim linenumber As Integer
        DTE.ActiveDocument.Selection.StartOfDocument()
        Dim FileType
        Dim selection As TextSelection
        selection = DTE.ActiveDocument.Selection
        selection.Text = TimeStamp() & vbLf
        ...
Overall, this makes the code a lot cleaner to read. And a fair bit more manageable. The other thing that I added was the ability to automatically generate Header Guards (something I wanted to add, but was just too lazy last time to do it). As usual, to code follows, as well as a link to a downloadable version. Enjoy.
Imports SystemImports SystemImports EnvDTEImports EnvDTE80Imports System.DiagnosticsImports Microsoft.VisualBasicImports Microsoft.VisualBasic.ControlCharsPublic 
Module Documentation
    ' Check to see if our cursor (the TextSelection passed in) is currently at the first line
    Function OnFirstLine(ByVal selection As TextSelection)
        Return (selection.ActivePoint.Line = 1)
    End Function

    ' Generate a TimeStamp string
    Function TimeStamp()
        Dim CurrentDate
        CurrentDate = System.DateTime.Now.ToShortDateString()
        Dim CurrentTime
        CurrentTime = System.DateTime.Now.ToShortTimeString()
        TimeStamp = "/// Time-stamp: <@(#)" & ActiveDocument.Name & "   " & CurrentDate & " - " & CurrentTime & "   " & Author() & ">"
    End Function

    ' Generate a Doxygen 'Brief' tag, that the user can then populate
    Function Brief()
        Brief = "/// @brief   :"
    End Function

    ' Generate a 'Purpose' string that the user can populate.  Be intellegent about it,
    ' ensuring proper grammar for header as opposed to source files.
    Function Purpose()
        Dim FileType As String
        If InStr(DTE.ActiveDocument.Name, ".h") <> 0 Then
            FileType = "Declaration of class "
        Else
            FileType = "Implementation of methods for class "
        End If
        Purpose = "///  Purpose : " & FileType
    End Function

    ' Generate a DateStamp string
    Function DateStamp()
        Dim CurrentDate
        CurrentDate = System.DateTime.Now.ToShortDateString()
        DateStamp = "/// @date    :" & CurrentDate
    End Function

    ' Generate a simple Comment Line (no fancy decorations)
    Function CommentLine()
        CommentLine = "///"
    End Function

    ' Generate a DOxygen filename tag comment line
    Function FileName()
        FileName = "/// @file    :" & DTE.ActiveDocument.Name
    End Function

    ' Generate an DOxyge author tag comment line
    Function Author()
        ' Up to you, you can either use this function to automatically get the user name
        ' or put in a literal string.
        Author = "/// @author  :" & System.Environment.UserName
    End Function

    ' Generate a Decorated comment line separator
    Function CommentSeparatorLine()
        CommentSeparatorLine = "/// *********************************************************************"
    End Function

    ' Select the current line
    ' Are we actually using this?
    Function SelectCurrentLine()
        DTE.ActiveDocument.Selection.StartOfLine(0)
    End Function

    ' Generate a newline
    ' Question?  Are we actually using this?
    Function NewLine(ByVal selection As TextSelection)
        selection.NewLine()
        selection.StartOfLine()
    End Function

    ' Is the current file a Header file?
    Function IsHeaderFile()
        Dim fileName As String
        fileName = DTE.ActiveDocument().Name
        fileName = Right(fileName, fileName.Length() - InStr(fileName, "."))
        fileName = fileName.ToUpper()
        Return (fileName = "HPP") Or (fileName = "H")
    End Function

    ' Generate Header guards for our file
    Function GenerateHeaderGuards()
        Dim fileName As String
        Dim ifndef As String
        Dim define As String
        fileName = DTE.ActiveDocument().Name
        fileName = Left(fileName, InStr(fileName, ".") - 1)
        fileName = "__" + fileName + "_HPP__"
        fileName = fileName.ToUpper()
        ifndef = "#ifndef " + fileName + vbLf
        define = "#define " + fileName + vbLf + vbLf
        ActiveDocument.Selection.Text = ifndef + define
        ActiveDocument.Selection.EndOfDocument()
        ActiveDocument.Selection.Text = vbLf + "#endif // " + fileName
        ActiveDocument.Selection.StartOfDocument()
    End Function

    ' Generate the default Version history
    Function VersionHistory()
        Dim buffer As String
        Dim CurrentDate
        CurrentDate = System.DateTime.Now.ToShortDateString()
        buffer = "/// Version History:" + vbLf
        buffer = buffer + CommentLine() + vbLf
        buffer = buffer + "/// V 0.10  " & CurrentDate & " : First Revision" + vbLf
        buffer = buffer + CommentLine() + vbLf
        buffer = buffer + CommentSeparatorLine() + vbLf
        buffer = vbLf + vbLf
        VersionHistory = buffer
    End Function

    ' What's our return type for the given statement?
    Function GetReturnType(ByVal inStatement As String)
        Dim returnstring As String
        Dim statement As String
        statement = inStatement
        'Find first bracket
        If (InStr(statement, "(") <> 0) Then
            'This gets us the return value and function/method name
            statement = Left(statement, InStr(statement, "(") - 1)
            ' Strip off whitespaces (some people put a space before the '('
            statement = TrimAll(statement)
            Dim tokenArray() As String
            tokenArray = Split(Trim(statement), " ")
            If tokenArray.Length > 1 Then
                Dim index As Integer
                index = 0
                While index < tokenArray.Length - 1
                    returnstring = returnstring + tokenArray(index)
                    index = index + 1
                End While
                If returnstring.ToLower = "void" Then
                    returnstring = "/// "
                Else
                    returnstring = "/// @returns   :" & returnstring
                End If
            Else
                returnstring = "/// "
            End If
        End If
        GetReturnType = returnstring
    End Function

    ' Generate a paramater tag bundle from the given statement
    Function BuildParams(ByVal TextIn As String) As String
        Dim args As String
        Dim result As String
        Dim argsarray() As String
        args = Split(TextIn, "(")(1)
        args = Replace(args, ")", " ")
        args = TrimAll(args)
        argsarray = Split(args, ",")
        ' now for our args
        result = ""
        For Each arguement As String In argsarray
            Dim tokenArray() As String
            Dim character As Char
            tokenArray = Split(Trim(arguement), " ")
            result = result & "/// @param " & tokenArray(tokenArray.Length - 1) & vbLf
        Next
        BuildParams = result
    End Function

    ' Trim out all the unecessary fluff from a given string.
    Function TrimAll(ByVal TextIn As String) As String
        Try ' Replace ALL Duplicate Characters in String with a Single Instance
            Dim result As String
            result = TextIn
            result = Replace(result, vbTab, " ")
            result = Replace(result, vbNullChar, " ")
            result = Replace(result, vbCr, " ")
            result = Replace(result, vbLf, " ")
            result = Trim(result)
            TrimAll = result
        Catch Exp As Exception
            TrimAll = TextIn ' Oops
        End Try
        Return TrimAll
    End Function

    ' Generate the statement that we want to test
    Function GetStatement()
        Dim selection As TextSelection
        Dim statement As String
        Dim linenumber As Integer
        selection = DTE.ActiveDocument.Selection
        ' Get all the arguements from the method
        linenumber = selection.ActivePoint.Line
        selection.StartOfLine()
        selection.SelectLine()
        statement = TrimAll(selection.Text)
        Dim nextline As String
        Dim lastLine As Integer
        lastLine = linenumber
        While (InStr(statement, ")") = 0)
            selection.SelectLine()
            If lastLine <> selection.ActivePoint.Line Then
                nextline = TrimAll(selection.Text)
                statement = statement & nextline
            Else
                Exit While
            End If
        End While
        selection.GotoLine(linenumber)
        selection.StartOfLine()
        GetStatement = statement
    End Function

    Sub PerformDocumentation()
        Try
            Dim objTextDoc As TextDocument
            Dim editPoint As EnvDTE.EditPoint
            Dim selection As TextSelection
            Dim linenumber As Integer
            objTextDoc = DTE.ActiveDocument.Object("TextDocument")
            editPoint = objTextDoc.StartPoint.CreateEditPoint
            selection = objTextDoc.Selection
            linenumber = selection.ActivePoint.Line
            selection.StartOfLine()
            If OnFirstLine(selection) = True Then
                GenerateFileHeader()
            ElseIf selection.FindText("class") = True Then
     'Class declaration
                GenerateClassHeader()
            ElseIf selection.FindText("::") = True Then
     'Method definition
                GenerateMethodHeader()
            Else
                If selection.FindText("{") Then
             'Some Function definition
                    selection.GotoLine(linenumber)
                    GenerateFunctionHeader()
                End If
            End If
        Catch ex As Exception
            Dim messagebox As System.Windows.Forms.MessageBox
            messagebox.Show(ex.Message)
        Finally
        End Try
    End Sub

    Sub GenerateMethodHeader()
        Dim selection As TextSelection
        DTE.UndoContext.Open("MethodHeader")
        Try
            selection = DTE.ActiveDocument.Selection
            ' Get all the arguements from the method
            Dim args As String
            Dim argsarray() As String
            Dim linenumber As Integer
            Dim statement As String
            statement = GetStatement()
            selection.NewLine()
            selection.StartOfLine()
            selection.Text = CommentSeparatorLine() & vbLf
            linenumber = selection.ActivePoint.Line ' This is where we want to return to
            selection.Text = Brief() & vbLf
            selection.Text = CommentLine() & vbLf
            selection.Text = GetReturnType(statement) & vbLf
            selection.Text = BuildParams(statement)
            selection.Text = CommentSeparatorLine() & vbLf
            selection.GotoLine(linenumber)
            selection.EndOfLine()
        Catch ex As Exception
            Dim messagebox As System.Windows.Forms.MessageBox
            messagebox.Show(ex.Message)
        Finally
            DTE.UndoContext.Close()
        End Try
    End Sub

    Sub GenerateFunctionHeader()
        Dim selection As TextSelection
        DTE.UndoContext.Open("FunctionHeader")
        Try
            selection = DTE.ActiveDocument.Selection
            ' Get all the arguements from the method
            Dim args As String
            Dim argsarray() As String
            Dim linenumber As Integer
            Dim statement As String
            statement = GetStatement()
            selection.NewLine()
            selection.StartOfLine()
            selection.Text = CommentSeparatorLine() & vbLf
            linenumber = selection.ActivePoint.Line ' This is where we want to return to
            selection.Text = Brief() & vbLf
            selection.Text = CommentLine() & vbLf
            selection.Text = GetReturnType(statement) & vbLf
            selection.Text = BuildParams(statement)
            selection.Text = CommentSeparatorLine() & vbLf
            selection.GotoLine(linenumber)
            selection.EndOfLine()
        Catch ex As Exception
            Dim messagebox As System.Windows.Forms.MessageBox
            messagebox.Show(ex.Message)
        Finally
            DTE.UndoContext.Close()
        End Try
    End Sub

    Sub GenerateClassHeader()
        DTE.UndoContext.Open("ClassHeader")
        Try
            Dim selection As TextSelection
            Dim linenumber As Integer
            selection = DTE.ActiveDocument.Selection
            selection.StartOfLine()
            selection.NewLine()
            selection.StartOfLine()
            selection.Text = CommentSeparatorLine() & vbLf
            linenumber = selection.ActivePoint.Line ' This is where we want to return to
            selection.Text = Brief() & vbLf
            selection.Text = CommentLine() & vbLf
            selection.Text = CommentLine() & vbLf
            selection.Text = CommentSeparatorLine() & vbLf
            selection.GotoLine(linenumber)
            selection.EndOfLine()
        Catch ex As Exception
        Finally
            DTE.UndoContext.Close()
        End Try
    End Sub

    Sub GenerateFileHeader()
        DTE.UndoContext.Open("Generate File Header")
        Try
            Dim linenumber As Integer
            DTE.ActiveDocument.Selection.StartOfDocument()
            Dim FileType
            Dim selection As TextSelection
            selection = DTE.ActiveDocument.Selection
            selection.Text = TimeStamp() & vbLf
            selection.Text = CommentSeparatorLine() & vbLf
            selection.Text = FileName() & vbLf
            selection.Text = CommentLine() & vbLf
            selection.Text = Author() & vbLf
            selection.Text = DateStamp() & vbLf
            selection.Text = CommentLine() & vbLf
            linenumber = selection.ActivePoint.Line ' This is where we want to return to
            selection.Text = Purpose() & vbLf
            selection.Text = CommentLine() & vbLf
            selection.Text = Brief() & vbLf
            selection.Text = CommentSeparatorLine() & vbLf
            selection.Text = VersionHistory() & vbLf
            If IsHeaderFile() = True Then
                GenerateHeaderGuards()
            End If
            selection.GotoLine(linenumber)
            selection.EndOfLine()
        Catch ex As Exception
            Dim messagebox As System.Windows.Forms.MessageBox
            messagebox.Show(ex.Message)
        Finally
            DTE.UndoContext.Close()
        End Try
    End
 SubEnd
 Module
Download here: http://ash.matheson.googlepages.com/Documentation.rar

No comments: