If you use VSCode tasks, you’ll probably be familiar with the warning that’s reported in the command palette if you haven’t specified a “problem matcher” for your task.
If you’re like me, you probably just clicked “never scan the task output for this task” and moved on with your life, but there’s a good reason to make one.
First, you should understand just what the problem matcher is. In the panels beneath your code, there is a “Problems” panel.
This is an interactive panel that shows all of the problems that were detected and lets you click on an issue to automatically bring up the offending file+line in the editor.
You may be thinking, “That’s all well and good for background tasks, but why would I want this for tasks?”
For one simple reason: it collates everything into one place and makes it easy to iterate through.
If you have several different linters you’d like to run plus tests, this will put all issues into one place so you don’t have to look at the terminal output from many sources. Having everything in one place is insanely useful, which is why I added it to my vscode_ros2_workspace template.
There are some excellent tutorials on how to make a problem matcher. The TL;DR is that you should create a regex filter that matches the output of your task when there is an issue.
I test my regex by copy+pasting an output line from the terminal into an
interactive regex testing site. It’s important to know
that VSCode expects an extra \
escape character, so you will have to modify
the expression you create to add it.
For example, \d
to match a digit in a regular expression becomes \\d
in
tasks.
Let’s create a simple problem matcher for ament_flake8
.
When ament_flake8
encounters a problem, the output looks like this:
> Executing task: ament_flake8 src/ <
src/examples/rclpy/actions/minimal_action_client/examples_rclpy_minimal_action_client/client_cancel.py:38:5: E303 too many blank lines (2)
def goal_response_callback(self, future):
^
src/examples/rclpy/actions/minimal_action_client/examples_rclpy_minimal_action_client/client_cancel.py:52:5: E303 too many blank lines (2)
def feedback_callback(self, feedback):
^
2 E303 too many blank lines (2)
61 files checked
2 errors
'E'-type errors: 2
The problem matcher matches regex strings on a single line. So we see that the most applicable line is
src/examples/rclpy/actions/minimal_action_client/examples_rclpy_minimal_action_client/client_cancel.py:38:5: E303 too many blank lines (2)
Where we see <file>:<line>:<column>: <code> <message>
Now we’ll make a regex expression to match. We can test it by pasting the output into regex101
The pattern I came up with is
^(.+):(\d+):(\d+): (\w\d+) (.+)$
Play with it here!
When you move this expression into VS Code you need to escape all \
, with a
\\
.
The corresponding task.json
setting then looks like this:
"problemMatcher": [
{
"owner": "flake8",
"source": "flake8",
"pattern": [
{
"code": 4,
"column": 3,
"file": 1,
"line": 2,
"message": 5,
"regexp": "^(.+):(\\d+):(\\d+): (\\w\\d+) (.+)$"
}
]
}
]
Simple single-line outputs are the easiest to test + parse, but it also supports more complicated multi-line matches. This tutorial shows you how.
However, it is fairly limited in that it expects continuous matching patterns from a single line. This works for most output, but not all.