通过任务与外部工具集成

有很多工具可以自动执行诸如检查、构建、打包、测试或部署软件系统等任务。示例包括TypeScript Compiler 、 ESLintTSLint等 linter以及MakeAntGulpJakeRakeMSBuild等构建系统。

VS Code 可以与各种外部工具对话

这些工具大多从命令行运行,并自动执行内部软件开发循环内部和外部的作业(编辑、编译、测试和调试)。鉴于它们在开发生命周期中的重要性,能够在 VS Code 中运行工具并分析其结果会很有帮助。VS Code 中的任务可以配置为运行脚本和启动进程,以便可以在 VS Code 中使用许多现有工具,而无需输入命令行或编写新代码。工作区或文件夹特定任务是从工作区文件夹tasks.json中的文件配置的。.vscode

扩展还可以使用Task Provider贡献任务,并且这些贡献的任务可以添加tasks.json文件中定义的特定于工作区的配置。

注意:任务支持仅在处理工作区文件夹时可用。编辑单个文件时不可用。

TypeScript 你好世界

让我们从一个简单的“Hello World”TypeScript 程序开始,我们想要将其编译为 JavaScript。

创建一个空文件夹“mytask”,生成一个tsconfig.json文件并从该文件夹启动 VS Code。

mkdir mytask
cd mytask
tsc --init
code .

现在创建一个HelloWorld.ts包含以下内容的文件

function sayHello(name: string): void {
  console.log(`Hello ${name}!`);
}

sayHello('Dave');

⇧⌘B(Windows、Linux Ctrl+Shift+B或从全局终端菜单运行运行构建任务会显示以下选择器:

TypeScript 构建任务

第一个条目执行 TypeScript 编译器并将 TypeScript 文件转换为 JavaScript 文件。编译完成后,应该有一个HelloWorld.js文件。第二个条目以监视模式启动 TypeScript 编译器。每次保存到HelloWorld.ts文件都会重新生成该HelloWorld.js文件。

您还可以将 TypeScript 构建或监视任务定义为默认构建任务,以便在触发运行构建任务时直接执行(⇧⌘B (Windows, Linux Ctrl+Shift+B ))。为此,请从全局终端菜单中选择配置默认构建任务。这会向您显示一个带有可用构建任务的选择器。选择tsc: buildtsc: watch,VS Code 将生成一个文件。下面显示的任务使tsc: build任务成为默认构建任务:tasks.json

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "type": "typescript",
      "tsconfig": "tsconfig.json",
      "problemMatcher": ["$tsc"],
      "group": {
        "kind": "build",
        "isDefault": true
      }
    }
  ]
}

上面的示例tasks.json没有定义新任务。它将VS Code 的 TypeScript 扩展贡献的tsc: 构建任务注释为默认构建任务。您现在可以通过按⇧⌘B(Windows、Linux Ctrl+Shift+B来执行 TypeScript 编译器。

任务自动检测

VS Code 目前自动检测以下系统的任务:Gulp、Grunt、Jake 和 npm。我们正在与相应的扩展作者合作,添加对 Maven 和 C#dotnet命令的支持。如果您使用 Node.js 作为运行时开发 JavaScript 应用程序,您通常会有一个package.json描述依赖项和要运行的脚本的文件。如果您已克隆eslint-starter示例,则从全局菜单执行运行任务将显示以下列表:

任务 ESLint 启动器

如果您尚未这样做,请通过运行安装必要的 npm 模块npm install。现在打开server.js文件并在语句末尾添加一个分号(请注意,ESLint 启动器假定语句不带分号),然后再次执行运行任务。这次选择npm: lint任务。当提示使用问题匹配器时,选择ESLint Style

任务 ESLint 问题匹配器选择

执行任务会产生一个错误,如“问题”视图中所示:

任务 ESLint 问题

此外,VS Code 创建了一个tasks.json包含以下内容的文件:

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "type": "npm",
      "script": "lint",
      "problemMatcher": ["$eslint-stylish"]
    }
  ]
}

这指示 VS Code使用 ESLint 时尚格式扫描npm lint脚本的输出以查找问题。

对于 Gulp、Grunt 和 Jake,任务自动检测的工作原理相同。以下是为vscode-node-debug扩展检测到的任务示例。

Gulp任务自动检测

提示:您可以通过键入“任务”、空格和命令名称,通过“快速打开” ( ⌘P (Windows、Linux Ctrl+P ) )运行任务。在本例中,为“任务 lint”。

可以使用以下设置禁用任务自动检测:

