提示文件

A 提示文件 帮助 Visual Studio 集成的开发环境 (IDE) 解释 Visual C++ 的标识符,如函数和宏的名称。当您打开 Visual C++ 项目,IDE 的 分析系统 分析项目中的每个源文件中的代码,并收集有关每个标识符的信息。IDE 将使用该信息如支持的功能,然后 类视图 浏览器和 导航栏.

分析系统,在引入 Visual C++ 2010了解 C/c + + 语法,但可以曲解包含宏的语句。如果该宏会导致语法不正确所编写的源代码,该语句可能被误解。语句语法可能不正确的源代码被编译和预处理替换时 宏标识符 为其定义。 分析系统的工作而无需生成项目,因为它使用提示文件来解释宏。 因此,浏览功能如 类视图 将立即显示。

提示文件包含用户可自定义 提示它具有相同的语法与 C/c + + 宏定义。Visual C++ 包含内置提示文件,可满足多数项目中,但您可以创建您自己的提示文件,从而提高 Visual Studio 处理标识符的方式。

方案

假定下面的代码是您用检查的源文件中 类视图 浏览器。" STDMETHOD 宏声明名为的方法 myMethod 它采用一个参数,并返回一个指针,指向 HRESULT.

// Source code file.
STDMETHOD(myMethod)(int parameter1);

以下宏定义都在单独的头文件中。

// Header file.
#define STDMETHOD(method) HRESULT (STDMETHODCALLTYPE * method)
#define STDMETHODCALLTYPE __stdcall
#define HRESULT void*

分析系统无法解释的源代码,因为名为 STDMETHOD 的函数声明,看起来,该声明是语法不正确的因为它具有两个参数列表。分析系统不会打开要发现的定义的标头文件 STDMETHOD, STDMETHODCALLTYPE和 HRESULT 宏。因为分析系统无法解释 STDMETHOD 宏,它将忽略整个语句并继续分析。

分析系统不使用头文件,因为您的项目可能会依赖于一个或多个重要的头文件。如果更改了任何头文件,分析系统可能需要重新检查所有的项目,从而降低性能的 IDE 中的头文件。相反,分析系统使用提示,以指定如何处理 STDMETHOD, STDMETHODCALLTYPE和 HRESULT 宏。

您是否知道您需要提示?并且如果您需要提示,哪种类型应创建吗?一个标志,则需要提示就是如果视图中的标识符 类视图 与中的视图不一致 编辑器.例如, 类视图 可能不会显示您所知道的类成员存在或该成员的名称不正确。有关解决常见问题的提示类型的详细信息,请参阅什么宏需要提示?在本主题后面的部分。

体系结构

提示文件属于物理目录,不属于的逻辑目录中所示 解决方案资源管理器.不需要将提示文件添加到用于该提示文件产生影响的项目。只有在分析源文件时,分析系统将使用提示文件。

每个提示文件被命名为 cpp.hint.因此,许多目录可以包含提示文件,但只有一个提示文件可以出现在特定目录中。

由零个或多个提示文件,您的项目会受到影响。如果没有提示文件,分析系统将使用错误恢复技术忽略无法解密的源代码。否则,分析系统使用以下策略来查找和收集提示。

搜索顺序

分析系统按以下顺序搜索提示文件的目录。

  • 包含 Visual C++ (的安装软件包的目录vcpackages).此目录包含内置提示文件描述频繁使用的系统文件中的符号如 windows.h.因此,项目将自动继承它所需要的提示中的大多数。

  • 从源代码文件的根目录到包含源文件本身的目录的路径。在典型的 Visual C++ 项目,根区目录中包含的解决方案或项目文件。

    此规则的例外情况是如果 停止文件 正在对源文件的路径。停止文件可对搜索顺序额外进行控制,是任何文件,名为 cpp.stop.而不是从根目录开始,分析系统将从包含停止文件到包含源文件的目录的目录搜索。在典型的项目中,您不需要停止文件。

提示收集

