ヒント ファイル

ヒント ファイルには C++ 参照データベース パーサーによってコードの領域がスキップされる原因となるマクロが含まれています。 Visual Studio C++ プロジェクトを開くと、パーサーによってプロジェクト内の各ソース ファイルのコードが分析され、すべての識別子に関する情報が含まれるデータベースが作成されます。 それらの情報はクラス ビュー ブラウザーやナビゲーション バーなどのコード参照機能をサポートするために、IDE によって使用されます。

C++ 参照データベース パーサーは、短時間で大量のコードを解析できるあいまいなパーサーです。 高速な理由の 1 つにコンテンツのブロックをスキップすることが挙げられます。 たとえば、関数の場所とパラメーターのみが記録され、そのコンテンツは無視されます。 一部のマクロはブロックの開始と終了の決定に使用するヒューリスティックの問題を引き起こす可能性があります。 この問題によって、コードの領域が正しく記録されなくなります。

スキップされるリージョンは複数の方法で明らかになります。

  • クラス ビューGo To\(移動先\)ナビゲーション バー で不足している型と関数

  • ナビゲーション バー で正しくないスコープ

  • 既に定義されている関数の [宣言/定義の作成] に対する修正候補

ヒント ファイルには、C/C++ マクロ定義と同じ構文を持つ、ユーザーがカスタマイズ可能なヒントが含まれています。 Visual C++ には、ほとんどのプロジェクトに対応する、組み込みのヒント ファイルが含まれています。 ただし、独自のヒント ファイルを作成して、自分のプロジェクトに特化したパーサーに改善することができます。

重要

ヒント ファイルを変更または追加する場合は、変更を反映するための追加の手順を実行する必要があります。

  • Visual Studio 2017 バージョン 15.6 より前のバージョン: すべての変更について、ソリューション内の .sdf ファイルおよび VC.db ファイルを削除します。
  • Visual Studio 2017 バージョン 15.6 以降: 新しいヒント ファイルを追加した後、ソリューションを閉じてから開き直します。

シナリオ

#define NOEXCEPT noexcept
void Function() NOEXCEPT
{
}

ヒント ファイルがないと、Functionクラス ビューGo To\(移動先\)、またはナビゲーション バーに表示されません。 このマクロ定義のヒント ファイルを追加すると、パーサーが NOEXCEPT マクロを理解して置き換え、関数を正しく解析できるようになります。

#define NOEXCEPT

中断を伴うマクロ

パーサーが中断するマクロのカテゴリは 2 つあります。

  • 関数を装飾するキーワードをカプセル化するマクロ

    #define NOEXCEPT noexcept
    #define STDMETHODCALLTYPE __stdcall
    

    この種類のマクロには、ヒント ファイルにマクロ名のみが必要です。

    #define NOEXCEPT
    #define STDMETHODCALLTYPE
    
  • 左右が一致しないブラケットが含まれているマクロ

    #define BEGIN {
    

    この種類のマクロには、ヒント ファイルにマクロ名とそのコンテンツの両方が必要です。

    #define BEGIN {
    

エディターのサポート

Visual Studio 2017 バージョン 15.8 以降には、中断を伴うマクロを識別するためのいくつかの機能があります。

  • パーサーによってスキップされた領域内のマクロが強調表示されます。

  • 強調表示されているマクロを含むヒント ファイルを作成するクイック アクションがあります。既にヒント ファイルがある場合には、そのヒント ファイルにマクロを追加します。

Highlighted Macro.

いずれかのクイック アクションを実行した後、パーサーは、ヒント ファイルによる影響を受けるファイルを再解析します。

既定では、問題のマクロは、修正候補として強調表示されます。 強調表示は、赤や緑の波線のようなわかりやすいものに変更できます。 [ツール]>[オプション]>[テキスト エディター]>[C/C++]>[ビュー][Code Squiggles]\(コードの波線\) セクションで、[Macros in Skipped Browsing Regions]\(スキップされた参照領域のマクロ\) を使用します。

Macros in Skipped Browsing Regions Option.

参照データベース エラーを表示

[プロジェクト]>[参照データベース エラーを表示] メニュー コマンドでは、解析に失敗したすべての領域が [エラー一覧] に表示されます。 このコマンドは、最初のヒント ファイルの作成を効率化するためのものです。 ただし、パーサーは、エラーの原因が中断を伴うマクロかどうかを通知しないため、各エラーを自分で評価する必要があります。 [参照データベース エラーを表示] コマンドを実行し、各エラーに移動して、影響を受けるファイルをエディターに読み込みます。 ファイルが読み込まれ、リージョン内に何らかのマクロがある場合には、それが強調表示されます。 これをヒント ファイルに追加するためのクイック アクションを呼び出すことができます。 ヒント ファイルの更新後、エラー一覧は自動的に更新されます。 また、ヒント ファイルを手動で変更している場合には、[ソリューションの再スキャン] コマンドを使用して更新をトリガーすることができます。

アーキテクチャ

論理ディレクトリではなく物理ディレクトリに関連するヒント ファイルが、ソリューション エクスプローラーに表示されます。 ヒント ファイルを有効にするためにヒント ファイルをプロジェクトに追加する必要はありません。 解析システムは、ソース ファイルを解析する場合にのみ、ヒント ファイルを使用します。

すべてのヒント ファイルには cpp.hint という名前が付けられます。 多くのディレクトリにヒント ファイルを含めることができますが、特定のディレクトリには 1 つのヒント ファイルしか含めることはできません。

プロジェクトは、0 個以上のヒント ファイルの影響を受けることがあります。 ヒント ファイルが存在しない場合、解析システムはエラー回復手法を使用して解読できないソース コードを無視します。 それ以外の場合は、解析システムは次の方法を使用してヒントを検索して収集します。

検索順序

解析システムでは、次の順序でヒント ファイルのディレクトリが検索されます。

  • Visual C++ のインストール パッケージが格納されているディレクトリ (vcpackages)。 このディレクトリには、頻繁に使用されるシステム ファイル (windows.h など) のシンボルを説明する組み込みのヒント ファイルが含まれます。 そのため、必要なヒントのほとんどがプロジェクトに自動的に継承されます。

  • ソース ファイルのルート ディレクトリからソース ファイル自体を含むディレクトリへのパス。 一般的な Visual Studio C++ プロジェクトでは、ルート ディレクトリには、ソリューションまたはプロジェクト ファイルが含まれます。

    この規則の例外は、ストップ ファイルがソース ファイルへのパスにある場合です。 ストップ ファイルは、cpp.stop という名前のファイルです。 ストップ ファイルは、検索順序のより詳細な制御を提供します。 解析システムは、ルート ディレクトリから開始するのではなく、ストップ ファイルを含むディレクトリからソース ファイルを含むディレクトリに検索します。 一般的なプロジェクトでは、ストップ ファイルは必要ありません。

ヒントの収集

ヒント ファイルには、0 個以上のヒントが含まれています。 ヒントは、C/C++ マクロと同じように定義または削除されます。 つまり、#define プリプロセッサ ディレクティブはヒントを作成または再定義し、#undef ディレクティブはヒントを削除します。

解析システムでは、前に説明した検索順序で各ヒント ファイルが開きます。 各ファイルのヒントをエフェクティブ ヒントに蓄積し、エフェクティブ ヒントを使用してコード内の識別子を解釈します。

解析システムは、次の規則を使用してヒントを蓄積します。

  • 新しいヒントでまだ定義されていない名前が指定されている場合、新しいヒントによってその名前がエフェクティブ ヒントに追加されます。

  • 新しいヒントで既に定義されている名前が指定されている場合、新しいヒントによって既存のヒントが再定義されます。

  • 新しいヒントが既存のエフェクティブ ヒントを指定する #undef ディレクティブの場合、新しいヒントによって既存のヒントが削除されます。

最初の規則は、エフェクティブ ヒントが以前に開かれたヒント ファイルから継承されたことを意味します。 最後の 2 つの規則は、検索の順序の後にあるヒントがそれより前のヒントをオーバーライドできることを意味します。 たとえば、ソース ファイルが格納されているディレクトリにヒント ファイルを作成すると、前のヒントをオーバーライドできます。

ヒントの収集方法については、「」のセクションを参照してください。

構文

ヒントは、マクロを作成および削除するプリプロセッサ ディレクティブと同じ構文を使用して作成および削除します。 実際、解析システムは C/C++ プリプロセッサを使用してヒントを評価します。 プリプロセッサ ディレクティブの詳細については、「#define ディレクティブ (C/C++)」と「#undef ディレクティブ (C/C++)」を参照してください。

特殊な構文要素は、@<@=、および @> の置換文字列だけです。 これらのヒント ファイル固有の置換文字列は、マップ マクロでのみ使用されます。 マップとは、データ、関数、またはイベントを他のデータ、関数、またはイベント ハンドラーに関連付ける一連のマクロです。 たとえば、MFC はマップを使用してメッセージ マップを作成し、ATL はマップを使用してオブジェクト マップを作成します。 ヒント ファイル固有の置換文字列は、マップの開始要素、中間要素、および終了要素を示します。 重要なのはマップ マクロの名前だけです。 そのため、各置換文字列は、マクロの実装を意図的に非表示にします。

ヒントは、次の構文を使用します。

構文 意味
#definehint-namereplacement-string

#definehint-name(parameter, ...)replacement-string
新しいヒントを定義または既存のヒントを再定義するプリプロセッサ ディレクティブ。 このディレクティブの後に、プリプロセッサはソース コード内で hint-name が出現するたび replacement-string と置き換えます。

2 番目の構文形式は、関数に似たヒントを定義します。 関数に似たヒントがソース コード内に出現すると、プリプロセッサは最初に replacement-string 内に parameter が出現するたびにソース コード内の対応する引数と置き換えてから、hint-namereplacement-string と置き換えます。
@< 一連のマップ要素の開始を示すヒント ファイル固有の replacement-string
@= 一連のマップ要素の開始を示すヒント ファイル固有の replacement-string。 1 つのマップで複数のマップ要素を持つことができます。
@> 一連のマップ要素の終了を示すヒント ファイル固有の replacement-string
#undefhint-name 既存のヒントを削除するプリプロセッサ ディレクティブ。 ヒントの名前は、hint-name 識別子によって提供されます。
//comment 単一行コメント。
/*comment*/ 複数行コメント。

次の例は、ヒント ファイルからヒントが蓄積される方法を示しています。 ストップ ファイルは、この例では使用されません。

図は、Visual Studio C++ プロジェクト内の物理ディレクトリの一部を示しています。 ヒント ファイルは、vcpackagesDebugA1、および A2 のディレクトリにあります。

ヒント ファイルのディレクトリ

Diagram showing the common and project specific hint file directories.

ディレクトリとヒント ファイルのコンテンツ

このリストは、ヒント ファイルを含むこのプロジェクト内のディレクトリと、これらのヒント ファイルのコンテンツを示しています。 リストに表示されているのは、vcpackages ディレクトリ ヒント ファイル内の多くのヒントの一部だけです。

  • vcpackages

    // vcpackages (partial list)
    #define _In_
    #define _In_opt_
    #define _In_z_
    #define _In_opt_z_
    #define _In_count_(size)
    
  • デバッグ

    // Debug
    #undef _In_
    #define OBRACE {
    #define CBRACE }
    #define RAISE_EXCEPTION(x) throw (x)
    #define START_NAMESPACE namespace MyProject {
    #define END_NAMESPACE }
    
  • A1

    // A1
    #define START_NAMESPACE namespace A1Namespace {
    
  • A2

    // A2
    #undef OBRACE
    #undef CBRACE
    

エフェクティブ ヒント

この表は、このプロジェクト内のソース ファイルのエフェクティブ ヒントを示しています。

  • ソース ファイル: A1_A2_B.cpp

  • エフェクティブ ヒント:

    // vcpackages (partial list)
    #define _In_opt_
    #define _In_z_
    #define _In_opt_z_
    #define _In_count_(size)
    // Debug...
    #define RAISE_EXCEPTION(x) throw (x)
    // A1
    #define START_NAMESPACE namespace A1Namespace {
    // ...Debug
    #define END_NAMESPACE }
    

次の注意事項は、上記のリストに適用されます。

  • エフェクティブ ヒントは、vcpackagesDebugA1、および A2 ディレクトリに格納されています。

  • Debug ヒント ファイル内の #undef ディレクティブにより、vcpackages ディレクトリ ヒント ファイル内の #define _In_ ヒントが削除されました。

  • A1 ディレクトリ内のヒント ファイルは START_NAMESPACE を再定義します。

  • A2 ディレクトリ内の #undef ヒントにより、Debug ディレクトリ ヒント ファイル内の OBRACECBRACE のヒントが削除されました。

関連項目

Visual Studio の C++ プロジェクトに対して作成されるファイルの種類
#define ディレクティブ (C/C++)
#undef ディレクティブ (C/C++)
SAL 注釈