{
  "typescript.tsc.autoDetect": "off",
  "grunt.autoDetect": "off",
  "jake.autoDetect": "off",
  "gulp.autoDetect": "off",
  "npm.autoDetect": "off"
}

自定义任务

并非所有任务或脚本都可以在您的工作区中自动检测。有时需要定义自己的自定义任务。假设您有一个脚本来运行测试,以便正确设置某些环境。该脚本存储在工作区内的脚本文件夹中,并test.sh针对 Linux 和 macOS 以及test.cmdWindows 进行命名。从全局终端菜单运行配置任务,然后从模板条目中选择创建tasks.json 文件。这将打开以下选择器:

配置任务运行器

注意:如果您没有看到任务运行程序模板列表,则您tasks.json的文件夹中可能已有一个文件,并且其内容将在编辑器中打开。在此示例中,关闭该文件并删除或重命名它。

我们正在努力提供更多的自动检测支持,因此这个列表将来会变得越来越小。由于我们想要编写自己的自定义任务,因此从列表中选择其他。这将打开tasks.json带有任务框架的文件。将内容替换为以下内容:

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Run tests",
      "type": "shell",
      "command": "./scripts/test.sh",
      "windows": {
        "command": ".\\scripts\\test.cmd"
      },
      "group": "test",
      "presentation": {
        "reveal": "always",
        "panel": "new"
      }
    }
  ]
}

任务的属性具有以下语义:

  • label:用户界面中使用的任务标签。
  • type:任务的类型。对于自定义任务,这可以是shellprocess。如果shell指定,则该命令将解释为 shell 命令(例如:bash、cmd 或 PowerShell)。如果process指定,则该命令被解释为要执行的进程。
  • command:实际执行的命令。
  • windows:任何 Windows 特定属性。在 Windows 操作系统上执行该命令时,将使用它代替默认属性。
  • group:定义任务属于哪个组。在示例中,它属于该test组。属于测试组的任务可以通过从命令面板运行运行测试任务来执行。
  • presentation:定义如何在用户界面中处理任务输出。在此示例中,显示了显示输出的集成终端,并在每次任务运行时创建always一个终端。new
  • optionscwd :覆盖(当前工作目录)、env(环境变量)或shell(默认 shell)的默认值。选项可以按任务设置,也可以全局或按平台设置。此处配置的环境变量只能从任务脚本或流程中引用,如果它们是参数、命令或其他任务属性的一部分,则不会被解析。
  • runOptions:定义任务运行的时间和方式。

您可以在文件中使用 IntelliSense 查看完整的任务属性和值集tasks.json使用Trigger Suggest ( ⌃Space (Windows, Linux Ctrl+Space ) )提出建议,并在悬停时或使用“阅读更多...” ('i') 弹出按钮阅读说明。

tasks.json 智能感知

您还可以查看tasks.json schema

当涉及包含空格或其他特殊字符(如 )的命令和参数时,Shell 命令需要特殊处理$。默认情况下,任务系统支持以下行为:

  • 如果提供单个命令,任务系统会按原样将该命令传递给底层 shell。如果命令需要引号或转义才能正常运行,则命令需要包含正确的引号或转义字符。例如,要列出名称中包含空格的文件夹的目录,在 bash 中执行的命令应如下所示:ls 'folder with spaces'
{
  "label": "dir",
  "type": "shell",
  "command": "dir 'folder with spaces'"
}
  • 如果提供了命令和参数,并且命令或参数包含空格,任务系统将使用单引号。对于cmd.exe,使用双引号。如下所示的 shell 命令将在 PowerShell 中执行为dir 'folder with spaces'.
{
  "label": "dir",
  "type": "shell",
  "command": "dir",
  "args": ["folder with spaces"]
}
  • 如果要控制参数的引用方式,参数可以是指定值和引用样式的文字。下面的示例使用转义而不是用空格引用参数。
{
  "label": "dir",
  "type": "shell",
  "command": "dir",
  "args": [
    {
      "value": "folder with spaces",
      "quoting": "escape"
    }
  ]
}

