7. Tips/Visual Studio

[Visual Studo .NET 2003 C++] Doxygen 스타일의 주석을 생성하는 Macro 코드

SSKK 2008. 8. 19. 21:02
클래스 및 함수등을 선택한 후 아래 매크로를 수행하면

주석을 달기 위한 입력 대화상자가 뜨며 그 대화상자에다가 정보를 입력하면 Doxygen과 호환되는 주석을 생성한다.

사용법 :

1. 아래 그림과 같이 주석을 할 함수나 클래스를 선택한다.


2. 매크로 탐색기에서 해당 매크로, 만약 아래의 코드를 그대로 사용하였다면 MakeCommentForDoxygen을 실행한다. 아래 작성된 코드를 매크로 탐색기에다가 붙여 넣으면 된다.



3. 그러면 아래와 같이 클래스나 함수에 대한 간단한 개요와 파라미터와 반환형에 대한 개요을 적을 수 있는 입력상자를 띄운다. 그 입력상자에 원하는 정보를 넣어준다.

 > 함수의 간단한 개요 (Brief)

 > 파라미터 i의 개요

 > 파라미터 c의 개요

 > 반환형의 개요

4. 위와 같이 입력하면, 아래와 같은 주석을 생성한다.



5. 이렇게 입력한 주석들을 이용하여 Doxgen 을 가지고 문서를 생성하면 각각의 함수나 코멘트에 대한 설명을 볼 수 있다. (Doxygen은 Java의 API Document와 같은 문서를 생성하게 해준다. 자세한 정보는 Doxygen 사이트 참고. 무료 툴이다.)

<매크로 코드>

