代码注释有很多风格,纵多开源软件都使用doxygen中几种注释风格的一种。在多个人协作开发一款软件或系统或者项目时,需要统一编码规范。代码的注释也是编码规范的一部分。我们在编写代码注释时为了统一风格,经常使用copy-paste方法,然后再修改不同的部分。为了更方便统一代码注释规范的应用,加快开发中编码的速度,我们在VS2005 IDE中使用代码注释插件,设定相应的快捷键,在使用时只需要按快捷键即可,效果就跟使用VS2005中自带的功能一样,比如在VS2005中选中代码按C-K C-C即可注释掉选中的代码。
我们使用VS2005中的宏来编写代码注释插件,其宏代码如下:
Imports System Imports EnvDTE Imports EnvDTE80 Imports System.Diagnostics 'Code Comment v1.0 'leatinfy <[email protected]> Public Module CodeComment 'C-M C-H(head of file) Sub AddFileHeaderComment() If DTE.ActiveDocument.Type = "Text" Then Dim selection As EnvDTE.TextSelection Dim commText As String Dim outTextDoc As TextDocument Dim outText As EditPoint selection = DTE.ActiveDocument.Selection commText = "/**" + vbCrLf commText += " * @file " + DTE.ActiveDocument.Name + vbCrLf commText += " * @author " + vbCrLf commText += " * @date " + System.DateTime.Now.ToString("yyyy-MM-dd") + vbCrLf commText += " * @version 1.0" + vbCrLf commText += " * <file description>" + vbCrLf commText += " */" + vbCrLf outTextDoc = DTE.ActiveDocument.Object("TextDocument") outText = outTextDoc.StartPoint.CreateEditPoint() outText.MoveToPoint(selection.TopPoint) selection.Text = "" outText.Insert(commText) End If End Sub '/** ' * style1 ' */ 'C-M C-C(code comment) Sub AddCommentStyle1() If DTE.ActiveDocument.Type = "Text" Then Dim selection As EnvDTE.TextSelection Dim commText As String Dim topline As Integer selection = DTE.ActiveDocument.Selection topline = selection.TopLine commText = "/**" + vbLf commText += " * " + vbLf commText += "*/" selection.Text = commText selection.MoveToLineAndOffset(topline + 1, 1) selection.EndOfLine() End If End Sub '/** style2 */ 'C-M C-A(above the code line) Sub AddCommentStyle2() If DTE.ActiveDocument.Type = "Text" Then Dim selection As EnvDTE.TextSelection Dim commText As String selection = DTE.ActiveDocument.Selection commText = "/** */" selection.Text = commText selection.CharLeft(, 3) End If End Sub '/**< style3 */ 'C-M C-E (end of the code line) Sub AddCommentStyle3() If DTE.ActiveDocument.Type = "Text" Then Dim selection As EnvDTE.TextSelection Dim commText As String selection = DTE.ActiveDocument.Selection commText = "/**< */" selection.Text = commText selection.CharLeft(, 3) End If End Sub '/* style4 */ 'C-M C-N(normal c style) Sub AddCommentStyle4() If DTE.ActiveDocument.Type = "Text" Then Dim selection As EnvDTE.TextSelection Dim commText As String selection = DTE.ActiveDocument.Selection commText = "/* */" selection.Text = commText selection.CharLeft(, 3) End If End Sub 'C-M C-F(function comment) Sub AddFunctionComment() Dim selection As EnvDTE.TextSelection If DTE.ActiveDocument.Type = "Text" Then selection = DTE.ActiveDocument.Selection Dim functext As String Dim funinfo As FuncInfo Dim editpoint As EditPoint Dim startLine As Integer Dim endLine As Integer Dim strTmp As String Dim commentText As String Dim col As Integer Dim codefunc As CodeFunction codefunc = CType(selection.TopPoint.CodeElement(vsCMElement.vsCMElementFunction), CodeFunction) If codefunc Is Nothing Then Exit Sub End If functext = String.Copy(selection.Text) commentText = "/**" + vbCrLf + " * " + codefunc.Name + " " + vbCrLf For Each arg As CodeElement In codefunc.Children commentText += "* @param " + arg.Name + " " + vbCrLf Next If codefunc.Type.AsString().ToLower() <> "void" Then commentText += "* @return " + " " + vbCrLf End If commentText += "*/" col = selection.TopPoint.DisplayColumn selection.GotoLine(selection.TopLine) selection.NewLine() selection.LineUp(, 1) If col > 1 Then selection.PadToColumn(col) Else selection.Text = GetFirstSpaceText(functext) End If selection.Text = commentText End If End Sub Public Class FuncInfo Public FuncName As String Public Args As New Collections.ArrayList Public hasReturn As Boolean End Class Public Structure BracketCount Public LCount As Integer Public RCount As Integer End Structure Private Function GetFuncInfo(ByVal funcstxt As String) As FuncInfo Dim index As Integer Dim funinfo As New FuncInfo Dim strTmp As String Dim args As String() index = funcstxt.IndexOf("(") strTmp = funcstxt.Substring(0, index) funinfo.FuncName = GetVarPartFromEnd(GetLastWord(strTmp)) funinfo.hasReturn = HasReturnValue(strTmp) If index < 0 Then Return funinfo End If strTmp = funcstxt.Substring(index + 1) index = strTmp.IndexOf(")") If index < 0 Then Return funinfo End If strTmp = strTmp.Substring(0, index) args = strTmp.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries) Dim i As Integer = 0 Dim counter As BracketCount Dim tmpcounter As BracketCount While i < args.Length counter.LCount = 0 counter.RCount = 0 While i < args.Length tmpcounter = GetBracketCount(args(i)) counter.LCount = counter.LCount + tmpcounter.LCount counter.RCount = counter.RCount + tmpcounter.RCount If counter.LCount = counter.RCount Then Exit While Else i = i + 1 End If End While If i < args.Length And counter.LCount = counter.RCount Then funinfo.Args.Add(GetLastWord(args(i))) End If i = i + 1 End While Return funinfo End Function Private Function GetVarPartFromEnd(ByVal funcStr As String) As String Dim strLen As Integer Dim ch As Char strLen = funcStr.Length For i As Integer = strLen - 1 To 0 Step -1 ch = funcStr.Chars(i) If (Asc(ch) >= 48 And Asc(ch) <= 57) Or (Asc(ch) >= 65 And Asc(ch) <= 90) Or (Asc(ch) >= 97 And Asc(ch) <= 122) Or ch = "_"c Then Continue For Else Return funcStr.Substring(i + 1) End If Next Return funcStr End Function Private Function GetLastWord(ByVal str As String) As String Dim strLen As Integer Dim index As Integer Dim strTmp As String str = str.TrimEnd((" " + vbTab + vbLf + vbCrLf).ToCharArray()) strLen = str.Length For i As Integer = strLen - 1 To 0 Step -1 If str.Chars(i) = " " Or str.Chars(i) = vbTab Or str.Chars(i) = vbLf Or str.Chars(i) = vbCrLf Then Return str.Substring(i + 1) End If Next Return str End Function Private Function GetBracketCount(ByVal str As String) As BracketCount Dim strLen As Integer Dim counter As BracketCount counter.LCount = 0 counter.RCount = 0 strLen = str.Length For i As Integer = 0 To strLen - 1 If str.Chars(i) = "<"c Then counter.LCount = counter.LCount + 1 End If If str.Chars(i) = ">"c Then counter.RCount = counter.RCount + 1 End If Next Return counter End Function Private Function GetFirstTextPosition(ByVal str As String, ByVal tabSize As Integer) As Integer Dim strLen As Integer Dim pos As Integer = 0 strLen = str.Length Dim i As Integer = 0 For i = 0 To strLen - 1 If str.Chars(i) = " "c Then pos = pos + 1 ElseIf str.Chars(i) = vbTab Then pos = pos + tabSize Else Return pos End If Next i Return pos End Function Private Function GetFirstSpaceText(ByVal str As String) As String Dim strLen As Integer Dim pos As Integer = 0 strLen = str.Length Dim i As Integer = 0 For i = 0 To strLen - 1 If str.Chars(i) <> " " And str.Chars(i) <> vbTab Then Exit For End If Next i Return str.Substring(0, i) End Function 'check function has return value Private Function HasReturnValue(ByVal str As String) As Boolean Dim strs As String() strs = str.Split((" " + vbTab + vbLf + vbCrLf).ToCharArray(), StringSplitOptions.RemoveEmptyEntries) Return Not Array.Exists(strs, AddressOf IsVoidKeyWords) End Function Private Function IsVoidKeyWords(ByVal str As String) As Boolean If str.ToLower() = "void" Then Return True Else Return False End If End Function End Module
这里我自己编写的宏代码,有四种代码注释风格,和一个文件注释、一个函数注释功能。其注释风格如:
/** * @file * @author * @date * @version * <file description> */ /** * function description * @param p1 * @param p2 * @return */ /** * style1 */ /** style2 */ /**< style3 */ /* style4 */ // style 5
接下来我们简单说一下如何使用这个注释插件。在“工具->宏->宏IDE”先启动宏IDE,然后新建一个宏项目,就上面的宏代码copy进去,接着就在VS2005中绑定快捷键,在“工具->选项->键盘”中选定相应的宏函数,然后分配快捷键。宏中的函数前面注释中的快捷键为推荐的快捷键,自己完全可以跟根自身的喜好来设定。
比如,我们选中函数getname,然后按C-M C-F(我绑定的是这两个键),然后生成函数上面部分的代码
/** * getname * @param id * @return */ int getname(int id) { ... }
注:GetFuncInfo GetVarPartFromEnd GetLastWord GetBracketCount HasReturnValue IsVoidKeyWords这几个函数为我自已通过分析字符串来分析函数的参数代码,在查阅文档时发现可以通过.Net的CodeElement(vsCMElement.vsCMElementFunction)过获取函数的相应信息,就对生成函数注释的宏代码进行了修改,这几个函数仅供大家参考,在AddFunctionComment中并没有调用。