除了转义之外,还支持以下值:

  • Strong:使用 shell 的强引用机制,抑制字符串内的所有计算。在 PowerShell 下以及 Linux 和 macOS 下的 shell,使用单引号 ( ')。对于cmd.exe,"使用。
  • weak:使用 shell 的弱引用机制,它仍然计算字符串内的表达式(例如,环境变量)。在 PowerShell 下以及对于 Linux 和 macOS 下的 shell,使用双引号 ( ")。cmd.exe 不支持弱引用,因此 VS Code"也使用弱引用。

如果命令本身包含空格,VS Code 默认也会强引用该命令。与参数一样,用户可以使用相同的文字样式控制命令的引用。

还有更多任务属性可用于配置您的工作流程。您可以将 IntelliSense 与⌃Space(Windows、Linux Ctrl+Space结合使用来获取有效属性的概述。

任务智能感知

除了全局菜单栏之外,还可以使用命令面板( ⇧⌘P (Windows、Linux Ctrl+Shift+P ) ) 访问任务命令。您可以过滤“任务”,并可以查看各种与任务相关的命令。

命令面板中的任务

复合任务

您还可以使用该属性将更简单的任务组合成任务dependsOn。例如,如果您有一个包含客户端和服务器文件夹的工作区,并且两者都包含构建脚本,则可以创建一个在单独的终端中启动两个构建脚本的任务。如果您在属性中列出多个任务dependsOn,则默认情况下它们会并行执行。

tasks.json文件如下所示:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Client Build",
      "command": "gulp",
      "args": ["build"],
      "options": {
        "cwd": "${workspaceFolder}/client"
      }
    },
    {
      "label": "Server Build",
      "command": "gulp",
      "args": ["build"],
      "options": {
        "cwd": "${workspaceFolder}/server"
      }
    },
    {
      "label": "Build",
      "dependsOn": ["Client Build", "Server Build"]
    }
  ]
}

如果您指定"dependsOrder": "sequence",那么您的任务依赖项将按照它们列出的顺序执行dependsOndependsOnwith中使用的任何后台/监视任务都"dependsOrder": "sequence"必须有一个问题匹配器来跟踪它们何时“完成”。以下任务运行任务二、任务三,然后运行任务一。

{
  "label": "One",
  "type": "shell",
  "command": "echo Hello ",
  "dependsOrder": "sequence",
  "dependsOn": ["Two", "Three"]
}

用户级任务

您可以使用“任务:打开用户任务”命令创建不绑定到特定工作区或文件夹的用户级任务。此处只能使用shell和任务,因为其他任务类型需要工作区信息。process

输出行为

有时您想要控制运行任务时集成终端面板的行为方式。例如,您可能希望最大化编辑器空间,并且仅在认为存在问题时才查看任务输出。presentation可以使用任务的属性来控制终端的行为。它提供以下属性:

  • Reveal:控制是否将集成终端面板置于前面。有效值为:
    • always- 面板始终位于前面。这是默认设置。
    • never- 用户必须使用“视图” > “终端”命令 ( ⌃` (Windows、Linux Ctrl+` ) )显式地将终端面板置于前面 。
    • silent- 仅当输出未扫描错误和警告时,终端面板才会置于前面。
  • RevealProblems:控制运行此任务时是否显示“问题”面板。优先于选项reveal。默认为never.
    • always- 执行此任务时始终显示问题面板。
    • onProblem- 仅在发现问题时才显示问题面板。
    • never- 执行此任务时绝不显示问题面板。
  • focus:控制终端是否获取输入焦点。默认为false.
  • echo:控制是否在终端中回显执行的命令。默认为true.
  • showReuseMessage:控制是否显示“终端将被任务重用,按任意键关闭它”消息。
  • panel:控制是否在任务运行之间共享终端实例。可能的值为:
    • shared- 终端是共享的,其他任务运行的输出将添加到同一终端。
    • dedicated- 终端专用于特定任务。如果再次执行该任务,则会重新使用该终端。但是,不同任务的输出显示在不同的终端中。
    • new- 该任务的每次执行都使用新的干净终端。
  • clear:控制在此任务运行之前是否清除终端。默认为false.
  • close:控制任务退出时是否关闭任务运行的终端。默认为false.
  • group:控制是否使用分割窗格在特定终端组中执行任务。同一组中的任务(由字符串值指定)将使用拆分终端来呈现,而不是使用新的终端面板。

您还可以修改自动检测任务的终端面板行为。例如,如果您想更改上面 ESLint 示例中npm: run lintpresentation的输出行为,请向其中添加属性:

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "type": "npm",
      "script": "lint",
      "problemMatcher": ["$eslint-stylish"],
      "presentation": {
        "reveal": "never"
      }
    }
  ]
}

您还可以将自定义任务与检测到的任务的配置混合使用。tasks.json配置npm: run lint任务并添加自定义运行测试任务的A如下所示:

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "type": "npm",
      "script": "lint",
      "problemMatcher": ["$eslint-stylish"],
      "presentation": {
        "reveal": "never"
      }
    },
    {
      "label": "Run tests",
      "type": "shell",
      "command": "./scripts/test.sh",
      "windows": {
        "command": ".\\scripts\\test.cmd"
      },
      "group": "test",
      "presentation": {
        "reveal": "always",
        "panel": "new"
      }
    }
  ]
}

