#概要
Visual Studio のProfessionalEdition以上ではマクロを使用することができる。
そのマクロを使用することで、VisualStudioの操作を自動化することが可能である。
今回はVCのコードでDoxygenコメントを記述するマクロを作成する。
VisualStudio2008 Proffesionalでサンプルを記述しているが、新しいバージョンでも同等のことができる。
Vs2012から使えないの拡張機能を使う必要がある。
(2019/12/15 追記)
復活のVisualStudioのマクロ
https://qiita.com/mima_ita/items/c56d6e2657cc836af7ac
いくつかの制限付きながら拡張機能としてVisualStudioのマクロが復活しているようです。
#マクロの登録方法
1.[ツール]→[マクロ]→[マクロエクスプローラ]を選択する。
3.モジュール追加のダイアログで任意の名前でモジュールを追加する。
4.マクロエクスプローラで追加したモジュールを選択して編集を行う
5.MicrosoftVisual Studio Macrosが起動するので以後、そこでマクロを記述する。
#選択中の項目にDoxygenコメントを記述するコード
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics
Public Module mdlVCSrcMacros
' カーソルで選択中の関数/Class/EnumにDoxgenで使用するコメントを付与します.
' 何も選択せずにファイルの先頭にある場合⇒ファイル用のヘッダコメント
' cppファイルで関数を選択して実行⇒関数用ヘッダ
' ※クラスのメンバはClassViewが認識していないとコメントを付与してくれない
' TODO:課題
' classを選択して実行⇒クラス用ヘッダ
' enumを選択して実行⇒enum用ヘッダ.
' 参考
' http://www.microsoft.com/japan/msdn/academic/Articles/fun/06/
Sub CreateHeaderComment()
Dim sel As TextSelection = DTE.ActiveDocument.Selection
Dim strCom As String
Dim myFCM As FileCodeModel = DTE.ActiveDocument.ProjectItem.FileCodeModel
strCom = ""
' ファイルヘッダ.
If sel.TopPoint.Line = 1 And sel.Text.Length = 0 Then
sel.Text = "/**"
sel.NewLine()
sel.Text = " * @file" + vbTab + DTE.ActiveDocument.Name
sel.NewLine()
sel.Text = "* @brief" + vbTab + "Copyright(c) " + Year(Today()).ToString()
sel.Text = vbTab + "Nikon Corporation - All rights reserved."
sel.NewLine()
sel.Text = "* @date" + vbTab + Format(Today(), "yyyy/MM/dd")
sel.NewLine()
sel.Text = "* @author" + vbTab + "作者名"
sel.NewLine()
sel.Text = "* @note" + vbTab + ""
sel.NewLine()
sel.Text = "*/"
Exit Sub
End If
Dim objCodeElement As CodeElement ' コード情報取得用オブジェクト
' 関数ヘッダ
objCodeElement = myFCM.CodeElementFromPoint(sel.ActivePoint, vsCMElement.vsCMElementFunction) ' ソースコード情報の取得
If IsNothing(objCodeElement) = False Then
If objCodeElement.Kind = vsCMElement.vsCMElementFunction Then
' 関数の場合.
Dim codeFun As CodeFunction = objCodeElement
strCom = "/**" + vbCrLf
strCom = strCom + " * " + codeFun.Name + vbCrLf
strCom = strCom + "* " + vbCrLf
Dim j As Integer
For j = 1 To codeFun.Parameters.Count
Dim codeParam As CodeParameter
codeParam = codeFun.Parameters.Item(j)
strCom = strCom + "* @param[in/out]" + vbTab + codeParam.Type.AsString + vbTab + codeParam.Name + vbCrLf
Next j
If codeFun.Parameters.Count > 1 Then
strCom = strCom + "* " + vbCrLf
End If
strCom = strCom + "* @return" + vbTab + codeFun.Type.AsString + vbCrLf
strCom = strCom + "* @note" + vbCrLf
strCom = strCom + "*/" + vbCrLf
sel.MoveToPoint(objCodeElement.StartPoint)
End If
End If
' class 名
objCodeElement = myFCM.CodeElementFromPoint(sel.ActivePoint, vsCMElement.vsCMElementClass) ' ソースコード情報の取得
If IsNothing(objCodeElement) = False Then
If objCodeElement.Kind = vsCMElement.vsCMElementClass Then
strCom = "/**" + vbCrLf
strCom = strCom + " * @class" + vbTab + objCodeElement.Name + vbCrLf
strCom = strCom + "* @brief" + vbCrLf
strCom = strCom + "*/" + vbCrLf
sel.MoveToPoint(objCodeElement.StartPoint)
End If
End If
' enum 名
objCodeElement = myFCM.CodeElementFromPoint(sel.ActivePoint, vsCMElement.vsCMElementEnum) ' ソースコード情報の取得
If IsNothing(objCodeElement) = False Then
If objCodeElement.Kind = vsCMElement.vsCMElementEnum Then
strCom = "/**" + vbCrLf
strCom = strCom + " * @enum" + vbTab + objCodeElement.Name + vbCrLf
strCom = strCom + "* @brief" + vbCrLf
strCom = strCom + "*/" + vbCrLf
sel.MoveToPoint(objCodeElement.StartPoint)
End If
End If
' struct
objCodeElement = myFCM.CodeElementFromPoint(sel.ActivePoint, vsCMElement.vsCMElementStruct) ' ソースコード情報の取得
If IsNothing(objCodeElement) = False Then
If objCodeElement.Kind = vsCMElement.vsCMElementStruct Then
Dim codeStruct As CodeStruct = objCodeElement
strCom = "/**" + vbCrLf
strCom = strCom + " * @struct" + vbTab + objCodeElement.Name + vbCrLf
strCom = strCom + "* @brief" + vbCrLf
strCom = strCom + "*/" + vbCrLf
sel.MoveToPoint(objCodeElement.StartPoint)
End If
End If
If Not strCom.Length = 0 Then
sel.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)
sel.LineUp(True)
sel.Text = strCom
End If
End Sub
End Module
DTEインターフェイスを経由することで、VisualStudioの操作がおこなえる。
http://msdn.microsoft.com/ja-jp/library/envdte.dte.aspx
##現在選択中のコードの要素を列挙
''' ソース ファイル内のコード要素または構成体を表します
Dim myFCM As FileCodeModel = DTE.ActiveDocument.ProjectItem.FileCodeModel
Dim objCodeElement As CodeElement
For Each objCodeElement In myFCM.CodeElements
MsgBox(objCodeElement.FullName & ":" & objCodeElement.Kind)
Next
CodeElement インターフェイス
http://msdn.microsoft.com/ja-jp/library/envdte.codeelement.aspx
kindを見ることで、Inculdeなのか、関数なのか、クラスなのか判断することができる。
##カーソルの座標とKindからコードの要素を取得
Dim myFCM As FileCodeModel = DTE.ActiveDocument.ProjectItem.FileCodeModel
Dim objCodeElement As CodeElement ' コード情報取得用オブジェクト
objCodeElement = myFCM.CodeElementFromPoint(sel.ActivePoint, vsCMElement.vsCMElementFunction) ' ソースコード情報の取得
この関数はカーソルの位置とKindの種類をもとにしてコード要素を取得する。
条件があわなければnullとなる。
##カーソルの位置を関数の先頭にあわせて文字を記述する
Dim sel As TextSelection = DTE.ActiveDocument.Selection
'コード要素の先頭に移動
sel.MoveToPoint(objCodeElement.StartPoint)
'一列目に移動
sel.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)
' 一行うえへ
sel.LineUp(True)
' 文字を記録
sel.Text = "XXXXXXXXXXXXXXX"
マクロの実行方法
1.ソースコードの任意の箇所を選択。
2.マクロエクスプローラの「CreateHeaderComment()」をダブルクリックする。
3.マクロが実行されると以下のようにDoxygenコメントが付与される。
ショートカットの登録
作成したマクロはショートカットキーに割り当てることができる。
1. [ツール] メニューの [オプション] をクリックして、[オプション] ダイアログ ボックスを表示する。
2.[環境] フォルダーの [キーボード] をクリックする。
3.[以下の文字列を含むコマンドを表示] ボックスにマクロ名を入力して絞りこみ、選択する。
4.[ショートカット キー] ボックスをクリックし、特定のキーの組み合わせ押し「割り当て」ボタンをクリックする
以降設定したキーの組み合わせで、指定のマクロが動作する。
方法: マクロを実行する
http://msdn.microsoft.com/ja-jp/library/vstudio/a0003t62%28v=vs.100%29.aspx
#応用
この記事でVisualStudioの自動化が行えることを説明した。
VisualStudioのマクロを使う例としては以下のようなことが考えられる。
・あるルールに従って、自動でコードを作成する。
・プロジェクトの設定を自動で行う
・プロジェクトエクスプローラーからファイルを選択してバージョン管理ソフトにコミットしたり、元に戻したりする。