关于黄色警告和删除线#

黄色警告分为由编译器产生的警告和由 clangd 的 clang-tidy 部分产生的警告, 而删除线由 clangd 的 clang-tidy 部分产生.

黄色警告

黄色警告分为由编译器产生的警告和由 clangd 的 clang-tidy 部分产生的警告. 它们不会让代码无法编译, 但说明在编译器或 clang-tidy 看来, 你的代码写得可能不够好.

删除线

删除线由 clangd 的 clang-tidy 部分检查产生. 它不会让代码无法编译, 但说明你的代码不满足在 .clang-tidy 文件中设定的代码风格规范.

在除了 Error Lens 插件所提供的代码中显示简单诊断信息, 我们还可以通过 问题 面板和 鼠标悬停 在诊断划线位置, 来了解更多信息:

如果没有显示出面板, 你可以通过 Ctrl-JCommand⌘-J 打开.

../../_images/%E9%97%AE%E9%A2%98%E9%9D%A2%E6%9D%BF.png

编译器产生的警告#

它的警告信息最后会有 clang(具体警告标识) 的字样. 部分开发者、尤其是库编写者为了让代码更好, 会选择启用 -Werror, 让所有编译器产生的警告提示为错误, 只要有任何警告或错误, 编译器就不会通过编译.

../../_images/%E5%B0%86%E5%8F%82%E6%95%B0%E6%9C%AA%E4%BD%BF%E7%94%A8%E8%AD%A6%E5%91%8A%E6%8F%90%E7%A4%BA%E4%B8%BA%E9%94%99%E8%AF%AF.png

将“参数未使用”警告提示为错误#

别看: 抑制这类警告的方法#

根据编译器不同使用的方法可能有差异, 可以参考第三方单元测试框架的代码, 其中一般会有抑制警告相关的部分. 以 Clang 为例:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-具体警告标识"
/* 你的代码部分,其中产生了你要抑制的警告 */
#pragma clang diagnostic pop

clang-tidy 产生的警告#

它的警告信息最后会有 clang-tidy(具体警告标识) 字样. 该警告标识是能点击的, 点击后会转到一个网页, 解释为什么有这个警告以及如何修复. 为了避免对新手产生太大影响, 我禁用了很多严格的警告.

此外, clang-tidy 也提供部分警告的自动修复.

可自动修复的警告#

部分 clang-tidy 产生的警告, 其警告信息后面会有 (fix available), 提示可以自动修复.

一个一个按键修复#

在代码或错误信息中选择它, 将会弹出 蓝色 小灯泡样式 (黄色小灯泡为 clangd 提供的代码重构功能), 点击它即可进行修复.

你也可以选中后按快捷键 Ctrl-句号Command⌘-句号 进行, 需要按 两次.

../../_images/%E5%8F%AF%E4%BF%AE%E5%A4%8D%E7%9A%84%E5%8F%98%E9%87%8F%E6%9C%AA%E5%88%9D%E5%A7%8B%E5%8C%96%E8%AD%A6%E5%91%8A.png

可修复的“变量未初始化”警告#

一键修复整个源文件中的警告#

打开要修复的源文件, Ctrl-Shift-PCommand⌘-Shift-P 打开命令菜单, 输入 task 找到 任务: 运行任务(Tasks: Run Task), 回车, 在出现的界面中选择我配置的 Clang-Tidy: fix current file, 回车.

这么做运行时间可能比较长, 但相比于按键修复, 它甚至能自动添加头文件包含保护.

../../_images/%E6%A0%B9%E6%8D%AE%E6%96%87%E4%BB%B6%E8%B7%AF%E5%BE%84%E8%87%AA%E5%8A%A8%E6%B7%BB%E5%8A%A0%E7%9A%84%E5%A4%B4%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB%E4%BF%9D%E6%8A%A4.png

根据文件路径自动添加的头文件包含保护, 如果头文件在 include 文件夹中, 则能产生更简单的路径.#

抑制这类警告的方法#

如果想要抑制 clang-tidy 产生的警告, 则

  • // NOLINT 可以抑制该行警告.

  • // NOLINTNEXTLINE 抑制下一行警告.

  • // NOLINTBEGIN// NOLINTEND 抑制它们之间的警告.

这些都是抑制 clang-tidy 相关所有警告, 如果想要抑制一部分警告, 则在它们后面加上 (具体警告标识1, 具体警告标识2), 你也可以用 * 作为通配符.

// NOLINT(cppcoreguidelines-init-variables)

抑制 C++ 核心准则要求初始化变量的警告.

// NOLINT(cppcoreguidelines*)

抑制所有以 cppcoreguidelines 开头的警告, 即所有 C++ 核心准则相关警告.

// NOLINT(*avoid-c-arrays)

抑制所有以 avoid-c-arrays 结尾的警告.

// NOLINT(*explicit*)

抑制所有包含 explicit 的警告.

不要滥用抑制警告#

请不要滥用抑制警告!

学习模板在配置时已经禁用了很多严格的警告, 而留下来的警告通常对初学者会有帮助. (当然, 我必须照顾在不同学习阶段的人, 因此有的警告你现在确实看不懂.)

我在答疑过程中经常看见有人用 // NOLINTBEGIN// NOLINTEND 禁用了整个源代码中的 clang-tidy 警告, 然后问代码出了什么问题, 结果代码出的问题恰恰就是他所禁用的警告所要警告的 (甚至能自动修复的!).

抑制警告不是说忽略那个警告, 而是编写者对软件、人 (可能是几天后的你自己!) 说: "我已经看到了那个警告并思考过了, 我认为我的代码没有问题, 并愿意为此负责."

例如, 新手常见的一个错误是, 将 == 写成了 =, 而 clang-tidy 完全能检测出来, 用警告询问你这样做是不是你想要的!

1int main() {
2  int value = 0;
3  cin >> value;
4
5  if (value = 5) {  // warning: Using the result of an assignment as a condition without parentheses (fixes available)
6    // ...
7  }
8}

所以, 我建议在抑制警告时, 一定要写明具体要禁用什么警告:

 1int main() {
 2  int value = 0;
 3  cin >> value;
 4
 5  //                ↓ 我知道我在下一行 if 里写了个 = 而不是 ==, 谢谢你的关心, 但这就是我想要的
 6  // NOLINTNEXTLINE(*assignment-in-if*)
 7  if (value = 5) {
 8    // ...
 9  }
10}

参考文献#

clang-tidy 产生的删除线#

它目前存在一些问题, 因而不能如 clang-tidy 产生的警告一样点击跳转到解释网页, 但删除线可以像 clang-tidy 产生的黄色警告一样进行修复.