运行行为

您可以使用以下属性指定任务的运行行为runOptions

  • reevaluateOnRerun :控制通过“重新运行上一个任务”命令执行任务时如何评估变量。默认值为true,这意味着重新运行任务时将重新评估变量。当设置false为上次运行任务中解析的变量值时,将使用该值。
  • runOn:指定任务何时运行。
    • default- 该任务仅在通过“运行任务”命令执行时才会运行。
    • folderOpen- 当包含的文件夹打开时,任务将运行。第一次打开包含带有 的任务的文件夹时folderOpen,系统会询问您是否允许任务在该文件夹中自动运行。您可以稍后使用“管理自动任务”命令并在“允许自动任务”“禁止自动任务”之间进行选择来更改您的决定。

自定义自动检测的任务

如上所述,您可以在tasks.json文件中自定义自动检测的任务。您通常这样做是为了修改演示文稿属性或附加问题匹配器来扫描任务的输出是否有错误和警告。您可以直接从“运行任务”列表自定义任务,方法是按右侧的齿轮图标将相应的任务引用插入到文件中tasks.json。假设您有以下 Gulp 文件来使用 ESLint 对 JavaScript 文件进行 lint(该文件取自https://github.com/adametry/gulp-eslint):

const gulp = require('gulp');
const eslint = require('gulp-eslint');

gulp.task('lint', () => {
  // ESLint ignores files with "node_modules" paths.
  // So, it's best to have gulp ignore the directory as well.
  // Also, Be sure to return the stream from the task;
  // Otherwise, the task may end before the stream has finished.
  return (
    gulp
      .src(['**/*.js', '!node_modules/**'])
      // eslint() attaches the lint output to the "eslint" property
      // of the file object so it can be used by other modules.
      .pipe(eslint())
      // eslint.format() outputs the lint results to the console.
      // Alternatively use eslint.formatEach() (see Docs).
      .pipe(eslint.format())
      // To have the process exit with an error code (1) on
      // lint error, return the stream and pipe to failAfterError last.
      .pipe(eslint.failAfterError())
  );
});

gulp.task('default', ['lint'], function() {
  // This will only run if the lint task is successful...
});

从全局终端菜单执行运行任务将显示以下选择器:

配置任务

按齿轮图标。这将创建以下tasks.json文件:

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "type": "gulp",
      "task": "default",
      "problemMatcher": []
    }
  ]
}

通常,您现在会添加问题匹配器(在本例中$eslint-stylish)或修改演示设置。

使用问题匹配器处理任务输出

VS Code 可以使用问题匹配器处理任务的输出。问题匹配器扫描任务输出文本以查找已知的警告或错误字符串,并在编辑器和问题面板中内联报告这些内容。VS Code 附带了几个“现成的”问题匹配器:

  • TypeScript$tsc假设输出中的文件名相对于打开的文件夹。
  • TypeScript Watch$tsc-watch匹配tsc在监视模式下执行时编译器报告的问题。
  • JSHint$jshint假设文件名报告为绝对路径。
  • JSHint Stylish$jshint-stylish假设文件名报告为绝对路径。
  • ESLint Compact$eslint-compact假设输出中的文件名相对于打开的文件夹。
  • ESLint Stylish$eslint-stylish假设输出中的文件名相对于打开的文件夹。
  • Go$go匹配编译器报告的问题go。假设文件名与打开的文件夹相关。
  • CSharp 和 VB 编译器$mscompile假定文件名报告为绝对路径。
  • Lessc 编译器$lessc假定文件名报告为绝对路径。
  • Node Sass 编译器$node-sass假设文件名报告为绝对路径。

您还可以创建自己的问题匹配器,我们将在后面的部分中讨论。

将键盘快捷键绑定到任务

如果您需要频繁运行某个任务,您可以为该任务定义键盘快捷键。

例如,要绑定Ctrl+H到上面的运行测试任务,请将以下内容添加到您的keybindings.json文件中:

{
  "key": "ctrl+h",
  "command": "workbench.action.tasks.runTask",
  "args": "Run tests"
}

变量替换

创作任务配置时,拥有一组预定义的通用变量非常有用,例如活动文件 ( ${file}) 或工作区根文件夹 ( ${workspaceFolder})。VS Code 支持文件中字符串内的变量替换,您可以在变量参考tasks.json中查看预定义变量的完整列表。

注意:并非所有属性都接受变量替换。具体来说,仅commandargs、 和options支持变量替换。