Imports EnvDTE
Imports System.Diagnostics
Imports System
Imports Microsoft.VisualBasic.ControlChars
Public Module Module1
    Function InsertNewLine(ByRef doc As Document, ByVal Str As String)
        doc.Selection.NewLine()
        doc.Selection.StartOfLine()
        doc.Selection.Text = Str
    End Function

    Function GetParam(ByVal str As String) As String
        Dim iIndexFound As Integer
        Dim strTemp As String
        strTemp = Trim(str)
        iIndexFound = InStr(str, " ", CompareMethod.Text)
        If iIndexFound > 0 Then
            GetParam = Trim(Right(strTemp, Len(strTemp) - iIndexFound))
        Else
            GetParam = strTemp
        End If
    End Function
    Function RemoveComment(ByVal str As String) As String
        Dim iCommentPrefixFound As Integer
        Dim iCommentPostfixFound As Integer
        Dim strTemp As String
        RemoveComment = str
        iCommentPrefixFound = InStr(RemoveComment, "/*", CompareMethod.Text)
        While iCommentPrefixFound > 0
            strTemp = Right(RemoveComment, Len(RemoveComment) - iCommentPrefixFound + 1)
            iCommentPostfixFound = InStr(strTemp, "*/", CompareMethod.Text)
            If iCommentPostfixFound > 0 Then
                RemoveComment = Left(RemoveComment, iCommentPrefixFound - 1)
                strTemp = Right(strTemp, Len(strTemp) - iCommentPostfixFound - 1)
                RemoveComment = RemoveComment & strTemp
            Else
                RemoveComment = Left(RemoveComment, iCommentPrefixFound - 1)
                Exit While
            End If
            iCommentPrefixFound = InStr(RemoveComment, "/*", CompareMethod.Text)
        End While
    End Function
    Sub MakeCommentForDoxygen()
        Dim strDelimFormat As String = "//////////////////////////////////////////////////////////////////////////"
        Dim strBriefFormat As String = "/// @brief" & Tab & Tab
        Dim strAuthorFormat As String = "/// @author" & Tab & Tab
        Dim strVersionFormat As String = "/// @version" & Tab & "v1.0"
        Dim strDateFormat As String = "/// @date" & Tab & Tab
        Dim strRemarkFormat As String = "/// @remark" & Tab & Tab
        Dim strReturnFormat As String = "/// @return" & Tab & Tab
        Dim strParamFormat As String = "/// @param" & Tab
        Dim FuncAll As String = DTE.ActiveDocument.Selection.Text
        Dim iIndexFound As Integer
        Dim strTemp As String
        Dim strInput As String
        Dim strClass As String = "Class"
        Dim currentDate As Date
        Dim strBriefDesc As String
        FuncAll = RemoveComment(FuncAll)    ' /* */ 로 끝나는 주석을 제거함.
        ' 선택된 텍스트를 가져옴
        FuncAll = FuncAll.Replace(CStr(Tab), " ")
        FuncAll = Trim(FuncAll.Replace(CStr(CrLf), ""))
        Dim curDocument As Document
        curDocument = ActiveDocument   ' 현재 다큐먼트를 저장

        ' 클래스인지 함수 인지 검사
        iIndexFound = InStr(UCase(FuncAll), UCase(strClass), CompareMethod.Text)
        Dim iTemp As Integer
        iTemp = iIndexFound - 1
        If iTemp > 0 Then
            strTemp = Mid(FuncAll, iIndexFound - 1, 1)  ' class 키워드 앞에 다른 문자가 붙으면 클래스가 아님.
            If strTemp <> " " Then
                iIndexFound = 0
            End If
        End If
        If iIndexFound > 0 Then ' 클래스이다
            strTemp = Right(FuncAll, FuncAll.Length - iIndexFound - Len(strClass) + 1)
            iIndexFound = InStr(strTemp, ":", CompareMethod.Text)
            If (iIndexFound > 0) Then
                strTemp = Left(strTemp, iIndexFound - 1)
                strTemp = Trim(strTemp)
            End If
            If strTemp.Length <> 0 Then
                ' 클래스 주석을 추가하자
                ' 입력을 먼저 받고 입력이 있을 경우에만 아래를 추가하자
                ' Brief
                strInput = InputBox("Insert a brief into " & strTemp)        ' 현재 strTemp는 클래스 명이다
                strTemp = Trim(strInput)
                If strTemp.Length = 0 Then
                    Exit Sub
                End If
                ' Delimitor
                curDocument.Selection.GotoLine(curDocument.Selection.TopLine)
                curDocument.Selection.StartOfLine(EnvDTE.vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
                InsertNewLine(curDocument, strDelimFormat)
                ' brief 추가
                strBriefDesc = strBriefFormat & strInput
                InsertNewLine(curDocument, strBriefDesc)
                ' version
                InsertNewLine(curDocument, strVersionFormat)
                ' Date
                currentDate = Date.Now
                strTemp = strDateFormat & Trim(Str(currentDate.Year())) & "/" & Trim(Str(currentDate.Month())) & "/" & Trim(Str(currentDate.Day()))
                InsertNewLine(curDocument, strTemp)
                ' Author
                strTemp = System.Security.Principal.WindowsIdentity.GetCurrent().Name()
                iIndexFound = InStr(strTemp, "\", CompareMethod.Text)
                If iIndexFound > 0 Then
                    strTemp = Right(strTemp, Len(strTemp) - iIndexFound)
                End If
                strTemp = strAuthorFormat & strTemp
                InsertNewLine(curDocument, strTemp)
                ' Delimitor
                InsertNewLine(curDocument, strDelimFormat)
                curDocument.Selection.NewLine()
            End If
        Else    ' 함수인지 검사
            iIndexFound = InStr(FuncAll, "(", CompareMethod.Text)
            If iIndexFound > 0 Then
                Dim strFunc As String
                Dim strReturn As String
                Dim strParams As String
                Dim strReturnDesc As String
                strFunc = Left(FuncAll, iIndexFound - 1)    ' 괄호앞 전체
                strTemp = Right(FuncAll, Len(FuncAll) - iIndexFound)   ' 괄호 이후 뒤쪽
                ' strFunc에서 반환값 추출
                iIndexFound = InStrRev(strFunc, " ", -1, CompareMethod.Text)
                If iIndexFound > 0 Then
                    strReturn = Trim(Left(strFunc, iIndexFound))
                Else
                    strReturn = ""
                End If
                iIndexFound = InStr(strTemp, ")", CompareMethod.Text)
                If iIndexFound > 0 Then
                    strParams = Trim(Left(strTemp, iIndexFound - 1))
                    Dim strParamList As String()
                    Dim strParamDesc As String()
                    Dim iParamCount As Integer = 0
                    Dim iCount As Integer
                    ' 파라미터 갯수 파악하기
                    If Len(strParams) <> 0 Then
                        strTemp = strParams
                        iIndexFound = InStr(strTemp, ",", CompareMethod.Text)
                        If iIndexFound > 0 Then
                            ' 파라미터가 1개 이상이다
                            ' 콤마 갯수를 센 후에 어레이를 잡고 파라미터를 대입하자 (무식하지만 귀찮다)
                            Dim iCommaCount As Integer = 0
                            While iIndexFound > 0
                                iCommaCount = iCommaCount + 1
                                strTemp = Right(strTemp, Len(strTemp) - iIndexFound)
                                iIndexFound = InStr(strTemp, ",", CompareMethod.Text)
                            End While
                            iParamCount = iCommaCount + 1
                            ReDim strParamList(iParamCount)
                            strTemp = strParams
                            iIndexFound = InStr(strTemp, ",", CompareMethod.Text)
                            iCount = 1
                            While iIndexFound > 0
                                strParamList(iCount) = Trim(Left(strTemp, iIndexFound - 1))
                                strTemp = Right(strTemp, Len(strTemp) - iIndexFound)
                                iIndexFound = InStr(strTemp, ",", CompareMethod.Text)
                                iCount = iCount + 1
                            End While
                            strParamList(iCount) = Trim(strTemp)
                        Else
                            iParamCount = 1
                            ReDim strParamList(iParamCount)
                            strParamList(iParamCount) = strTemp
                        End If
                    End If
                    ' Brief 얻기
                    strBriefDesc = InputBox("Insert a brief into " & strFunc)
                    If Len(strBriefDesc) = 0 Then
                        Exit Sub
                    End If
                    ReDim strParamDesc(iParamCount)
                    ' 파라미터에 대한 brief 얻기
                    For iCount = 1 To iParamCount
                        If iParamCount <> 1 Or UCase(strParamList(1)) <> "VOID" Then
                            strParamDesc(iCount) = InputBox("Insert a brief into " & strParamList(iCount))
                        End If
                    Next iCount
                    ' Return에 대한 brief 얻기
                    If Len(strReturn) <> 0 And UCase(strReturn) <> "VOID" Then
                        strReturnDesc = InputBox("Inser a brief into the return value")
                    End If
                    ' Delimitor
                    curDocument.Activate()
                    curDocument.Selection.GotoLine(curDocument.Selection.TopLine)
                    curDocument.Selection.StartOfLine(EnvDTE.vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
                    InsertNewLine(curDocument, strDelimFormat)
                    ' brief 추가
                    strBriefDesc = strBriefFormat & strBriefDesc
                    InsertNewLine(curDocument, strBriefDesc)
                    ' 파라미터에 대한 정보 추가
                    For iCount = 1 To iParamCount
                        If iParamCount <> 1 Or UCase(strParamList(1)) <> "VOID" Then
                            strTemp = GetParam(strParamList(iCount))
                            strTemp = strParamFormat & strTemp & Tab & strParamDesc(iCount)
                            InsertNewLine(curDocument, strTemp)
                        End If
                    Next
                    If Len(strReturn) <> 0 And UCase(strReturn) <> "VOID" Then
                        ' Return 추가
                        strReturnDesc = strReturnFormat & strReturnDesc
                        InsertNewLine(curDocument, strReturnDesc)
                    End If
                    InsertNewLine(curDocument, strRemarkFormat)
                    ' Delimitor
                    InsertNewLine(curDocument, strDelimFormat)
                    curDocument.Selection.NewLine()
                    curDocument.Selection.StartOfLine()
                End If
            End If
        End If
        curDocument.Save()
        'Temp = FuncAll.IndexOf("(")
        'If Temp < 0 Then Exit Sub
    End Sub
End Module