提示文件包含零个或更多 提示.一种提示定义或删除就像 C/c + + 宏一样。也就是说, #define 预处理器指令创建或重新定义提示,并且 #undef 指令删除提示。

分析系统前面描述的搜索顺序打开每个提示文件,将每个文件的提示累积到一组 有效提示然后使用有效提示解释代码中的标识符。

分析系统使用以下规则来累积提示。

  • 如果新提示指定一个未定义的名称,则该新提示将名称添加到有效提示。

  • 如果新提示指定一个已定义的名称,则新提示将重新定义现有提示。

  • 如果新提示是 #undef 指令指定现有有效提示,则新提示将删除现有提示。

第一条规则意味着有效提示继承以前打开的提示文件。最后两个规则意味着在后面的搜索顺序中出现的提示可以重写前面发生的提示。如果在包含源文件的目录中创建提示文件,例如,可以重写以前的任何提示。

有关如何收集提示的描述,请参阅 示例 在本主题后面的部分。

语法

提示创建和删除具有相同的语法与用于创建和删除宏的预处理器指令。事实上,分析系统使用 C/c + + 预处理器评估提示。关于预处理程序指令的详细信息,请参阅 #define 指令 (C/C++)#undef 指令 (C/C++).

只有特殊的语法元素 @<, @=和 @> 替换字符串。这些是只与一起使用的提示文件特定的替换字符串 映射 宏。映射是一组与其他数据、 函数或事件处理程序相关的数据、 函数或事件的宏。例如, MFC 使用映射来创建 消息映射ATL 使用映射来创建 对象映射.提示文件特定的替换字符串指示映射的开始、 中间,和结束元素。只有映射宏的名称非常重要。因此,每个替换字符串有意隐藏宏的实现。

提示使用下面的语法。

语法

含义

#define提示名称替换字符串

#define提示名称(参数, ...)替换字符串

定义新的提示或重新定义现有提示的预处理器指令。该指令之后,预处理器会将每个匹配项 提示名称 在源代码中使用 替换字符串.

第二种语法形式定义类似于函数的提示。如果在源代码中出现的类似于函数的提示,预处理器首先将每个匹配项替换 参数 在中 替换字符串 使用源代码,然后替换中的对应实参 提示名称 与 替换字符串.

@<

特定于提示文件 替换字符串 指示一组映射元素的开始。

@=

特定于提示文件 替换字符串 它指示一个中间映射元素。图可以包含多个映射元素。

@>

特定于提示文件 替换字符串 指示一组映射元素的结尾。

#undef提示名称

将删除现有提示的预处理器指令。提供的名称的提示 提示名称 标识符。

//注释

单行注释。

/*注释*/

多行注释。

哪些宏需要提示?

某些类型的宏可能会干扰分析系统。本部分中介绍的宏,可能会导致出现问题,类型和类型的提示,您可以创建用于解决该问题。

中断宏

某些宏会导致错误地解释源代码,则分析系统,但可以忽略而不会影响您的浏览体验。例如,源代码批注语言 (SAL) 宏解析为 c + + 属性,可帮助您查找编程错误。如果您想要忽略 SAL 注释浏览代码时,可能要创建一个隐藏注释的提示文件。

在下面的源代码中的参数类型为 FormatWindowClassName() 技术支持部门 PXSTR并且参数名称 szBuffer.但是,分析系统会 _Pre_notnull_ 和 _Post_z_ SAL 注释参数类型或参数名称。

源代码:

static void FormatWindowClassName(_Pre_notnull_ _Post_z_ PXSTR) szBuffer

策略: Null 定义

在此情况下的策略是将 SAL 注释,好像他们不存在。若要执行此操作,请指定替换字符串为 null 的提示。因此,分析系统会忽略注释,并且 类视图 浏览器不显示它们。(Visual C++ 包括内置提示文件,它隐藏 SAL 注释)。

提示文件:

#define _Pre_notnull_

隐藏的 C/c + + 语言元素