下面是一个自定义任务配置的示例,它将当前打开的文件传递给 TypeScript 编译器。

{
  "label": "TypeScript compile",
  "type": "shell",
  "command": "tsc ${file}",
  "problemMatcher": ["$tsc"]
}

同样,您可以通过在名称前添加${config: 来引用项目的配置设置。例如,${config:python.formatting.autopep8Path}返回 Python 扩展设置formatting.autopep8Path

下面是自定义任务配置的示例,它使用设置定义的 autopep8 可执行文件在当前文件上执行 autopep8 python.formatting.autopep8Path

{
  "label": "autopep8 current file",
  "type": "process",
  "command": "${config:python.formatting.autopep8Path}",
  "args": ["--in-place", "${file}"]
}

如果要指定tasks.json或 的Python 扩展使用的选定 Python 解释器launch.json,可以使用该${command:python.interpreterPath}命令。

inputs如果简单的变量替换还不够,您还可以通过向文件添加一个部分来获取任务用户的输入tasks.json

输入示例

有关 的详细信息inputs,请参阅变量参考

操作系统特定属性

任务系统支持定义特定于操作系统的值(例如要执行的命令)。为此,请将操作系统特定的文字放入文件中tasks.json,并在该文字内指定相应的属性。

下面是一个使用 Node.js 可执行文件作为命令的示例,并且在 Windows 和 Linux 上的处理方式有所不同:

{
  "label": "Run Node",
  "type": "process",
  "windows": {
    "command": "C:\\Program Files\\nodejs\\node.exe"
  },
  "linux": {
    "command": "/usr/bin/node"
  }
}

有效的操作属性适用windows于 Windows、linuxLinux 和osxmacOS。在操作系统特定范围内定义的属性会覆盖在任务或全局范围内定义的属性。

全局任务

任务属性也可以在全局范围内定义。如果存在,它们将用于特定任务,除非它们定义具有不同值的相同属性。在下面的示例中,有一个全局presentation属性,它定义所有任务都应在新面板中执行:

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "presentation": {
    "panel": "new"
  },
  "tasks": [
    {
      "label": "TS - Compile current file",
      "type": "shell",
      "command": "tsc ${file}",
      "problemMatcher": ["$tsc"]
    }
  ]
}

提示:要访问全局范围tasks.json文件,请打开命令面板 ( ⇧⌘P (Windows、Linux Ctrl+Shift+P ) ) 并运行任务:打开用户任务命令。

PowerShell 中的字符转义

当默认 shell 是 PowerShell 或将任务配置为使用 PowerShell 时,您可能会看到意外的空格和引号转义。意外转义仅发生在 cmdlet 中,因为 VS Code 不知道您的命令是否包含 cmdlet。下面的示例 1 显示了一种无法使用 PowerShell 进行转义的情况。示例 2 显示了获得良好转义的最佳跨平台方法。在某些情况下,您可能无法遵循示例 2,并且需要执行示例 3 中所示的手动转义。

"tasks": [
    {
        "label": "PowerShell example 1 (unexpected escaping)",
        "type": "shell",
        "command": "Get-ChildItem \"Folder With Spaces\""
    },
    {
        "label": "PowerShell example 2 (expected escaping)",
        "type": "shell",
        "command": "Get-ChildItem",
        "args": ["Folder With Spaces"]
    },
    {
        "label": "PowerShell example 3 (manual escaping)",
        "type": "shell",
        "command": "& Get-ChildItem \\\"Folder With Spaces\\\""
    }
]

更改任务输出的编码

任务经常对磁盘上的文件进行操作。如果这些文件存储在磁盘上的编码与系统编码不同,则需要让作为任务执行的命令知道要使用哪种编码。由于这取决于操作系统和所使用的 shell,因此没有通用的解决方案来控制它。以下是有关如何使其发挥作用的建议和示例。

如果您需要调整编码,您应该检查更改操作系统使用的默认编码是否有意义,或者至少通过调整 shell 的配置文件来更改您使用的 shell。

如果您只需要针对特定​​任务调整它,则将更改编码所需的特定于操作系统的命令添加到任务命令行。以下示例适用于使用代码页 437 作为默认值的 Windows。该任务显示包含西里尔字符的文件的输出,因此需要代码页 866。列出文件的任务如下所示,假设默认 shell 设置为cmd.exe

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "label": "more",
      "type": "shell",
      "command": "chcp 866 && more russian.txt",
      "problemMatcher": []
    }
  ]
}

如果任务在 中执行PowerShell,则命令需要这样读chcp 866; more russian.txt。在 Linux 和 macOS 上,该locale命令可用于检查区域设置并调整必要的环境变量。

