共计 9248 个字符,预计需要花费 24 分钟才能阅读完成。
☞ ░ 前往老猿 Python 博客 ░ https://blog.csdn.net/LaoYuanPython
一、简介
在 VS Code 中,tasks.json 文件中的 problemMatcher 字段用于定义如何解析任务输出中的问题(错误、警告等)。
problemMatcher 有三种配置方式,具体可参考《VSCode 中的任务什么情况下需要配置多个问题匹配器 problemMatcher?多个问题匹配器之间的关系是什么?》的介绍。
本文要介绍的是 problemMatcher 为一个 ProblemMatcher 的 JSON 对象时其下的子对象 pattern,pattern 用于匹配任务执行时输出的信息,如编译任务输出的告警和错误信息,对符合 pattern 指定匹配规则的信息则纳入 problemMatcher 处理。
二、测试的 C ++ 代码文件样例
为了测试 vscode 的问题匹配,下面是一个故意存在多处错误的 hello.cpp 文件的代码,注意就是一个完整的 cpp 文件,不存在单独的头文件和其他外部文件:
#include
#include
#include "myhead.h"
int main()
{
int loop;
int i,j;
printf("j=%sn",j);
for(loop=0;loop5;loop++)
printf("hello,world!%dn",i);
i++;
hell("");
}
大家看得出来几处问题代码吗?
三、问题匹配器中的模式 pattern 介绍
3.1、vscode 中 pattern 的定义
pattern 在 vscode 中 的定义如下:
pattern: string | ProblemPattern | ProblemPattern[]
关于这个定义,vscode 官方文档中有如下说明:The name of a predefined problem pattern, the inline definition of a problem pattern or an array of problem patterns to match problems spread over multiple lines,结合上述定义和文字说明可知,pattern 可以为字符串、ProblemPattern 类型对象和 ProblemPattern 数组:
- pattern 为字符串的情况,vscode 官方说是预定义的匹配模式,老猿查阅了很多资料,也许是统信下的 vscode 版本 1.81.0 太低,也许是没找对方法,在 vscode1.81.0 中反复测试也没有测试通过;
- pattern 为 ProblemPattern 类型的对象时,包含有多个子对象,在接下来的 3.2 节中详细介绍其相关信息;
- pattern 为 ProblemPattern 类型的数组时,表明其所在的问题匹配器的匹配模式可以有多种,这些匹配模式按照配置中的先后顺序逐一与输出信息匹配,如果都匹配成功,则整个问题匹配成功,否则就是未匹配,即多个匹配模式是与的关系,这个与问题匹配器 problemMatcher 多个之间是或的关系是不同的。查阅了 vscode 的官方文档,这种模式数组是用于匹配多行。不过关于此模式老猿一直未能测试成功,3.3 节再介绍测试情况。
3.2、ProblemPattern 类型介绍
3.2.1、ProblemPattern 类的定义
以下是 vscode 官方文档中关于 ProblemPattern 类的定义:
interface ProblemPattern {
regexp: string;
kind?: 'file' | 'location';
file: number;
location?: number;
line?: number;
column?: number;
endLine?: number;
endColumn?: number;
severity?: number;
code?: number;
message: number;
loop?: boolean;
}
3.2.2 ProblemPattern 类型的介绍
从上面官方文档的介绍可以知道,ProblemPattern 包含多个子元素,从以上定义的英文注释能理解大部分定义要素的含义,但有些光理解注释的字面意思还不够,老猿结合测试情况对这下面分每个子元素展开介绍。
3.2.2.1、regexp
3.2.2.1.1、regexp 概述
regexp 对应为匹配输出问题信息的正则表达式,正则表达式使用的元字符与 Python 的 re 模块基本一致,如元字符包括:“.*?[]{}[]+-^$”等,转义符为 ””,同时支持转义符定义的特殊序列以及组匹配模式,支持通过组序号方式来访问匹配内容,需要注意转义符在字符串中需要使用双斜杠。关于 Python 正则表达式的有关介绍请参考老猿在 CSDN 的博文专栏《Python 支撑正则表达式处理的 re 模块》。
3.2.2.1.2、regexp 正则表达式中常用的元字符及含义
regexp 正则表达式中部分常用元字符及其含义:
- ^:匹配字符串的开头
- s*:匹配零个或多个空格字符
- (.*):匹配任意字符,零个或多个 字符
- (d+):匹配一个或多个数字字符
- s+:匹配一个或多个分隔字符 (如空格、回车、tab 等)
- (子正则表达式):用于将指定正则匹配的内容进行分组
案例:"^(.*):(d+):(d+):s+(error):s+(.*)$"
这个正则语句匹配如下类似的错误信息:hello.cpp:3:10: error: myhead.h: 没有那个文件或目录
,其中文件名的匹配组号为 1、行号匹配组号位 2、列号的匹配组号为 3,匹配的问题级别信息“error”的匹配组号为 4,具体错误信息匹配组号为 5
3.2.2.2、kind
指问题匹配时匹配到问题具体的行列位置还是只需要匹配到文件,有 2 个取值,一个是“file”,表示只需要匹配到文件,另一个是“location”,匹配到行列指定的具体位置,缺省值是“location”。
我们通过案例来看看问题面板输出的不同,以上面 hello.cpp 的爆粗信息:hello.cpp:3:10: fatal error: myhead.h: 没有那个文件或目录
为例:
- 设置为“location”,问题面板中输出信息文件那栏输出了文件名、行号、列号,如图:
注意,零两个问题不是问题匹配器 problem_1 输出的,而是扩展组件 C ++ 智能感知输出的。 - 设置为“file”,问题面板中输出信息文件那栏输出了文件名、行号、列号,不过行号、列号固定为 1,如图:
3.2.2.3、file、line、column
在正则表达式匹配输出信息时识别出来的文件名的匹配组号,有关正则知识请参考老猿在 CSDN 上《Python 基础教程》下的博文《第 11.16 节 Python 正则元字符“()”(小括号)与组(group)匹配模式》的相关介绍。
按照:
案例正则表达式:"^(.*):(d+):(d+):s+(error):s+(.*)$"
对错误信息:hello.cpp:3:10: error: myhead.h: 没有那个文件或目录
进行匹配,file 的匹配组号为 1,即第一个括号内匹配到的内容为文件名,类似的 line、column 为匹配到错误位置行号、列号的匹配组号,在上面例子中分别对应组号 2 和 3。
3.2.2.4、endLine、endColumn
endLine、endColumn 与 line、column 类似,不过有些代码的编译构建程序会输出错误代码的起止行号和列号,line、column 匹配开始行号和列号,而 endLine、endColumn 匹配终止行号和列号。C++ 的编译器没有输出相关信息,因此无需配置。
3.2.2.5、severity
问题输出信息中匹配到的问题级别的匹配组号,在上面的例子中就是 (error)
这个匹配信息对应的匹配组号。problemMatcher 和 ProblemPattern 都存在“severity”的属性,ProblemPattern 又是 problemMatcher 的子属性,二者的“severity”属性关系请见《VSCode 任务 tasks.json 中的问题匹配器 problemMatcher 和 ProblemPattern 的 severity 属性关系》的分析,相关情况请参考本文后面的测试情况说明。
3.2.2.6、code
用于设置正则表达式匹配问题报错信息中给出的错误源代码的匹配组号,在 C ++ 中的报错信息中存在有源代码信息,但是在报错信息后面单独一行输出,由于涉及多行匹配,老猿一直无法验证成功。
没测试成功的原因可能有 3 个:
- vscode 的版本过低,因为老猿使用的是国产操作系统,安装的 vscode 的版本是 1.81.0,而 windows 下已经至少是 1.20.0 的版本了;
- 多行问题匹配器不适合 C ++ 的编译错误信息,可能在别的语言构建时可以;
- 老猿的配置方法不对。
老猿觉得前面两个原因的可能性占多数,因为老猿做了很多测试都无法支持多行输出信息的处理,详细请见博文下面的介绍。
3.2.2.7、message
用于设置正则表达式匹配问题报错信息中给出的具体错误信息的匹配组号,如果没有配置或配置为 0,默认就是包含文件名等在内的整个问题信息。
3.2.2.8、loop
loop 这个属性老猿仅从字面理解了,是指定多行问题匹配器中的最后一个模式是否应循环,只要它与一行匹配即可,仅对多行问题匹配器中的最后一个问题模式有效。老猿理解为多行问题信息匹配需要多个匹配器来匹配多行的信息,如果 loop 为 true,则只要这个问题匹配器匹配到任意一行的输出信息即可。
因为涉及多行匹配,与 code 属性一样,用 C ++ 程序测试时没有测试通过,因此也不知道理解是否正确。
四、问题匹配器的一些测试案例及结果介绍
4.1、编译 hello.cpp 的 tasks.json 的基本配置
下面是老猿使用的编译 hello.cpp 的 tasks.json 的基本配置:
{
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ 生成活动文件",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-g",
"-Wall",
"-Wextra",
"-O0",
"${workspaceFolder}/hello.cpp",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options":
{"cwd": "${fileDirname}"
},
"problemMatcher":
["$gcc"],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "编译器: /usr/bin/g++"
}
]
}
这是初始配置,问题匹配器用的是预定义的$gcc
。用该配置编译上述 hello.cpp 时,在终端窗口输出的错误信息如下:
目前看到仅一个报错:“/home/administrator/E_DRIVER/vcwork/test/hello.cpp:3:10: fatal error: myhead.h: 没有那个文件或目录
”,这是因为遇到了致命错误,所以没有继续往下执行编译。下面是此时在问题控制面板的输出信息:
可以看到输出了三个 error 级别的错误信息,其中前 2 个是 VSCODE 的 C ++ 插件 IntelliSense 输出的,第三个是 cpptools 输出的,实际上就是上面配置的问题匹配器 $gcc
输出的。
4.2、测试新增一个问题匹配器以及 problemMatcher 和 ProblemPattern 的 severity 属性关系
修改问题匹配器配置如下:
"problemMatcher":
[
{"owner": "problem_1",
"severity": "warning",
"fileLocation": "absolute",
"pattern":
{"regexp": "^(.*):(d+):(d+):s+(fatal).*:s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
},
"$gcc"
]
注意该问题匹配器的配置有如下要点:
- problemMatcher.”severity” 的值为“warning”;
- pattern.”severity” 的值为 4,对应 regexp 的第 4 个匹配组号,对应匹配内容为
(fatal)
; - 配置了 2 个问题匹配器,分别是自定义的
problem_1
和预定义的$gcc
。
这样配置后,执行生成构建任务后,问题面板的输出信息如下:
可以看到:
- 原来基本配置显示的最左边的严重级别图标为 error,修改问题匹配器后显示为 warning 对应的图标;
- 问题来源显示为新配置的 problem_1;
- 错误信息由原来的“myhead.h: 没有那个文件或目录”变成了“没有那个文件或目录”。
结合上述问题匹配器大家去理解一下为什么会有这些变化,有疑问在评论区提问。
通过这个配置可以说明如下情况:
- problemMatcher 的 severity 属性优先 ProblemPattern 的 severity 属性;
- 多个问题匹配器是按顺序匹配的,匹配到一个后面的不再匹配。
4.3、去除 problemMatcher 的 severity 配置场景
将自定义的问题匹配器的 problemMatcher 的 severity 属性配置注释掉,同时将 message 的匹配组号调整为 4,与 pattern.”severity” 的值相同,配置如下:
"problemMatcher":
[
{"owner": "problem_1",
// "severity": "warning",
"fileLocation": "absolute",
"pattern":
{"regexp": "^(.*):(d+):(d+):s+(fatal).*:s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 4
}
},
"$gcc"
],
可以看到执行构建任务时,问题面板输出内容如下:
可以看到输出的消息变为:fatal,问题严重级别图标变为 error,相关结论大家可以参考《VSCode 任务 tasks.json 中的问题匹配器 problemMatcher 和 ProblemPattern 的 severity 属性关系》的介绍。
4.3、新增两个定制化的 problemMatcher 配置场景
4.3.1、测试背景说明
由于测试代码中的 #include "myhead.h"
存在致命错误,导致编译程序无法往下执行,为了测试本场景,要求本次测试的代码是注释或去除了该行代码,此时编译报错信息为:
hello.cpp:10:12: warning: format‘%s’expects argument of type‘char*’, but argument 2 has type‘int’[-Wformat=]
printf("j=%sn",j);
^~~~~~~~ ~
hello.cpp:14:5: error:‘hell’was not declared in this scope
hell("");
^~~~
hello.cpp:14:5: note: suggested alternative:‘ftell’hell("");
^~~~
ftell
生成已完成,但出现错误。* 终端进程启动失败 ( 退出代码: -1)。
4.3.2、测试的问题匹配器配置
配置了三个问题匹配器,分别是 problem_error、problem_warning 和预定义的 gcc,三个问题匹配器本身都没有配置 severity 属性。具体配置如下:
"problemMatcher":
[
{"owner": "problem_error",
"fileLocation": "absolute",
"pattern":
{"regexp": "^(.*):(d+):(d+):s+(.*error).*:s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
},
{"owner": "problem_warning",
"fileLocation": "absolute",
"pattern":
{"regexp": "^(.*):(d+):(d+):s+(.*warning|note).*:s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
},
"$gcc"
]
进行编译构建后,输出问题面板内容如下:
可以看到输出了 4 个问题,其中一个是 C ++ InelliSense 输出的,其他三个是自定义问题匹配器输出的,大家应该可以理解输出信息为什么是这样吧?特别是最后一个显示的信息为什么是‘ftell’
?不理解的在评论区提问吧。
4.4、测试捕获输出了源代码的问题
将问题匹配器换成如下:
"problemMatcher":
[
{"owner": "problem_code",
"fileLocation": "absolute",
"pattern":
{"regexp": "^.*(printf).*$",
"file":1,
"message": 1
}
},
"$gcc"
]
该问题匹配器试图匹配输出信息存在 printf 的语句,但经测试该问题匹配器无法捕获到问题,具体原因未知,如果有哪位大佬可以解惑,欢迎在评论区留言,老猿感激不尽。
4.5、测试捕获多行问题信息
将问题匹配器改成如下:
"problemMatcher":
[
{"owner": "problem_multiline",
"fileLocation": "absolute",
"pattern":
[
{"regexp": "^(.*):(d+):(d+):s+(warning|note|error):s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
},
{"regexp": "(.*)",
"file":1,
"message": 1,
"loop":true
}
]
},
"$gcc"
]
上面的问题匹配器数组包含了两个问题匹配器,一个自定义的 problem_multiline,一个 gcc,其中 problem_multiline 配置了两个 ProblemPattern 问题模式。运行编译任务后,可以看到问题面板输出信息如下:
这个输出结果可以看到,针对 note 的告警信息,匹配了 problem_multiline 这个问题匹配器,其他的问题输出信息都没有匹配到 problem_multiline,匹配到的问题匹配器的输出信息感觉是两个 ProblemPattern 对 note 所在的首行输出信息进行匹配之后叠加一起作为 message 输出,为什么这样老猿也没搞懂,欢迎各位大佬指教。
五、小结
本文介绍了 VSCode 任务 tasks.json 中的问题匹配器 problemMatcher 的配置项问题匹配模式 ProblemPattern,包括官方定义以及老猿对每个 ProblemPattern 子对象的解读,有些内容是老猿测试验证后独家公布,同时对相关知识老猿也存在多处没有理解的地方,在正文中都以加粗字体显示,期待各位大佬指导。
写博不易,敬请支持:
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!
更多关于 vscode 使用方面的问题 的内容请参考专栏《国产信创之光》的相关文章。
关于老猿的付费专栏
- 付费专栏《https://blog.csdn.net/laoyuanpython/category_9607725.html 使用 PyQt 开发图形界面 Python 应用》专门介绍基于 Python 的 PyQt 图形界面开发基础教程,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/107580932 使用 PyQt 开发图形界面 Python 应用专栏目录》;
- 付费专栏《https://blog.csdn.net/laoyuanpython/category_10232926.html moviepy 音视频开发专栏 )详细介绍 moviepy 音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy 音视频开发专栏文章目录》;
- 付费专栏《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python 初学者疑难问题集》为《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python 图形图像处理》的伴生专栏,是笔者对 OpenCV-Python 图形图像处理学习中遇到的一些问题个人感悟的整合,相关资料基本上都是老猿反复研究的成果,有助于 OpenCV-Python 初学者比较深入地理解 OpenCV,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/109713407 OpenCV-Python 初学者疑难问题集专栏目录》
- 付费专栏《https://blog.csdn.net/laoyuanpython/category_10762553.html Python 爬虫入门》站在一个互联网前端开发小白的角度介绍爬虫开发应知应会内容,包括爬虫入门的基础知识,以及爬取 CSDN 文章信息、博主信息、给文章点赞、评论等实战内容。
前两个专栏都适合有一定 Python 基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python 图形图像处理》的学习使用。
对于缺乏 Python 基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python 基础教程目录)从零开始学习 Python。
如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。
老猿 Python,跟老猿学 Python!
☞ ░ 前往老猿 Python 博文目录 https://blog.csdn.net/LaoYuanPython ░
原文地址: VSCode 任务 tasks.json 中的问题匹配器 problemMatcher 的问题匹配模式 ProblemPattern 详解