Skip to content

Update hint file documentation #820

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 55 additions & 149 deletions docs/ide/hint-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,77 @@ ms.assetid: 17194f66-cf62-4523-abec-77db0675ab65
---
# Hint Files

A *hint file* helps the Visual Studio integrated development environment (IDE) interpret Visual C++ identifiers, such as the names of functions and macros. When you open a Visual C++ project, the IDE's *parsing system* analyzes the code in each source file in the project and gathers information about every identifier. Then the IDE uses that information to support features such as the **Class View** browser and the **Navigation Bar**.
A *hint file* contains macros which would otherwise cause regions of code to be skipped by the C++ Browsing Database Parser. When you open a Visual C++ project, the parser analyzes the code in each source file in the project and builds a database with information about every identifier. That information is used to support Then the IDE uses that information to support code browsing features such as the Class View browser and the Navigation Bar.
The C++ Browsing Database Parser by a fuzzy parser which enables parsing large amounts of code in a short amount of time. This is done in part by skipping contents of blocks (e.g. it records the location and parameters of a function but ignores it's contents). Certain macros can cause issues with the heuristics to determine the start and end of a block which causes regions of code to not be recorded properly.

The parsing system, which is introduced in Visual C++ 2010, understands C/C++ syntax but can misinterpret a statement that contains a macro. The statement can be misinterpreted if the macro causes the source code to be syntactically incorrect as written. The statement can become syntactically correct when the source code is compiled and the preprocessor replaces the [macro identifier](../preprocessor/hash-define-directive-c-cpp.md) with its definition. The parsing system works without having to build the project because it uses hint files to interpret macros. Therefore, a browsing feature such as **Class View** is immediately available.
These skipped regions can manifest in multiple ways
- Missing types and functions in **Class View**, **Go To** and **Navigation Bar**
- Incorrect scopes in the **Navigation Bar**
- Suggestions to **Create Declaration/Definition** for functions that are already defined

A hint file contains user-customizable *hints*, which have the same syntax as C/C++ macro definitions. Visual C++ includes a built-in hint file that is sufficient for most projects, but you can create your own hint files to improve the way Visual Studio handles identifiers.
A hint file contains user-customizable hints, which have the same syntax as C/C++ macro definitions. Visual C++ includes a built-in hint file that is sufficient for most projects, but you can create your own hint files to teach the improve the parser for your project.

> [!IMPORTANT]
> If you modify or add a hint file, you must delete the .sdf file and/or VC.db file in the solution in order for the changes to take effect.
> For earlier versions if you modify or add a hint file you need additional changes in order for the changes to take effect.
> Anything before Visual Studio 2017 15.6: Delete the .sdf file and/or VC.db file in the solution for all changes
> Visual Studio 2017 15.6 through 15.9: Close and reopen the solution after adding new hint files

## Scenario

Assume that the following code is in a source file that you examine with the **Class View** browser. The `STDMETHOD` macro declares a method named `myMethod` that takes one parameter and returns a pointer to an **HRESULT**.

```cpp
// Source code file.
STDMETHOD(myMethod)(int parameter1);
#define NOEXCEPT noexcept
void Function() NOEXCEPT
{
}
```
Without a hint file Function will not show up in **Class View**, **Go To** or **Navigation Bar**. After adding a hint file with the macro definition the parser will now understand and replace the macro which allows it to correctly parse the function.

```cpp.hint
#define NOEXCEPT
```
## Disruptive Macros

The following macro definitions are in a separate header file.
There are two categories of macros that disrupt the parser:

- Macros that encapsulate keywords that adorn a function
```cpp
// Header file.
#define STDMETHOD(method) HRESULT (STDMETHODCALLTYPE * method)
#define NOEXCEPT noexcept
#define STDMETHODCALLTYPE __stdcall
#define HRESULT void*
```
For these types of macros only the macro name is required in the hint file.
```cpp.hint
#define NOEXCEPT
#define STDMETHODCALLTYPE
```
- Macros that contain unbalanced brackets
```cpp
#define BEGIN {
```
For these types of macros both the macro name and it's contents are required in the hint file.
```cpp.hint
#define BEGIN {
```
## Editor Support

Starting with Visual Studio 2017 Update 8 there are several features to identify these disruptive macros:

The parsing system cannot interpret the source code because a function named `STDMETHOD` appears to be declared, and that declaration is syntactically incorrect because it has two parameter lists. The parsing system does not open the header file to discover the definitions for the `STDMETHOD`, `STDMETHODCALLTYPE`, and `HRESULT` macros. Because the parsing system cannot interpret the `STDMETHOD` macro, it ignores the whole statement and then continues parsing.
- Macros that are inside regions skipped by the parser will be highlighted.
- Action to add a hint file including the highlighted macro.
- Action to add the macro to the hint file if there's an existing hint file.

The parsing system does not use header files because your project might depend on one or more important header files. If any header file changes, the parsing system might have to reexamine all of the header files in your project, which slows down the performance of the IDE. Instead, the parsing system uses hints that specify how to handle the `STDMETHOD`, `STDMETHODCALLTYPE`, and `HRESULT` macros.
![Highlighted Macro.](../ide/media/HintSquiggleAndActions.png "HintSquiggleAndActions.")

How do you know that you need a hint? And if you need a hint, what kind should you create? One sign that a hint is needed is if the view of an identifier in **Class View** is inconsistent with the view in the **Editor**. For example, **Class View** might not display a class member that you know exists, or the name of the member is incorrect. For more information about the types of hints that solve common problems, see the What Macros Require A Hint? section later in this topic.
After executing either of the actions the parser will parse the files affected by the hint file.

By default the highlight of the macro will be a suggestion. It can be changed to something more noticeable such as a red or green squiggle with the **Macros in Skipped Browsing Regions** option in the **Code Squiggles** section under **Tools** -> **Options** -> **Text Editor** -> **C/C++** -> **View**.

![Macros in Skipped Browsing Regions Option.](../ide/media/SkippedRegionsSquiggleOption.png "SkippedRegionsSquiggleOption.")

## Display Browsing Database Errors

The **Display Browsing Database Errors** command (found under the **Project** menu) will display all the regions that failed to parse in the **Error List**. The command is meant to streamline building the initial hint file however at the parser level it can't determine if the cause of the error was a disruptive macro so each error needs to be evaluated. The recommended usage is to run the command and navigate to the errors which will load the affected file in the editor. Once the file is loaded if there is any macros inside the region those will be highlighted and the actions can be invoked. After an update the list will update automatically. Alternatively if you're modifying the hint file manually you can use the **Rescan Solution** command to trigger an update.

TODO: Add wording to request feedback tickets for unknown tag parser bugs?

## Architecture

Expand Down Expand Up @@ -94,135 +133,6 @@ Hints use the following syntax.
|`//` *comment*|A single line comment.|
|`/*` *comment* `*/`|A multiline comment.|

## What Macros Require A Hint?

Certain types of macros can interfere with the parsing system. This section describes the types of macros that can cause a problem, and the type of hint you can create to solve that problem.

### Disruptive Macros

Some macros cause the parsing system to misinterpret source code, but can be ignored without impairing your browsing experience. For example, the Source Code Annotation Language ([SAL](../c-runtime-library/sal-annotations.md)) macros resolve to C++ attributes that help you find programming bugs. If you want to ignore SAL annotations as you browse code, you might want to create a hint file that hides the annotation.

In the following source code, the parameter type for the `FormatWindowClassName()` function is `PXSTR`, and the parameter name is `szBuffer`. However, the parsing system mistakes the `_Pre_notnull_` and `_Post_z_` SAL annotations for either the parameter type or the parameter name.

**Source Code:**

```cpp
static void FormatWindowClassName(_Pre_notnull__Post_z_ PXSTR szBuffer)
```

**Strategy:** Null definition

The strategy in this situation is to treat the SAL annotations as if they did not exist. To do this, specify a hint whose replacement string is null. Consequently, the parsing system ignores the annotations, and the **Class View** browser does not display them. (Visual C++ includes a built-in hint file that hides SAL annotation.)

**Hint file:**

```cpp.hint
#define _Pre_notnull_
```

### Concealed C/C++ Language Elements

A typical reason that the parsing system misinterprets source code is if a macro hides a C/C++ [punctuator](../cpp/punctuators-cpp.md) or [keyword](../cpp/keywords-cpp.md) token. That is, a macro might contain half of a pair of punctuators, such as `<>`, `[]`, `{}`, and `()`.

In the following source code, the `START_NAMESPACE` macro hides an unpaired left brace (`{`).

**Source Code:**

```cpp
#define START_NAMESPACE namespace MyProject {
```

**Strategy:** Direct copy

If the semantics of a macro are critical to the browsing experience, create a hint that is identical to the macro. The parsing system resolves the macro to the definition in the hint file.

Note that if the macro in the source file contains other macros, those macros are interpreted only if they are already in the set of effective hints.

**Hint File:**

```cpp.hint
#define START_NAMESPACE namespace MyProject {
```

### Maps

A map consists of macros that designate a starting element, ending element, and zero or more intermediate elements. The parsing system misinterprets maps because each map macro hides C/C++ language elements, and the syntax of a complete C/C++ statement is distributed across many separate macros.

The following source code defines the `BEGIN_CATEGORY_MAP`, `IMPLEMENTED_CATEGORY`, and `END_CATEGORY_MAP` macros.

**Source Code:**

```cpp
#define BEGIN_CATEGORY_MAP(x)\
static const struct ATL::_ATL_CATMAP_ENTRY* GetCategoryMap() throw() {\
static const struct ATL::_ATL_CATMAP_ENTRY pMap[] = {
#define IMPLEMENTED_CATEGORY( catid ) { _ATL_CATMAP_ENTRY_IMPLEMENTED, &catid },
#define END_CATEGORY_MAP()\
{ _ATL_CATMAP_ENTRY_END, NULL } };\
return( pMap ); }
```

**Strategy:** Identify map elements

Specify hints for the start, middle (if any), and end elements of a map. Use the special map replacement strings, `@<`, `@=`, and `@>`. For more information, see the `Syntax` section in this topic.

**Hint File:**

```cpp.hint
// Start of the map.
#define BEGIN_CATEGORY_MAP(x) @<
// Intermediate map element.
#define IMPLEMENTED_CATEGORY( catid ) @=
// Intermediate map element.
#define REQUIRED_CATEGORY( catid ) @=
// End of the map.
#define END_CATEGORY_MAP() @>
```

### Composite Macros

Composite macros contain one or more of the types of macro that confuse the parsing system.

The following source code contains the `START_NAMESPACE` macro, which specifies the start of a namespace scope, and the `BEGIN_CATEGORY_MAP` macro, which specifies the start of a map.

**Source Code:**

```cpp
#define NSandMAP START_NAMESPACE BEGIN_CATEGORY_MAP
```

**Strategy:** Direct copy

Create hints for the `START_NAMESPACE` and `BEGIN_CATEGORY_MAP` macros, and then create a hint for the `NSandMAP` macro that is the same as shown earlier for the source code. Alternatively, if a composite macro consists of only disruptive macros and white space, you can define a hint whose replacement string is a null definition.

In this example, assume `START_NAMESPACE` already has a hint as described in this topic in the `Concealed C/C++ Language Elements` subheading. And assume `BEGIN_CATEGORY_MAP` has a hint as described earlier in `Maps`.

**Hint File:**

```cpp.hint
#define NSandMAP START_NAMESPACE BEGIN_CATEGORY_MAP
```

### Inconvenient Macros

Some macros can be interpreted by the parsing system, but the source code is difficult to read because the macro is long or complex. For the sake of readability, you can provide a hint that simplifies the display of the macro.

**Source Code:**

```cpp
#define STDMETHOD(methodName) HRESULT (STDMETHODCALLTYPE * methodName)
```

**Strategy:** Simplification

Create a hint that displays a simpler macro definition.

**Hint File:**

```cpp.hint
#define STDMETHOD(methodName) void* methodName
```

## Example

The following example illustrates how hints are accumulated from hint files. Stop files are not used in this example.
Expand Down Expand Up @@ -311,8 +221,4 @@ The following notes apply to the preceding list.

[File Types Created for Visual C++ Projects](../ide/file-types-created-for-visual-cpp-projects.md)<br>
[#define Directive (C/C++)](../preprocessor/hash-define-directive-c-cpp.md)<br>
[#undef Directive (C/C++)](../preprocessor/hash-undef-directive-c-cpp.md)<br>
[SAL Annotations](../c-runtime-library/sal-annotations.md)<br>
[Message Maps](../mfc/reference/message-maps-mfc.md)<br>
[Message Map Macros](../atl/reference/message-map-macros-atl.md)<br>
[Object Map Macros](../atl/reference/object-map-macros.md)
[#undef Directive (C/C++)](../preprocessor/hash-undef-directive-c-cpp.md)<br>
Binary file added docs/media/HintSquiggleAndActions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/media/SkippedRegionsSquiggleOption.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.