分析系统对源代码作出错误解释的一个典型原因是如果宏将隐藏 C/c + + 标点符号关键字 标记。也就是说,宏可能包含一半对标点符号如 <>, [], {}和 ().

在下面的源代码, START_NAMESPACE 宏将隐藏不成对的左大括号 ({).

源代码:

#define START_NAMESPACE 我的项目的命名空间 {

策略: 直接复制

如果宏的语义是非常关键的浏览体验,则创建与宏相同的提示。分析系统将解析为提示文件中定义的宏。

请注意,是否在源文件中的宏包含其他宏,这些宏来解释仅当已在有效提示的一组。

提示文件:

#define START_NAMESPACE 我的项目的命名空间 {

映射

一幅地图包含,指定起始元素、 结束元素以及零个或多个中间元素的宏。分析系统错误地解释映射,因为每个映射宏隐藏 C/c + + 语言元素,并且完整的 C/c + + 语句的语法分布在许多单独的宏中。

定义了下面的源代码 BEGIN_CATEGORY_MAP, IMPLEMENTED_CATEGORY和 END_CATEGORY_MAP 宏。

源代码:

#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 ); }

策略: 标识映射元素

指定提示的开始、 中间 (如果有的话) 和结束映射中的元素。使用特殊映射替换字符串中, @<, @=和 @>.有关详细信息,请参阅 语法 本主题中的部分。

提示文件:

// 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() @>

组合宏

组合宏包含一个或多个类型的宏,扰乱分析系统。

包含下面的源代码 START_NAMESPACE 宏,用它指定命名空间范围的起始点,并将 BEGIN_CATEGORY_MAP 宏,指定一个映射的开始。

源代码:

#define NSandMAP START_NAMESPACE BEGIN_CATEGORY_MAP

策略: 直接复制

为创建提示 START_NAMESPACE 和 BEGIN_CATEGORY_MAP 宏,然后创建一个提示 NSandMAP 如上文所示的源代码相同的宏。或者,如果组合宏包含仅中断宏和空白区域,您可以定义替换字符串为 null 定义的提示。

在此示例中,假定 START_NAMESPACE 在本主题中所述,已经有一个提示 隐藏的 C/c + + 语言元素 子标题。并认为 BEGIN_CATEGORY_MAP 如前面所述,在具有一种提示 映射.

提示文件:

#define NSandMAP START_NAMESPACE BEGIN_CATEGORY_MAP

不合适的宏

分析系统,可以解释某些宏,但是源代码很难看清因宏太长或太复杂。为了增强可读性,您可以提供一个简化了的宏显示的提示。

源代码:

#define STDMETHOD(methodName) HRESULT (STDMETHODCALLTYPE * 方法名称)

策略: 简化

创建一个显示简单的宏定义的提示。

提示文件:

#define STDMETHOD(methodName) void * 方法名称

示例

下面的示例说明了如何从提示文件累积提示。在此示例中,不会使用停止文件。

下图描述了一些 Visual C++ 项目中的物理目录。提示文件位于 vcpackages, 调试, A1A2 目录。

提示文件目录

通用和特定于项目的提示文件目录。

目录和提示文件内容

下表列出了此项目中包含提示文件和这些提示文件中的内容的目录。只有部分中的很多提示 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 }

下列注意事项适用于上表。

  • 有效的提示是来自 vcpackages, 调试, A1A2 目录。

  • " #undef 指令中 调试 提示文件中删除 #define _In_ 在提示 vcpackages 目录提示文件。

  • 在提示文件中的 A1 重新定义了目录 START_NAMESPACE.

  • " #undef 在提示 A2 目录中删除的提示 OBRACE 和 CBRACE 在中 调试 目录提示文件。

请参见

参考

#define 指令 (C/C++)

#undef 指令 (C/C++)

消息映射 (MFC)

概念

为 Visual C++ 项目创建的文件类型

SAL 批注

其他资源

创建和控制环境窗口

Message Map Macros (ATL)

Object Map Macros