正在执行的任务示例

为了突出任务的强大功能,这里有一些示例,说明 VS Code 如何使用任务来集成 linter 和编译器等外部工具。

将 TypeScript 转换为 JavaScript

TypeScript主题包含一个示例,该示例创建一个任务以将 TypeScript 转换为 JavaScript 并观察 VS Code 中的任何相关错误。

将 Less 和 SCSS 转译为 CSS

CSS 主题提供了如何使用任务生成 CSS 文件的示例。

  1. 使用构建任务手动转译
  2. 使用文件观察器自动化编译步骤

定义问题匹配器

VS Code 内置了一些最常见的问题匹配器。然而,有很多编译器和 linting 工具,所有这些都会产生自己风格的错误和警告,因此您可能需要创建自己的问题匹配器。

我们有一个helloWorld.c程序,开发人员将printf错误地输入为printf。用gcc编译它会产生以下警告:

helloWorld.c:5:3: warning: implicit declaration of function ‘prinft’

我们想要生成一个问题匹配器,它可以捕获输出中的消息并在 VS Code 中显示相应的问题。问题匹配器严重依赖正则表达式。以下部分假设您熟悉正则表达式。

提示:我们发现RegEx101 Playground具有 ECMAScript (JavaScript) 风格,是开发和测试正则表达式的好方法。

捕获上述警告(和错误)的匹配器如下所示:

{
  // The problem is owned by the cpp language service.
  "owner": "cpp",
  // The file name for reported problems is relative to the opened folder.
  "fileLocation": ["relative", "${workspaceFolder}"],
  // The actual pattern to match problems in the output.
  "pattern": {
    // The regular expression. Example to match: helloWorld.c:5:3: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
    "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
    // The first match group matches the file name which is relative.
    "file": 1,
    // The second match group matches the line on which the problem occurred.
    "line": 2,
    // The third match group matches the column at which the problem occurred.
    "column": 3,
    // The fourth match group matches the problem's severity. Can be ignored. Then all problems are captured as errors.
    "severity": 4,
    // The fifth match group matches the message.
    "message": 5
  }
}

请注意,文件、行和消息属性是必需的。指定fileLocation任务输出生成的并在问题中匹配的文件路径是否为absoluterelative。如果任务同时生成绝对路径和相对路径,您可以使用autoDetect文件位置。使用 时autoDetect,首先将路径测试为绝对路径,如果文件不存在,则假定该路径是相对路径。

这是一个完成的tasks.json文件,其中包含上面的代码(已删除注释),并包含实际的任务详细信息:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "build",
      "command": "gcc",
      "args": ["-Wall", "helloWorld.c", "-o", "helloWorld"],
      "problemMatcher": {
        "owner": "cpp",
        "fileLocation": ["relative", "${workspaceFolder}"],
        "pattern": {
          "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
          "file": 1,
          "line": 2,
          "column": 3,
          "severity": 4,
          "message": 5
        }
      }
    }
  ]
}

