DoxyCommentでC++でもコメントを自動生成
JavaにはJavadocというコメントから自動的にドキュメントを生成する標準的な機能がありますが、Visual C++には標準ツールはありません。
お勧めなのはdoxygenというドキュメント生成ツールです。ソースファイルのコメントから文書を抜き出し、HTMLをはじめとするさまざまなフォーマットのドキュメントを生成することができます。
DoxygenはQtスタイル及びJavaDocスタイルのコメン トを認識してくれます。
私はお仕事ではJavaプログラマーなのでJavaDocスタイルのコメントに慣れていますのでJavaDoc形式のコメントは助かります。
さて、今回インストールするDoxyCommentですが、そのdoxygen形式のコメントを自動生成してくれるツールです。Visual Studioにアドイン(add-in)して使用します。
別にDoxygenでドキュメント作らないよーという場合でも、ソースにコメントは入れると思います。コメント作成の作業をちょっと楽にしてくれるお勧め便利ツールです。
インストール
プロジェクトのサイト
http://sourceforge.net/projects/doxycomment/
よりインストーラをダウンロードしてインストールしてみました。
Visual Studio2005 用と2008用があります。ご自分の環境にあったファイルをダウンロードしてください。
※現在2008用はベータバージョンのようです。
Visual Studio2005の場合
ダウンロードした、doxycomment_0_4_3_setup.msi をインストールします。
Visual Studioを起動すると画像のようなツールバーがでます。
Add Code Commentをクリックすると、コメントが生成されます。
カスタムコメントプロバイダで自分好みのコメントを生成する
さて、DoxygenのデフォルトではQt形式のタグになっており、JavaDoc形式のコメントになりません。[ツール]-[オプション]のDoxyCommentで設定すればコメントブロックだけはJavaDoc形式にできますが、\authorや\versionなどのコマンドの接頭辞は\(バックスラッシュ(¥マーク))のままです。ここはやはり@で記述してほしいところです。
DoxyCommentにはコメントプロバイダというDLLを作成することで、コメントの生成を自分好みにカスタマイズすることができます。
これを使ってJavaDoc風のコメントにしてみましょう。
[ファイル]-[新しいプロジェクト]-[Visual C#]
より、クラスライブラリを選択します。
プロジェクト名:JavaDocComment
OKを押します。
参照設定に
EnvDTE(.NETライブラリ)
Microsoft.VisualStudio.VCCodeModel(.NETライブラリ)
DoxyComment(デフォルトではC:\Program Files\SourceForge.net\DoxyComment add-in for Visual Studio 2005\DoxyComment.dllにあります。)
を追加します。
DoxyComment.ICommentProviderインターフェースを実装する新しいパブリッククラスを作成してください。
ICommentProviderインターフェースのすべての方法を実装してください。
DoxyCommentのインストールフォルダにTest Providerフォルダがあります。これを参考にすると良いでしょう。
C:\Program Files\SourceForge.net\DoxyComment add-in for Visual Studio 2005\Test Provider
using System;
using System.Collections;
using DoxyComment;
using EnvDTE;
using System.ComponentModel;
using Microsoft.VisualStudio.VCCodeModel;
namespace JavaDocComment
{
[CommentProviderFriendlyName("JavaDocComment")]
public class JavaDocComment : DoxyComment.ICommentProvider
{
[CommentProviderProperty]
private string firstLineTag = "/**";
[CommentProviderProperty]
private string normalLineTag = " * ";
[CommentProviderProperty]
private string lastLineTag = " */";
[CommentProviderProperty]
private string commandPrefix = "@";
public JavaDocComment()
{
}
[Category("コメントブロック概観"),
Description("コメントブロックの先頭行の接頭辞.")]
public string FirstLineTag
{
get
{
return firstLineTag;
}
set
{
firstLineTag = value;
}
}
[Category("コメントブロック概観"),
Description("コメントブロックの行の接頭辞.")]
public string NormalLineTag
{
get
{
return normalLineTag;
}
set
{
normalLineTag = value;
}
}
[Category("コメントブロック概観"),
Description("コメントブロックの最終行の接頭辞.")]
public string LastLineTag
{
get
{
return lastLineTag;
}
set
{
lastLineTag = value;
}
}
[Category("コマンド接頭辞"),
Description("コマンドの接頭辞です。\\や@を指定します.")]
public string CommandPrefix
{
get
{
return commandPrefix;
}
set
{
commandPrefix = value;
}
}
#region ICommentProvider implementation
private ArrayList CreateCommentHeader(VCCodeElement codeElem)
{
ArrayList rv = new ArrayList();
if (FirstLineTag.Length > 0)
{
rv.Add(FirstLineTag);
}
rv.Add(NormalLineTag + CommandPrefix +"brief ここに" + codeElem.Name + " の要約を記載.");
rv.Add(NormalLineTag);
return rv;
}
private void AppendCommentFooter(VCCodeElement codeElem, ArrayList buffer)
{
buffer.Add(NormalLineTag + "ここに " + codeElem.Name + " の詳細を記載.");
buffer.Add(NormalLineTag);
buffer.Add(NormalLineTag + CommandPrefix +"remarks ここに" + codeElem.Name + " の備考を記載.");
buffer.Add(NormalLineTag);
buffer.Add(NormalLineTag + CommandPrefix +"see ");
// Does the comment provider require a last line tag?
if (LastLineTag.Length > 0)
{
buffer.Add(LastLineTag);
}
}
public string[] CreateFileComment(Document doc)
{
ArrayList rv = new ArrayList();
DateTime now = DateTime.Now;
// Begin tag?
if (FirstLineTag.Length > 0)
{
rv.Add(FirstLineTag);
}
rv.Add(NormalLineTag + CommandPrefix +"file " + doc.Name);
rv.Add(NormalLineTag + CommandPrefix +"brief ");
rv.Add(NormalLineTag);
rv.Add(NormalLineTag + CommandPrefix +"author ");
rv.Add(NormalLineTag + CommandPrefix +"date " + now.ToString("yyyy/MM/dd"));
rv.Add(NormalLineTag + CommandPrefix +"version ");
// End tag?
if (LastLineTag.Length > 0)
{
rv.Add(LastLineTag);
}
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateTypeDefComment(VCCodeTypedef codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateUnionComment(VCCodeUnion codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateMacroComment(VCCodeMacro codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
if ((codeElem.Parameters.Count > 0))
{
foreach (VCCodeParameter curParam in codeElem.Parameters)
{
rv.Add(NormalLineTag + CommandPrefix +"param " + curParam.Name
+ " パラメータ " + curParam.Name + " の説明を記載.");
rv.Add(NormalLineTag);
}
}
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateStructComment(VCCodeStruct codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateNamespaceComment(VCCodeNamespace codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateFunctionComment(VCCodeFunction codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
// Create /param sections for each parameters in the function
if (codeElem.Parameters.Count > 0)
{
foreach (VCCodeParameter curParam in codeElem.Parameters)
{
rv.Add(NormalLineTag + CommandPrefix +"param " + curParam.Name
+ " パラメータ " + curParam.Name + " の説明を記載.");
rv.Add(NormalLineTag);
}
}
// Create /returns section
if ((codeElem.TypeString.Length > 0) &
(codeElem.TypeString.ToLower() != "void"))
{
rv.Add(NormalLineTag + CommandPrefix +"returns "
+ "ここに戻り値の説明を記載.");
rv.Add(NormalLineTag);
}
// Create /throws section
rv.Add(NormalLineTag + CommandPrefix +"throws <exception class>");
rv.Add(NormalLineTag + " この例外を投げるための基準の説明を記載.");
rv.Add(NormalLineTag);
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateEnumValueComment(VCCodeVariable codeElem)
{
ArrayList rv = new ArrayList();
if (FirstLineTag.Length > 0)
{
rv.Add(FirstLineTag);
}
rv.Add(NormalLineTag + CommandPrefix +"brief ここに " + codeElem.Name + " の要約を記載.");
// End tag required?
if (LastLineTag.Length > 0)
{
rv.Add(LastLineTag);
}
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateEnumComment(VCCodeEnum codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateVariableComment(VCCodeVariable codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateClassComment(VCCodeClass codeElem)
{
ArrayList rv;
// Header
rv = CreateCommentHeader((VCCodeElement)codeElem);
// Template parameters?
if ((codeElem.IsTemplate))
{
foreach (VCCodeParameter curTemplateParam in codeElem.Templatizations)
{
string typeStr;
if ((curTemplateParam.Name.Length != 0))
{
typeStr = curTemplateParam.Name;
}
else
{
int typeIdx;
typeIdx = curTemplateParam.TypeString.LastIndexOf(" ");
typeStr = curTemplateParam.TypeString.Substring(typeIdx + 1);
}
rv.Add(NormalLineTag + CommandPrefix +"param " + typeStr);
rv.Add(NormalLineTag + "パラメータ " + typeStr + " の説明を記載.");
rv.Add(NormalLineTag);
}
}
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
using System;
using System.Collections;
using DoxyComment;
using EnvDTE;
using System.ComponentModel;
using Microsoft.VisualStudio.VCCodeModel;
namespace JavaDocComment
{
[CommentProviderFriendlyName("JavaDocComment")]
public class JavaDocComment : DoxyComment.ICommentProvider
{
[CommentProviderProperty]
private string firstLineTag = "/**";
[CommentProviderProperty]
private string normalLineTag = " * ";
[CommentProviderProperty]
private string lastLineTag = " */";
[CommentProviderProperty]
private string commandPrefix = "@";
[CommentProviderProperty]
private string author ="";
public JavaDocComment()
{
}
[Category("コメントブロック概観"),
Description("コメントブロックの先頭行の接頭辞です.")]
public string FirstLineTag
{
get
{
return firstLineTag;
}
set
{
firstLineTag = value;
}
}
[Category("コメントブロック概観"),
Description("コメントブロックの行の接頭辞です.")]
public string NormalLineTag
{
get
{
return normalLineTag;
}
set
{
normalLineTag = value;
}
}
[Category("コメントブロック概観"),
Description("コメントブロックの最終行の接頭辞です.")]
public string LastLineTag
{
get
{
return lastLineTag;
}
set
{
lastLineTag = value;
}
}
[Category("コマンド接頭辞"),
Description("コマンドの接頭辞です。\\や@を指定します.")]
public string CommandPrefix
{
get
{
return commandPrefix;
}
set
{
commandPrefix = value;
}
}
[Category("制作者"),
Description("制作者を指定します.")]
public string Author
{
get
{
return author;
}
set
{
author = value;
}
}
#region ICommentProvider implementation
private ArrayList CreateCommentHeader(VCCodeElement codeElem)
{
ArrayList rv = new ArrayList();
if (FirstLineTag.Length > 0)
{
rv.Add(FirstLineTag);
}
rv.Add(NormalLineTag + "ここに" + codeElem.Name + "の要約を記載.");
rv.Add(NormalLineTag + "ここに" + codeElem.Name + "の詳細を記載.");
return rv;
}
private void AppendCommentFooter(VCCodeElement codeElem, ArrayList buffer)
{
buffer.Add(NormalLineTag + CommandPrefix +"remarks ここに" + codeElem.Name + "の備考を記載.");
// Does the comment provider require a last line tag?
if (LastLineTag.Length > 0)
{
buffer.Add(LastLineTag);
}
}
public string[] CreateFileComment(Document doc)
{
ArrayList rv = new ArrayList();
DateTime now = DateTime.Now;
// Begin tag?
if (FirstLineTag.Length > 0)
{
rv.Add(FirstLineTag);
}
rv.Add(NormalLineTag + "ここに" + doc.Name + "の概要を記載.");
rv.Add(NormalLineTag + CommandPrefix + "file " + doc.Name);
rv.Add(NormalLineTag + CommandPrefix + "author " + Author);
rv.Add(NormalLineTag + CommandPrefix + "date " + now.ToString("yyyy/MM/dd"));
rv.Add(NormalLineTag + CommandPrefix + "version ");
// End tag?
if (LastLineTag.Length > 0)
{
rv.Add(LastLineTag);
}
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateTypeDefComment(VCCodeTypedef codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateUnionComment(VCCodeUnion codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateMacroComment(VCCodeMacro codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
if ((codeElem.Parameters.Count > 0))
{
foreach (VCCodeParameter curParam in codeElem.Parameters)
{
rv.Add(NormalLineTag + CommandPrefix +"param " + curParam.Name
+ " パラメータ" + curParam.Name + "の説明を記載.");
}
}
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateStructComment(VCCodeStruct codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateNamespaceComment(VCCodeNamespace codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateFunctionComment(VCCodeFunction codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
// Create /param sections for each parameters in the function
if (codeElem.Parameters.Count > 0)
{
foreach (VCCodeParameter curParam in codeElem.Parameters)
{
rv.Add(NormalLineTag + CommandPrefix +"param " + curParam.Name
+ " パラメータ" + curParam.Name + "の説明を記載.");
}
}
rv.Add(NormalLineTag + CommandPrefix + "see ");
// Create /returns section
if ((codeElem.TypeString.Length > 0) &
(codeElem.TypeString.ToLower() != "void"))
{
rv.Add(NormalLineTag + CommandPrefix +"return "
+ "ここに戻り値の説明を記載.");
}
// Create /throws section
rv.Add(NormalLineTag + CommandPrefix +"throws <exception class> この例外を投げるための基準の説明を記載.");
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateEnumValueComment(VCCodeVariable codeElem)
{
ArrayList rv = new ArrayList();
if (FirstLineTag.Length > 0)
{
rv.Add(FirstLineTag);
}
rv.Add(NormalLineTag + CommandPrefix +"brief ここに " + codeElem.Name + " の要約を記載.");
// End tag required?
if (LastLineTag.Length > 0)
{
rv.Add(LastLineTag);
}
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateEnumComment(VCCodeEnum codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateVariableComment(VCCodeVariable codeElem)
{
ArrayList rv;
rv = CreateCommentHeader((VCCodeElement)codeElem);
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
public string[] CreateClassComment(VCCodeClass codeElem)
{
ArrayList rv;
// Header
rv = CreateCommentHeader((VCCodeElement)codeElem);
// Template parameters?
if ((codeElem.IsTemplate))
{
foreach (VCCodeParameter curTemplateParam in codeElem.Templatizations)
{
string typeStr;
if ((curTemplateParam.Name.Length != 0))
{
typeStr = curTemplateParam.Name;
}
else
{
int typeIdx;
typeIdx = curTemplateParam.TypeString.LastIndexOf(" ");
typeStr = curTemplateParam.TypeString.Substring(typeIdx + 1);
}
rv.Add(NormalLineTag + CommandPrefix +"param " + typeStr + " パラメータ" + typeStr + "の説明を記載.");
}
}
AppendCommentFooter((VCCodeElement)codeElem, rv);
return (string[])rv.ToArray(typeof(string));
}
#endregion
}
}
#endregion
}
}
[ビルド]-[JavaDocCommentのビルド]を選択してDLLを作成します。
JavaDocComment.dll
が生成されるので、これをあなたがDoxyCommentをインストールしたフォルダに「Custom Providers」という名のサブフォルダを作ってそこへコピーしてください。
デフォルトのインストール先であれば
C:\Program Files\SourceForge.net\DoxyComment add-in for Visual Studio 2005\Custom Providers
です。
Visual Studio 2005を再度起動すればカスタムコメントプロバイダがロードされます。
JavaDocCommentプロバイダを使用するように設定します。
[ツール]-[オプション]よりオプションウィンドウを開き、ツリー内のDoxyComment-Generalを選択します。
Active comment provider:JavaDocComment を設定します。
次にDoxyComment-Providerを選択します。
Comment provider:JavaDocComment を選択し、コマンド接頭辞やコメントブロック概観を好みのスタイルに設定してください。
さらにカスタマイズすれば、自分好みのコメントを自動生成できて、便利に使えるでしょう
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | - | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | - | - | - | - | - | - |