Hinweisdateien
Makros führen normalerweise dazu, dass bestimmte Codebereiche vom Parser für die Datenbank zum Durchsuchen von C++-Code übersprungen werden. Dies wird vermieden, indem Makros einer Hinweisdatei hinzugefügt werden. Wenn Sie ein Visual Studio C++-Projekt öffnen, analysiert der Parser den Code in jeder Quelldatei des Projekts und erstellt eine Datenbank mit Informationen zu jedem Bezeichner. Die IDE verwendet diese Informationen, um Features zum Durchsuchen von Code wie die Klassenansicht und die Navigationsleiste zu unterstützen.
Der Parser für die Datenbank zum Durchsuchen von C++-Code ist ein Fuzzyparser, der große Mengen an Code in kurzer Zeit analysieren kann. Ein Grund dafür ist, dass die Inhalte von Blöcken übersprungen werden. Beispielsweise wird nur erfasst, wo sich eine Funktion befindet und welche Parameter für diese vorhanden sind. Der Inhalt der Funktion wird hingegen ignoriert. Bestimmte Makros können zu Problemen mit den Heuristiken führen, die zur Ermittlung des Anfangs und Endes eines Blocks eingesetzt werden. Dadurch werden bestimmte Codebereiche nicht richtig erfasst.
Die übersprungenen Bereiche können unterschiedliche Auswirkungen haben:
Typen und Funktionen fehlen in der Klassenansicht, im Fenster Gehe zu und in der Navigationsleiste.
In der Navigationsleiste werden falsche Bereiche angezeigt.
Für bereits definierte Funktionen werden Deklaration/Definition erstellen-Vorschläge angezeigt.
Eine Hinweisdatei enthält vom Benutzer anpassbare Hinweise, die die gleiche Syntax wie die C/C++-Makrodefinitionen aufweisen. Visual C++ verfügt über eine integrierte Hinweisdatei, die für die meisten Projekte ausreicht. Sie können allerdings eigene Hinweisdateien erstellen, um die Leistung des Parsers speziell für Ihr Projekt zu verbessern.
Wichtig
Wenn Sie eine Hinweisdatei ändern oder hinzufügen, sind zusätzliche Schritte erforderlich, damit die Änderungen wirksam werden:
- In Versionen vor Visual Studio 2017, Version 15.6: Löschen Sie die SDF-Datei und/oder VC.db Datei in der Lösung für alle Änderungen.
- In Visual Studio 2017, Version 15.6 und höher: Schließen Sie die Lösung, und öffnen Sie sie erneut, nachdem Sie neue Hinweisdateien hinzugefügt haben.
Szenario
#define NOEXCEPT noexcept
void Function() NOEXCEPT
{
}
Ohne eine Hinweisdatei wird Function
nicht in der Klassenansicht, im Fenster Gehe zu oder in der Navigationsleiste angezeigt. Nachdem Sie eine Hinweisdatei mit dieser Makrodefinition hinzugefügt haben, ersetzt der Parser das NOEXCEPT
-Makro und analysiert die Funktion fehlerfrei:
#define NOEXCEPT
Störende Makros
Es gibt zwei Kategorien von Makros, die die Funktionsweise des Parsers stören:
Makros, die Schlüsselwörter einer Funktion kapseln
#define NOEXCEPT noexcept #define STDMETHODCALLTYPE __stdcall
Für diese Makros muss nur der Name des Makros in der Hinweisdatei angegeben werden:
#define NOEXCEPT #define STDMETHODCALLTYPE
Makros, die eine ungleiche Anzahl öffnender und geschlossener Klammern enthalten
#define BEGIN {
Für diese Makros müssen sowohl der Name des Makros als auch der zugehörige Inhalt in der Hinweisdatei angegeben werden:
#define BEGIN {
Editor-Unterstützung
Ab Version 15.8 von Visual Studio 2017 gibt es verschiedene Features, mit denen sich störende Makros identifizieren lassen:
Makros, die sich innerhalb von Bereichen befinden und vom Parser übersprungen werden, werden hervorgehoben.
Mit einer Schnellaktion kann eine Hinweisdatei erstellt werden, die das hervorgehobene Makro einschließt. Wenn bereits eine Hinweisdatei vorhanden ist, kann ihr mit einer anderen Schnellaktion das Makro hinzugefügt werden.
Nach dem Ausführen einer der beiden Schnellaktionen analysiert der Parser die Dateien neu, die von der Hinweisdatei betroffen sind.
Standardmäßig wird das störende Makro als Vorschlag hervorgehoben. Die Hervorhebung kann beispielsweise durch eine grüne oder rote Wellenlinie so angepasst werden, dass sie deutlicher zu sehen ist. Verwenden Sie dazu unter Extras>Optionen>Text-Editor>C/C++>Ansicht im Abschnitt Wellenlinien im Code die Option Makros in übersprungenen Suchbereichen.
Anzeigen von Fehlern beim Durchsuchen der Datenbank
Über den Menübefehl Projekt>Fehler beim Durchsuchen der Datenbank anzeigen werden in der Fehlerliste alle Bereiche angezeigt, die nicht analysiert werden konnten. Der Befehl dient dazu, die Erstellung der Hinweisdatei zu optimieren. Vom Parser kann jedoch nicht ermittelt werden, ob die Ursache des Fehlers ein störendes Makro ist. Sie müssen daher jeden Fehler einzeln analysieren. Führen Sie den Befehl Fehler beim Durchsuchen der Datenbank anzeigen aus, und navigieren Sie zu jedem Fehler, um die betroffene Datei im Editor zu laden. Wenn sich Makros im Bereich befinden, werden sie hervorgehoben. Sie können diese mit Schnellaktionen einer Hinweisdatei hinzufügen. Nach einem Update der Hinweisdatei wird die Fehlerliste automatisch aktualisiert. Wenn Sie die Hinweisdatei manuell ändern, können Sie mit dem Befehl Projektmappe neu prüfen ein Update auslösen.
Aufbau
Hinweisdateien beziehen sich auf physische Verzeichnisse, nicht auf die lokalen Verzeichnisse, die im Projektmappen-Explorer angezeigt werden. Sie müssen eine Hinweisdatei nicht Ihrem Projekt hinzufügen, damit diese wirksam ist. Das Analysesystem verwendet Hinweisdateien nur, wenn es Quelldateien analysiert.
Jede Hinweisdatei heißt cpp.hint. Viele Verzeichnisse können eine Hinweisdatei enthalten, es kann jedoch nur eine Hinweisdatei pro Verzeichnis vorhanden sein.
Null oder mehr Hinweisdateien können Auswirkungen auf Ihr Projekt haben. Wenn keine Hinweisdateien vorhanden sind, verwendet das Analysesystem Wiederherstellungstechniken für Fehler, um den unlesbaren Quellcode zu ignorieren. Andernfalls verwendet das Analysesystem folgende Strategie, um Hinweise zu suchen und zu sammeln.
Suchreihenfolge
Das Analysesystem durchsucht Verzeichnisse in folgender Reihenfolge nach Hinweisdateien.
Das Verzeichnis, das das Installationspaket für Visual C++ enthält (vcpackages). Dieses Verzeichnis enthält eine integrierte Hinweisdatei, die Symbole in häufig verwendeten Systemdateien (z.B. windows.h) beschreibt. Deshalb erbt Ihr Projekt automatisch die meisten erforderlichen Hinweise.
Der Pfad vom Stammverzeichnis einer Quelldatei zu dem Verzeichnis, das die Quelldatei enthält. In einem typischen Visual Studio C++-Projekt enthält das Stammverzeichnis die Projektmappen- oder die Projektdatei.
Eine Ausnahme besteht darin, wenn sich eine STOP-Datei im Pfad zur Quelldatei befindet. Eine Stoppdatei ist eine Datei mit dem Namen cpp.stop. Sie stellt eine zusätzliche Möglichkeit zum Einstellen der Suchreihenfolge dar. Statt im Stammverzeichnis zu beginnen, sucht das Analysesystem von dem Verzeichnis aus, das die STOP-Datei enthält, und beendet die Suche in dem Verzeichnis, das die Quelldatei enthält. In einem typischen Projekt benötigen Sie keine Stoppdatei.
Sammeln von Hinweisen
Eine Hinweisdatei enthält null oder mehr Hinweise. Ein Hinweis wird genau wie ein C/C++-Makro definiert oder gelöscht. Das bedeutet, dass die Präprozessordirektive #define
einen Hinweis erstellt oder neu definiert und die Direktive #undef
einen Hinweis löscht.
Das Analysesystem öffnet jede Hinweisdatei in der zuvor beschriebenen Suchreihenfolge. Es fasst die Hinweise aller Dateien in einer Menge effektiver Hinweise zusammen. Diese werden dann zur Auswertung der Bezeichner im Code verwendet.
Das Analysesystem verwendet folgende Regeln, um Hinweise zu sammeln:
Wenn der neue Hinweis einen Namen festlegt, der noch nicht definiert ist, fügt der neue Hinweis diesen den effektiven Hinweisen hinzu.
Wenn der neue Hinweis einen Namen festlegt, der bereits definiert ist, definiert der neue Hinweis den vorhandenen Hinweisen neu.
Wenn der neue Hinweis eine
#undef
-Direktive ist, die einen vorhandenen effektiven Hinweis angibt, löscht der neue Hinweis den vorhandenen Hinweis.
Die erste Regel bedeutet, dass effektive Hinweise von zuvor geöffneten Hinweisdateien geerbt werden. Durch die letzten beiden Regeln wird festgelegt, dass Hinweise, die in der Suchreihenfolge eher am Ende stehen, vorherige Hinweise überschreiben können. Sie können beispielsweise alle vorherigen Hinweise überschreiben, wenn Sie eine Hinweisdatei in dem Verzeichnis erstellen, das eine Quelldatei enthält.
Im Abschnitt Beispiel finden Sie eine Abbildung, auf der die Erfassung von Hinweisen illustriert wird.
Syntax
Sie können Hinweise mit der gleichen Syntax erstellen und löschen, die in Präprozessoranweisungen zum Erstellen und Löschen von Makros verwendet wird. Tatsächlich verwendet das Analysesystem den C/C++-Präprozessor, um die Hinweise auszuwerten. Weitere Informationen zu den Präprozessordirektiven finden Sie unter #define Directive (C/C++) (#define-Direktive (C/C++)) und #undef Directive (C/C++) (#undef-Direktive (C/C++)).
Die einzigen ungewöhnlichen Syntaxelemente sind die Ersatzzeichenfolgen @<
, @=
und @>
. Diese Ersatzzeichenfolgen werden nur bei Hinweisdateien und ausschließlich für Zuordnungsmakros verwendet. Eine Zuordnung besteht aus mehreren Makros, die Daten, Funktionen oder Ereignisse mit anderen Daten, Funktionen oder Ereignishandlern in Verbindung bringen. MFC
verwendet beispielsweise Zuordnungen, um Meldungszuordnungen zu erstellen, und ATL
verwendet Zuordnungen, um Objektzuordnungen zu erstellen. Die für die Hinweisdateien spezifischen Ersatzzeichenfolgen geben die Start-, Zwischen- und Endelemente einer Zuordnung an. Nur der Name eines Zuordnungsmakros ist relevant. Deshalb blendet jede Ersatzzeichenfolge die Implementierung des Makros absichtlich aus.
Für Hinweise wird die folgende Syntax verwendet:
Syntax | Bedeutung |
---|---|
#define hint-name Ersetzungszeichenfolge#define hint-name ( parameter, ...) Ersetzungszeichenfolge |
Eine Präprozessordirektive, die einen neuen Hinweis definiert oder einen vorhandenen Hinweis neu definiert. Nach der Direktive ersetzt der Präprozessor jedes Vorkommen von Hinweisname im Quellcode mit Ersatzzeichenfolge. Durch das zweite Syntaxformat wird ein funktionsähnlicher Hinweis definiert. Wenn ein funktionsähnlicher Hinweis im Quellcode vorkommt, ersetzt der Präprozessor zunächst jedes Vorkommen von Parameter in Ersatzzeichenfolge mit dem entsprechenden Argument im Quellcode. Anschließend wird Hinweisname durch Ersatzzeichenfolge ersetzt. |
@< |
Eine für Hinweisdateien spezifische Ersatzzeichenfolge, die den Anfang von einer Reihe von Zuordnungselementen definiert. |
@= |
Eine für Hinweisdateien spezifische Ersatzzeichenfolge, die ein Zwischenzuordnungselement definiert. Eine Zuordnung kann mehrere Zuordnungselemente enthalten. |
@> |
Eine für Hinweisdateien spezifische Ersatzzeichenfolge, die das Ende von einer Reihe von Zuordnungselementen definiert. |
#undef hint-name |
Die Präprozessordirektive, die einen vorhandenen Hinweis löscht. Der Name des Hinweises wird durch den Bezeichner Hinweisname bereitgestellt. |
// Kommentar |
Ein einzeiliger Kommentar. |
/* Kommentar */ |
Ein mehrzeiliger Kommentar. |
Beispiel
Im folgenden Beispiel wird gezeigt, wie Hinweise aus Hinweisdateien gesammelt werden. Stoppdateien werden in diesem Beispiel nicht verwendet.
Die Abbildung stellt einige der physischen Verzeichnisse in einem Visual Studio C++-Projekt dar. Die Hinweisdateien befinden sich in den Verzeichnissen vcpackages
, Debug
, A1
und A2
.
Hinweisdateiverzeichnisse
Verzeichnisse und Hinweisdateiinhalte
Die folgende Liste enthält Projektverzeichnisse mit Hinweisdateien und deren zugehörige Inhalten. Es werden nur einige der vielen Hinweise in der Hinweisdatei des Verzeichnisses vcpackages
aufgeführt:
vcpackages
// vcpackages (partial list) #define _In_ #define _In_opt_ #define _In_z_ #define _In_opt_z_ #define _In_count_(size)
Debug
// 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
Effektive Hinweise
In der folgenden Tabelle werden die effektiven Hinweise für die Quelldateien in diesem Projekt aufgeführt:
Quelldatei: A1_A2_B.cpp
Effektive Hinweise:
// 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 }
Die folgenden Hinweise gelten für die vorangehende Liste:
Die effektiven Hinweise stammen aus den Verzeichnissen
vcpackages
,Debug
,A1
, undA2
.Die #undef-Direktive in der Hinweisdatei
Debug
hat den Hinweis#define _In_
aus der Verzeichnishinweisdateivcpackages
gelöscht.Die Hinweisdatei im Verzeichnis
A1
definiertSTART_NAMESPACE
neu.Der Hinweis
#undef
im VerzeichnisA2
hat die Hinweise fürOBRACE
undCBRACE
aus der VerzeichnishinweisdateiDebug
gelöscht.
Siehe auch
Für Visual Studio C++-Projekte erstellte Dateitypen
#define-Direktive (C/C++)
#undef-Direktive (C/C++)
SAL-Anmerkungen