在 VS Code 中运行它并按⇧⌘M(Windows、Linux Ctrl+Shift+M获取问题列表,会得到以下输出:

GCC 问题匹配器

注意: C /C++ 扩展包括 GCC 的问题匹配器,因此无需定义我们自己的。

还有更多属性可以在模式中使用。这些都是:

  • location - 如果问题位置是行或行、列或 startLine、startColumn、endLine、endColumn,则可以使用我们的通用位置匹配组。
  • endLine - 问题结束线的匹配组索引。如果编译器未提供结束行值,则可以省略。
  • endColumn - 问题结束列的匹配组索引。如果编译器未提供结束列值,则可以省略。
  • code - 问题代码的匹配组索引。如果编译器未提供代码值,则可以省略。

您还可以定义仅捕获文件的问题匹配器。为此,请定义 apattern并将可选kind属性设置为file。在这种情况下,不需要提供 alinelocation属性。

注意:如果属性设置为,功能模式必须至少为file和提供匹配组。如果未提供属性或属性设置为,则函数模式还必须提供或属性。messagekindfilekindkindlocationlinelocation

注意:问题匹配器仅解析给定命令的输出。如果您想要解析写入单独文件(例如日志文件)的输出,请让您运行的命令在完成执行之前打印出单独文件中的行。

定义多行问题匹配器

有些工具将源文件中发现的问题分散到多行中,特别是在使用时尚的报告器时。一个例子是ESLint;在时尚模式下,它会产生如下输出:

test.js
  1:0   error  Missing "use strict" statement                 strict
✖ 1 problems (1 errors, 0 warnings)

我们的问题匹配器是基于行的,因此我们需要使用与实际问题位置和消息不同的正则表达式来捕获文件名 (test.js)(1:0 错误缺少“use strict”语句)。

为此,请使用属性的问题模式数组pattern。通过这种方式,您可以为要匹配的每一行定义一个模式。

以下问题模式与时尚模式下 ESLint 的输出相匹配 - 但仍有一个小问题需要我们接下来解决。下面的代码使用第一个正则表达式来捕获文件名,第二个正则表达式用于捕获行、列、严重性、消息和错误代码:

{
  "owner": "javascript",
  "fileLocation": ["relative", "${workspaceFolder}"],
  "pattern": [
    {
      "regexp": "^([^\\s].*)$",
      "file": 1
    },
    {
      "regexp": "^\\s+(\\d+):(\\d+)\\s+(error|warning|info)\\s+(.*)\\s\\s+(.*)$",
      "line": 1,
      "column": 2,
      "severity": 3,
      "message": 4,
      "code": 5
    }
  ]
}

但是,如果一种资源存在多个问题,则此模式将不起作用。例如,想象 ESLint 的以下输出:

test.js
  1:0   error  Missing "use strict" statement                 strict
  1:9   error  foo is defined but never used                  no-unused-vars
  2:5   error  x is defined but never used                    no-unused-vars
  2:11  error  Missing semicolon                              semi
  3:1   error  "bar" is not defined                           no-undef
  4:1   error  Newline required at end of file but not found  eol-last
✖ 6 problems (6 errors, 0 warnings)

该模式的第一个正则表达式将匹配“test.js”,第二个“1:0 error ...”。下一行“1:9 error ...”已处理,但与第一个正则表达式不匹配,因此未捕获任何问题。

为了实现此目的,多行模式的最后一个正则表达式可以指定该loop属性。如果设置为 true,它会指示任务系统将多行匹配器的最后一个模式应用到输出中的行(只要正则表达式匹配)。

第一个模式(在本例中为匹配)捕获的信息test.js将与匹配该loop模式的每个后续行组合以创建多个问题。在此示例中,将产生六个问题。

这是一个问题匹配器,可以完全捕获 ESLint 时尚问题:

{
  "owner": "javascript",
  "fileLocation": ["relative", "${workspaceFolder}"],
  "pattern": [
    {
      "regexp": "^([^\\s].*)$",
      "file": 1
    },
    {
      "regexp": "^\\s+(\\d+):(\\d+)\\s+(error|warning|info)\\s+(.*)\\s\\s+(.*)$",
      "line": 1,
      "column": 2,
      "severity": 3,
      "message": 4,
      "code": 5,
      "loop": true
    }
  ]
}

注意:如果同一资源上的同一行和同一列出现多个问题,则只会显示一个问题。这适用于所有问题匹配器,而不仅仅是多行问题匹配器。

修改现有的问题匹配器

如果现有的问题匹配器接近您的需要,您可以在tasks.json任务中对其进行修改。例如,$tsc-watch问题匹配器仅适用于封闭文档。如果您想让它适用于所有文档,您可以修改它:

{
  "type": "npm",
  "script": "watch",
  "problemMatcher": {
    "base": "$tsc-watch",
    "applyTo": "allDocuments"
  },
  "isBackground": true
}

其他可修改的问题匹配器属性包括backgroundfileLocationownerpatternseveritysource

背景/观看任务

某些工具支持在后台运行,同时监视文件系统的更改,然后在磁盘上的文件更改时触发操作。通过Gulpnpm 模块gulp-watch提供此类功能。TypeScript 编译器tsc通过命令行选项内置了对此的支持--watch

为了提供后台任务在 VS Code 中处于活动状态并生成问题结果的反馈,问题匹配器必须使用其他信息来检测state输出中的这些更改。我们以tsc编译器为例。当编译器以监视模式启动时,它会向控制台打印以下附加信息:

> tsc --watch
12:30:36 PM - Compilation complete. Watching for file changes.

当磁盘上的文件发生更改且存在问题时,会出现以下输出:

12:32:35 PM - File change detected. Starting incremental compilation...
src/messages.ts(276,9): error TS2304: Cannot find name 'candidate'.
12:32:35 PM - Compilation complete. Watching for file changes.

查看输出显示以下模式:

  • 编译器在File change detected. Starting incremental compilation...打印到控制台时运行。
  • Compilation complete. Watching for file changes.当打印到控制台时,编译器停止。
  • 在这两个字符串之间报告了问题。
  • 编译器也会在初始启动后运行(不打印File change detected. Starting incremental compilation...到控制台)。

为了捕获此信息,问题匹配器可以提供属性background

对于tsc编译器来说,合适的background属性如下所示:

"background": {
    "activeOnStart": true,
    "beginsPattern": "^\\s*\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? - File change detected\\. Starting incremental compilation\\.\\.\\.",
    "endsPattern": "^\\s*\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? - Compilation complete\\. Watching for file changes\\."
}

除了background问题匹配器的属性之外,还必须将任务本身标记为,isBackground以便任务在后台保持运行。

tasks.json在监视模式下运行的任务的完整手工制作tsc如下所示:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "watch",
      "command": "tsc",
      "args": ["--watch"],
      "isBackground": true,
      "problemMatcher": {
        "owner": "typescript",
        "fileLocation": "relative",
        "pattern": {
          "regexp": "^([^\\s].*)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$",
          "file": 1,
          "location": 2,
          "severity": 3,
          "code": 4,
          "message": 5
        },
        "background": {
          "activeOnStart": true,
          "beginsPattern": "^\\s*\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? - File change detected\\. Starting incremental compilation\\.\\.\\.",
          "endsPattern": "^\\s*\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? - Compilation complete\\. Watching for file changes\\."
        }
      }
    }
  ]
}

