このセクションはまだ作成中です!
以下の図は、Doxygenがソースファイルをどのように処理するかを示しています。
以下のセクションでは、上記のステップについて詳しく説明します。
プロジェクトの設定を制御する設定ファイルはパースされ、設定はsrc/config.h
にあるシングルトンクラスConfig
に保存されます。パーサー自体はflex
を使用して書かれており、src/config.l
で見つけることができます。このパーサーはDoxywizardによっても直接使用されるため、別のライブラリに配置されています。
各設定オプションには、String
、List
、Enum
、Int
、Bool
の5つの可能な型があります。これらのオプションの値は、グローバル関数Config_getXXX()
を通じて利用できます。ここでXXX
はオプションの型です。これらの関数の引数は、設定ファイルに表示されるオプションの名前を示す文字列です。例えば、Config_getBool(GENERATE_TESTLIST)
は、設定ファイルでテストリストが有効になっている場合にTRUE
となるブール値への参照を返します。
src/doxygen.cpp
にある関数readConfiguration()
は、コマンドラインオプションを読み込み、その後設定パーサーを呼び出します。
設定ファイルに記載されている入力ファイルは、(デフォルトで)Cプリプロセッサに供給されます(利用可能な場合は、ユーザー定義フィルターを介してパイプされた後)。
プリプロセッサの動作は、標準的なCプリプロセッサとは多少異なります。デフォルトではマクロ展開を行いませんが、すべてのマクロを展開するように設定できます。典型的な使用法は、ユーザーが指定したマクロのセットのみを展開することです。これは、たとえば関数パラメータの型にマクロ名が現れることを可能にするためです。
もう一つの違いは、プリプロセッサが#include
に遭遇したときにコードをパースするものの、実際にはインクルードしないことです({ ... }ブロック内で見つかった#include
を除く)。この標準からの逸脱の理由は、同じ関数/クラスの複数の定義がDoxygenのパーサーに供給されるのを防ぐためです。例えば、すべてのソースファイルが共通のヘッダーファイルをインクルードする場合、クラスや型の定義(およびそれらのドキュメント)は各翻訳単位に存在することになります。
プリプロセッサはflex
を使用して書かれており、src/pre.l
で見つけることができます。条件ブロック(#if
)の場合、定数式の評価が必要です。このため、yacc
ベースのパーサーが使用され、src/constexp.y
とsrc/constexp.l
で見つけることができます。
プリプロセッサはsrc/pre.h
で宣言されたpreprocessFile()
関数を使用して各ファイルに対して呼び出され、前処理された結果を文字バッファに追加します。文字バッファのフォーマットは次のとおりです。
0x06 file name 1 0x06 preprocessed contents of file 1 ... 0x06 file name n 0x06 preprocessed contents of file n
前処理された入力バッファは言語パーサーに供給されます。これはflex
を使用して大きな状態機械として実装されています。src/scanner.l
ファイルで見つけることができます。すべての言語(C/C++/Java/IDL)に対して1つのパーサーがあります。状態変数insideIDL
とinsideJava
は、言語固有の選択のために一部の場所で使用されます。
パーサーのタスクは、入力バッファをエントリのツリー(基本的には抽象構文ツリー)に変換することです。エントリはsrc/entry.h
で定義されており、緩やかに構造化された情報の塊です。最も重要なフィールドはsection
で、エントリに含まれる情報の種類を指定します。
将来のバージョンでの改善点
このステップは、抽出されたクラス、ファイル、名前空間、変数、関数、パッケージ、ページ、グループの辞書を構築する多くの小さなステップで構成されています。辞書を構築するだけでなく、このステップでは抽出されたエンティティ間の関係(継承関係など)も計算されます。
各ステップにはsrc/doxygen.cpp
で定義された関数があり、言語パース中に構築されたエントリのツリーに対して操作を行います。詳細については、parseInput()
の「情報の収集」部分を参照してください。
このステップの結果は、src/doxygen.h
で定義されているDoxygenの「名前空間」で見つけることができる多数の辞書です。これらの辞書のほとんどの要素は、クラスDefinition
から派生しています。例えば、クラスMemberDef
はメンバーに関するすべての情報を保持します。このようなクラスのインスタンスは、ファイル(クラスFileDef
)、クラス(クラスClassDef
)、名前空間(クラスNamespaceDef
)、グループ(クラスGroupDef
)、またはJavaパッケージ(クラスPackageDef
)の一部になることができます。
設定ファイルでタグファイルが指定されている場合、これらはsrc/tagreader.cpp
にあるSAXベースのXMLパーサーによってパースされます。タグファイルのパース結果は、エントリツリーへのEntry
オブジェクトの挿入です。Entry::tagInfo
フィールドは、エントリを外部としてマークするために使用され、タグファイルに関する情報を保持します。
特殊なコメントブロックは、それらがドキュメント化するエンティティ内に文字列として保存されます。概要記述用の文字列と詳細記述用の文字列があります。ドキュメンテーションパーサーはこれらの文字列を読み込み、その中に見つかるコマンドを実行します(これはドキュメンテーションのパースにおける第2パスです)。結果は直接出力ジェネレーターに書き込まれます。
パーサーはC++で書かれており、src/docparser.cpp
で見つけることができます。パーサーが処理するトークンはsrc/doctokenizer.l
から供給されます。コメントブロック内で見つかったコードフラグメントはソースパーサーに渡されます。
ドキュメンテーションパーサーの主なエントリポイントは、src/docparser.h
で宣言されているvalidatingParseDoc()
です。特殊なコマンドを含むシンプルなテキストにはvalidatingParseText()
が使用されます。
ソースブラウジングが有効になっている場合、またはドキュメンテーション内にコードフラグメントが見つかった場合、ソースパーサーが呼び出されます。
コードパーサーは、パースしたソースコードとドキュメント化されたエンティティを相互参照しようとします。また、ソースの構文ハイライトも行います。出力は直接出力ジェネレーターに書き込まれます。
コードパーサーの主なエントリポイントは、src/code.h
で宣言されているparseCode()
です。
データが収集され相互参照された後、Doxygenは様々な形式で出力を生成します。これには抽象クラスOutputGenerator
が提供するメソッドを使用します。複数の形式で一度に出力を生成するために、代わりにOutputList
のメソッドが呼び出されます。このクラスは具体的な出力ジェネレーターのリストを保持し、呼び出された各メソッドはリスト内のすべてのジェネレーターに委譲されます。
各具体的な出力ジェネレーターへの出力にわずかな差異を許容するため、特定のジェネレーターを一時的に無効にすることが可能です。OutputListクラスには、これのための様々なdisable()
およびenable()
メソッドが含まれています。OutputList::pushGeneratorState()
およびOutputList::popGeneratorState()
メソッドは、有効/無効な出力ジェネレーターのセットをスタックに一時的に保存するために使用されます。
XMLは収集されたデータ構造から直接生成されます。将来的にはXMLが中間言語(IL)として使用される予定です。出力ジェネレーターはその後、このILを開始点として特定の出力形式を生成します。ILを持つ利点は、様々な言語で書かれた様々な独立して開発されたツールがXML出力から情報を抽出できることです。可能なツールは次のとおりです。
Doxygenは多くのflex
コードを使用しているため、flex
がどのように機能するか(これについてはman
ページを読むべきです)、およびflex
が何らかの入力をパースしているときに何をしているのかを理解することが重要です。幸いなことに、flex
を-dオプションで使用すると、どのルールが一致したかが出力されます。これにより、特定の入力フラグメントで何が起こっているかを追跡することが非常に簡単になります。
特定のflex
ファイルのデバッグ情報を切り替えやすくするために、Makefile
の正しい行から-dを自動的に追加または削除する以下のperl
スクリプトを作成しました。
#!/usr/bin/perl $file = shift @ARGV; print "Toggle debugging mode for $file\n"; if (!-e "../src/${file}.l") { print STDERR "Error: file ../src/${file}.l does not exist!\n"; exit 1; } system("touch ../src/${file}.l"); unless (rename "src/CMakeFiles/doxymain.dir/build.make","src/CMakeFiles/doxymain.dir/build.make.old") { print STDERR "Error: cannot rename src/CMakeFiles/doxymain.dir/build.make!\n"; exit 1; } if (open(F,"<src/CMakeFiles/doxymain.dir/build.make.old")) { unless (open(G,">src/CMakeFiles/doxymain.dir/build.make")) { print STDERR "Error: opening file build.make for writing\n"; exit 1; } print "Processing build.make...\n"; while (<F>) { if ( s/flex \$\(LEX_FLAGS\) -d(.*) ${file}.l/flex \$(LEX_FLAGS)$1 ${file}.l/ ) { print "Disabling debug info for $file\n"; } elsif ( s/flex \$\(LEX_FLAGS\)(.*) ${file}.l$/flex \$(LEX_FLAGS) -d$1 ${file}.l/ ) { print "Enabling debug info for $file.l\n"; } print G "$_"; } close F; unlink "src/CMakeFiles/doxymain.dir/build.make.old"; } else { print STDERR "Warning file src/CMakeFiles/doxymain.dir/build.make does not exist!\n"; } # touch the file $now = time; utime $now, $now, $file;
flex
コードからルールの一致/デバッグ情報を取得する別の方法は、make
でLEX_FLAGS
を設定することです(make LEX_FLAGS=-d)。
デフォルトでは、Doxygenのデバッグバージョン(つまり、CMake
設定-DCMAKE_BUILD_TYPE=Debugで作成された実行可能ファイル)には、すべてのflex codefileのflex
デバッグ情報が自動的に含まれます。
Doxygenを-d lexで実行すると、どのflex codefileが使用されているかに関する情報が得られます。flexデバッグオプションでコンパイルされたflexパーサーの情報を表示するには、Doxygenを実行するときに-d lex:<flex codefile>を指定する必要があります。
lexパースに関する情報はstderrに出力され、他のデバッグ出力は-d stderrを使用しない限りデフォルトでstdoutに出力されることに注意してください。
Doxygenには、一部のコードの整合性をテストするための少数のテストセットがあります。テストは、コマンドmake testsを使用して実行できます。1つまたは少数のテストのみが必要な場合は、テスト実行時に変数TEST_FLAGS
を設定できます。例えば、make TEST_FLAGS="--id 5" tests、または複数のテストの場合はmake TEST_FLAGS="--id 5 --id 7" testsです。すべての可能性については、コマンドmake TEST_FLAGS="--help" testsを実行してください。TEST_FLAGSを環境変数として指定することも可能です(Visual Studioプロジェクト経由でのテストにも機能します)。例えば、setenv TEST_FLAGS "--id 5 --id 7"としてからmake testsを実行します。
例えばフォーラムを通じて、標準のDoxygen設定ファイルの設定とは異なる設定を伝える必要がある場合、-xオプションと設定ファイルの名前(デフォルトはDoxyfile)を指定してDoxygenコマンドを実行できます。出力は、デフォルトではない設定のリスト(Doxyfile形式)になります。あるいは、-xオプションと同じですが、環境変数やCMake
型置換変数を置換しない-x_noenvも可能です。
インデックスに戻る。