下一步

这就是任务 - 让我们继续前进......

  • tasks.json 架构- 您可以查看完整的tasks.json架构和描述。
  • 基本编辑- 了解强大的 VS Code 编辑器。
  • 代码导航- 快速浏览源代码。
  • 语言支持- 了解我们支持的编程语言,这些语言均随 VS Code 一起提供并通过社区扩展提供。
  • 调试- 直接在 VS Code 编辑器中调试源代码。

常见问题

任务是否可以使用与为集成终端指定的 shell 不同的 shell?

是的。您可以使用该"terminal.integrated.automationProfile.*"设置来设置将用于 VS Code 中所有自动化(包括任务)的 shell。

    "terminal.integrated.automationProfile.windows": {
        "path": "cmd.exe"
    }

或者,您可以使用该options.shell属性覆盖任务的 shell。您可以针对每个任务、全局或每个平台进行设置。例如,要在 Windows 上使用 cmd.exe,您tasks.json需要包括:

{
    "version": "2.0.0",
    "windows": {
        "options": {
            "shell": {
                "executable": "cmd.exe",
                "args": [
                    "/d", "/c"
                ]
            }
        }
    },
    ...

后台任务可以用作prelaunchTasklaunch.json 中的 a 吗?

是的。由于后台任务将一直运行直到被杀死,因此后台任务本身没有任何信号表明它已“完成”。要将后台任务用作prelaunchTask,您必须为后台任务添加适当的后台problemMatcher,以便任务系统和调试系统有办法知道任务“完成”。

你的任务可能是:

{
  "type": "npm",
  "script": "watch",
  "problemMatcher": "$tsc-watch",
  "isBackground": true
}

注意:$tsc-watch后台问题匹配器,这是后台任务所需的。

prelaunchTask然后,您可以在文件中使用该任务launch.json

{
  "name": "Launch Extension",
  "type": "extensionHost",
  "request": "launch",
  "runtimeExecutable": "${execPath}",
  "args": ["--extensionDevelopmentPath=${workspaceRoot}"],
  "stopOnEntry": false,
  "sourceMaps": true,
  "outFiles": ["${workspaceRoot}/out/src/**/*.js"],
  "preLaunchTask": "npm: watch"
}

有关后台任务的更多信息,请转到后台/监视任务

为什么运行任务时出现“找不到命令”?

当您尝试运行的任务命令未被终端识别为可运行的命令时,会出现“命令未找到”消息。大多数情况下,发生这种情况是因为该命令被配置为 shell 启动脚本的一部分。任务以非登录和非交互方式运行,这意味着 shell 的启动脚本不会运行。nvm特别是众所周知,它使用启动脚本作为其配置的一部分。

有几种方法可以解决此问题:

  1. 确保您的命令位于您的路径上,并且不需要将启动脚本添加到您的路径中。这是解决问题最彻底的方法,也是推荐的解决方案。
  2. 您可以对任务进行一次性修复,使其以登录或交互方式运行。不建议这样做,因为它可能会产生其他后果。但是,它也可以快速轻松地修复单个任务。bash下面是一个使用 shell执行此操作的任务示例:
{
  "type": "npm",
  "script": "watch",
  "options": {
    "shell": {
      "args": ["-c", "-l"]
    }
  }
}

上述npm任务将bash使用命令 ( -c) 运行,就像任务系统默认执行的那样。bash但是,此任务也作为登录 shell ( )运行-l