通过任务与外部工具集成

市面上有许多工具可以自动化诸如布线、构建、打包、测试或部署软件系统等任务。例如TypeScript编译器、像ESLintTSLint这样的构建系统,以及MakeAnt、GulpJakeRakeMSBuild等构建系统。

VS Code 可以与多种外部工具通信

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

扩展还可以通过任务提供者贡献任务,这些贡献任务可以添加定义在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代码将生成一个tasks.json档案。下面显示的就是 tsc: build 任务变成默认的 build 任务:

{
  // 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: build任务标注为默认构建任务。你现在可以通过按⇧⌘B(Windows,Linux Ctrl+Shift+B来执行TypeScript编译器。

任务自动检测

VS Code 目前自动检测以下系统的任务:Gulp、Grunt、Jake 和 npm。我们正在与通讯扩展作者合作,为Maven和C#添加支持点网指挥部也是如此。如果你用Node.js作为运行时开发JavaScript应用,通常你会有package.json描述你的依赖和要运行的脚本的文件。如果你已经克隆了eslint-starter的示例,那么在全局菜单执行“运行任务”时会显示以下列表:

任务 ESLint 启动器

如果你还没安装,请通过运行安装必要的 npm 模块NPM 安装.现在打开server.js在语句末尾添加分号(注意 ESLint 起始程序假设语句无分号),然后再次执行执行任务。这次选择npm:lint 任务。当被要求使用问题匹配器时,选择ESLint stylish

任务 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 扫描 npm lint 脚本的输出,以查找使用 ESLint stylish 格式的问题。

对于吞咽、咕噜和杰克,任务自动检测也是一样的。以下是 vscode-node-debug 扩展检测到的任务示例。

Gulp 任务自动检测

提示:你可以通过快速打开⌘P(Windows,Linux Ctrl+P)来运行你的任务,只需输入“task”、空格和命令名。这里指的是“任务棉絮”。

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

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

自定义任务

并非所有任务或脚本都能在你的工作区自动检测。有时需要定义自己的定制任务。假设你有一个脚本来运行测试,以便正确设置某个环境。脚本存储在你工作区内的一个脚本文件夹中,并命名为test.sh适用于Linux和macOS和test.cmd适用于Windows。在全局终端菜单中运行配置任务,并从模板条目中选择创建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:用户界面中使用的任务标签。
  • 类型:任务的类型。对于自定义任务,这可以是贝壳流程.如果贝壳被指定时,命令被解释为shell命令(例如:bash、cmd或PowerShell)。如果流程被指定时,命令被解释为执行进程。
  • 命令:实际执行命令。
  • Windows:任何特定的Windows属性。在 Windows作系统上执行命令时,将用来替代默认属性。
  • :定义任务所属组。在示例中,它属于测试小组。属于测试组的任务可以通过命令面板中的“运行测试任务”来执行。
  • 展示:定义用户界面中任务输出的处理方式。在这个例子中,输出的集成端子为永远揭示和终端会在每次任务运行时创建。
  • 选项:覆盖 的默认值慢性消耗病(当前工作目录),环境(环境变量),或贝壳(默认壳)。选项可以按任务设置,也可以按全局或按平台设置。这里配置的环境变量只能在你的任务脚本或进程中引用,如果它们是你的 ARGS、命令或其他任务属性的一部分,就无法解析。
  • runOptions:定义任务何时以及如何运行。
  • hide:隐藏任务的运行任务快速选择,对于复合任务中不可独立运行的元素非常有用。

你可以用 IntelliSense 在你的tasks.json档案。用Trigger Suggest空间(Windows,Linux Ctrl+Space)调出建议,并在鼠标悬停或使用“阅读更多”(“i”)窗口阅读描述。

tasks.json IntelliSense

你也可以查看tasks.json模式

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

  • 如果只提供一个命令,任务系统会将该命令原样传递给底层的 shell。如果命令需要引用或转义才能正常工作,命令需要包含正确的引号或转义字符。例如,要列出包含空格的文件夹目录,bash执行的命令应为:ls “带空格的文件夹”.
{
  "label": "dir",
  "type": "shell",
  "command": "dir 'folder with spaces'"
}
  • 如果命令和参数都被提供,任务系统会使用单引号,且命令或参数包含空格。对于cmd.exe,使用双引号。下面这样的shell命令将在PowerShell中执行为dir “带空格的文件夹”.
{
  "label": "dir",
  "type": "shell",
  "command": "dir",
  "args": ["folder with spaces"]
}
  • 如果你想控制论证的引用方式,论元可以是指定值的字面形式和引用风格。下面的例子在带空格的论元中使用了转义代替引用。
{
  "label": "dir",
  "type": "shell",
  "command": "dir",
  "args": [
    {
      "value": "folder with spaces",
      "quoting": "escape"
    }
  ]
}

除了逃脱,还支持以下数值:

  • 强:使用壳的强引号机制,抑制字符串内的所有评估。在PowerShell以及Linux和macOS的shell中,使用单引号()。对于cmd.exe,使用。'"
  • weak:使用shell的弱引用机制,该机制仍会在字符串中评估表达式(例如环境变量)。在PowerShell以及Linux和macOS的shell中,使用双引号()。cmd.exe不支持弱引号,所以VS Code也用了。""

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

还有更多任务属性可以配置你的工作流程。你可以用 IntelliSense 配合 ⌃Space(Windows,Linux 的 Ctrl+Space来了解有效属性。

任务 IntelliSense

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

命令调色板中的任务

复合任务

你也可以用取决于财产。例如,如果你有一个带有客户端和服务器文件夹的工作区,且两者都包含构建脚本,你可以创建一个任务,在不同的终端启动两个构建脚本。如果你在取决于属性,默认情况下并行执行。

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”: “序列”然后你的任务依赖按列出的顺序执行取决于.有没有背景/监控任务用过取决于其中“dependsOrder”: “序列”必须有一个问题匹配器,能追踪他们“完成”的时间。接下来的任务执行任务二、任务三,然后是任务一。

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

用户级任务

您可以使用“任务:打开用户任务”命令创建不绑定到特定工作区或文件夹的用户级任务。只有贝壳以及流程任务可以在这里使用,因为其他任务类型需要工作区信息。

输出行为

有时你想控制集成终端面板在执行任务时的表现。比如,你可能想最大化编辑空间,只有在你觉得有问题时才查看任务输出。终端的行为可以通过以下方式进行控制呈现任务的属性。它提供以下特性:

  • 揭示:控制集成终端面板是否被移到前方。有效数值如下:
    • 永远- 面板总是被带到前面。这是默认的。
    • 绝不- 用户必须明确使用“终端视图”命令(⌃'(Windows,Linux Ctrl+')将终端面板移到前方>。
    • 寂静- 只有当输出未扫描错误和警告时,终端面板才会被移到前方。
  • 揭示问题:控制执行此任务时是否显示问题面板。优先于期权揭示.默认是绝不.
    • 永远- 执行该任务时,总是会显示问题面板。
    • onProblem- 只有在发现问题时才会显示问题面板。
    • 绝不- 执行该任务时从不显示问题面板。
  • 焦点:控制终端是否接收输入焦点。默认是错误.
  • echo:控制执行命令是否在终端中被echo。默认是确实如此.
  • showReuseMessage:控制是否显示“终端将被任务重用,按任意键关闭”消息。
  • 面板:控制终端实例是否在任务运行间共享。可能的数值有:
    • 共享- 终端共享,其他任务运行的输出被添加到同一终端。
    • 敬献- 终端专门用于特定任务。如果该任务再次执行,终端将被重复使用。然而,不同任务的输出会以不同的终端呈现。
    • - 该任务的每次执行都使用新的清洁终端。
  • clear:控制该任务运行前终端是否已清除。默认是错误.
  • 关闭:控制任务运行的终端在任务退出时是否关闭。默认是错误.
  • :通过分割面板控制任务是否在特定终端组中执行。同一组内的任务(由字符串值指定)会使用分割终端来展示,而不是新的终端面板。

你也可以修改终端面板的自动检测任务行为。例如,如果你想更改npm的输出行为:运行上面ESLint示例中的lint,可以添加呈现其属性:

{
  // 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"
      }
    }
  ]
}

你也可以将自定义任务与检测到任务的配置混合使用。Atasks.json它配置了 NPM:运行 lint 任务并添加了自定义的运行测试任务,看起来如下:

{
  // 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:通过“重运行最后任务”命令控制任务执行时变量的评估方式。默认为确实如此,意味着在任务重运行时变量会被重新评估。当设置为错误将使用上一次任务运行中解析的变量值。
  • runOn:指定任务运行时间。
    • 默认- 任务仅在通过执行任务命令执行时才会被执行。
    • 文件夹打开- 当打开包含文件夹时,任务将被执行。第一次打开包含任务的文件夹时文件夹打开系统会询问您是否希望允许任务自动运行在该文件夹中。你可以之后通过“管理自动任务”命令,在“允许自动任务”和“不允许自动任务”之间选择更改决定。
  • instanceLimit - 允许同时运行任务的实例数。默认值为1.

自定义自动检测任务

如上所述,你可以在tasks.json档案。通常这样做是为了修改演示属性,或附加问题匹配器以扫描任务输出中的错误和警告。你可以直接从运行任务列表中自定义任务,方法是点击右侧的齿轮图标,将对应的任务引用插入tasks.json档案。假设你有以下Gulp文件,用ESLint来填充JavaScript文件(文件取自 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时尚)或修改展示设置。

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

VS Code 可以处理带有问题匹配器的任务输出。问题匹配器扫描任务输出文本中的已知警告或错误字符串,并在编辑器和问题面板中内联报告。VS Code 自带了几款“盒装”问题匹配器:

  • TypeScript$tsc假设输出文件名相对于打开的文件夹。
  • TypeScript 观察$tsc手表比赛问题报告来自TSC在观察模式下执行编译器。
  • JSHint$jshint假设文件名被报告为绝对路径。
  • JSHint时尚$jshint风格假设文件名被报告为绝对路径。
  • ESLint Compact$eslint紧致假设输出文件名相对于打开的文件夹。
  • ESLint时尚$eslint时尚假设输出文件名相对于打开的文件夹。
  • 开始$go比赛问题报告来自编译器。假设文件名是相对于打开的文件夹。
  • CSharp 和 VB 编译器$mscompile假设文件名被报告为绝对路径。
  • Lessc编译器$lessc假设文件名被报告为绝对路径。
  • Node Sass 编译器$node-泼辣假设文件名被报告为绝对路径。

你也可以创建自己的问题匹配器,我们将在后面部分详细讨论。

将键盘快捷方式绑定到任务

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

例如,绑定Ctrl+H从上方的“运行测试”任务中,添加以下内容到keybindings.json文件:

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

变量替换

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

注:并非所有属性都接受变量替换。具体来说,只有指挥,args, 和选项支持变量替换。

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

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

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

以下是一个自定义任务配置的示例,该配置使用由python.formatting.autopep8Path地点:

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

如果你想指定 Python 扩展所选的 Python 解释器tasks.jsonlaunch.json,你可以使用${command:python.interpreterPath}指挥部。

如果简单的变量替换还不够,你也可以通过添加一个输入tasks.json档案。

输入示例

欲了解更多信息输入,参见变量参考文献

作系统特定属性

任务系统支持定义特定作系统的值(例如,要执行的命令)。为此,将作系统特定的字面值放入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,Linux对于Linux,以及OSXmacOS版。作系统特定作用域中定义的属性覆盖任务或全局范围中定义的属性。

全球任务

任务属性也可以在全局范围中定义。如果存在,除非定义了相同属性但值不同,否则它们会用于特定任务。在下面的例子中,存在一个全局呈现属性,定义所有任务都应在新面板中执行:

{
  // 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配置文件来更改它。

如果你只需要针对特定任务调整,那就添加作系统专用命令,用来更改任务命令行的编码。以下示例是Windows默认使用437代码页。该任务显示包含西里尔字母的文件输出,因此需要代码页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;更多russian.txt.在Linux和macOS上,地点命令可用于检查位置并调整必要的环境变量。

任务实际作示例

为了突出任务的力量,以下是VS Code如何利用任务集成外部工具(如linter和编译器)的例子。

将TypeScript转为JavaScript

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

将 Less 和 SCSS 转为 CSS

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

  1. 使用构建任务手动转译
  2. 通过文件监视器自动化编译步骤

定义问题匹配器

VS Code 提供了一些最常见的问题匹配器“内置”功能。不过,市面上有很多编译器和打印工具,它们各自会产生不同的错误和警告,所以你可能需要自己做一个问题匹配器。

我们有一个helloWorld.c开发者错误地将 printf 打错为 prinft。用gcc编译后会显示以下警告:

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

我们希望生成一个问题匹配器,能够在输出中捕获消息,并在 VS Code 中显示对应的问题。问题匹配器高度依赖正则表达式。下面部分假设你熟悉正则表达式。

提示:我们发现带有ECMAScript(JavaScript)风格的RegEx101游乐场是开发和测试正则表达式的绝佳方式。

捕捉上述警告(及错误)的匹配器如下:

{
  // 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 name that will be shown as the source of the problem.
  "source": "gcc",
  // 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指定任务输出产生的文件路径是否与问题匹配绝对的相关关系.如果任务产生绝对路径和相对路径,你可以使用自动检测档案所在地。其中自动检测路径首先被测试为绝对路径,如果文件不存在,则假设路径是相对路径。

严重程度如果模式中没有问题严重度,指定使用哪个问题严重度。可能的值严重程度错误,警告,或者信息.

这里是完成的tasks.json包含上述代码(注释已移除)并包裹实际任务细节的文件:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "build",
      "command": "gcc",
      "args": ["-Wall", "helloWorld.c", "-o", "helloWorld"],
      "problemMatcher": {
        "owner": "cpp",
        "fileLocation": ["relative", "${workspaceFolder}"],
        "source": "gcc",
        "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 的问题匹配器,因此无需自定义。

还有几个属性可以用于图案内部。这些包括:

  • 位置——如果问题位置是行、行、列或起始行、起始列、结束行、结束列,那么可以使用我们的通用位置匹配组。
  • endLine - 问题终点线的匹配组索引。如果编译器没有提供端行值,可以省略。
  • endColumn - 问题结束列的匹配组索引。如果编译器未提供端列值,可以省略。
  • 代码——问题代码的匹配组索引。如果编译器没有提供代码值,可以省略。

你也可以定义一个只捕获文件的问题匹配器。为此,定义一个图案可选属性设置为文件.在这种情况下,无需提供线路位置财产。

注:函数模式至少必须提供一个匹配群文件以及信息如果属性设置为文件.如果没有财产被提供或属性设置为位置,函数模式必须提供线路位置财产也一样。

注:问题匹配器只解析给定命令的输出。如果你想解析写入独立文件(例如日志文件)的输出,可以让命令在文件执行完成前打印出该独立文件的行。

定义多行问题匹配器

有些工具将源文件中发现的问题分散到多行,尤其是在使用时尚记者时。一个例子是ESLint;在时尚模式下,输出如下:

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

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

为此,使用数组问题模式图案财产。这样你就能为每条想要匹配的行定义一个图案。

以下问题模式与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 错误......”。下一行“1:9错误......”处理后未被第一个正则表达式匹配,因此不捕获问题。

为了实现这一点,多线模式的最后一个正则表达式可以指定环形财产。如果设置为true,则指示任务系统对输出中的行施加多行匹配器的最后一个模式,只要正则表达式匹配。

第一个模式捕获的信息,在此中匹配test.js,将与后续匹配的每行合并环形模式会制造多个问题。在这个例子中,会产生六个问题。

这里有一个问题匹配器,可以完全捕捉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手表问题匹配器仅适用于已关闭的文档。如果你想让它适用于所有文档,可以修改:

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

其他可修改的问题匹配器性质包括背景,fileLocation,所有者,图案,严重程度, 和资料来源.

背景/监控任务

有些工具支持在后台运行,同时监控文件系统是否有变化,然后在磁盘上文件发生变化时触发作。其中咽口水此类功能通过NPM模块Gulp-Watch提供。TypeScript编译器TSC通过——看着命令行选项。

为了反馈后台任务在 VS Code 中激活并产生问题结果,问题匹配器必须使用额外信息来检测这些任务输出发生变化。我们来拿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.

查看输出显示以下模式:

  • 编译器运行于检测到文件变更。开始增量编译......打印在控制台上。
  • 编译器停止于合辑完成。注意文件变动。打印在控制台上。
  • 在这两根弦之间会报告问题。
  • 编译器在初始启动后(不打印)也会运行检测到文件变更。开始增量编译......控制台)。

为了捕捉这些信息,问题匹配器可以提供背景财产。

对于TSC编译器,一个合适的背景性质如下:

"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对于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 Schema - 你可以完整阅读tasks.json模式和描述。
  • 基础编辑——了解强大的VS Code编辑器。
  • 代码导航——快速浏览源代码。
  • 语言支持——了解我们支持的编程语言,既有随VS Code自带,也有通过社区扩展提供的。
  • 调试——直接在VS Code编辑器中调试源代码。

常见问题

任务可以使用与集成终端指定的不同的外壳吗?

是的。你可以使用“terminal.integrated.automationProfile.*”设置用于VS Code中所有自动化的shell,包括任务。

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

或者,你也可以用options.shell财产。你可以根据任务、全局或平台设置。例如,在Windows上使用cmd.exe,你的tasks.json将包括:

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

后台任务可以作为prelaunchTask(预发布任务)launch.json?

是的。由于后台任务会运行直到被杀,单独的后台任务不会显示“完成”。将后台任务作为prelaunchTask(预发布任务)你必须添加合适的背景problemMatcher后台任务,这样任务系统和调试系统就能知道任务“完成”了。

你的任务可能是:

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

注:$tsc手表背景问题匹配器,而后台任务则需要。

然后你可以把这个任务当作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 启动脚本不会被运行。NVM特别是,已知在配置中使用启动脚本。

解决这个问题有几种方法:

  1. 确保你的命令在路径上,且不需要启动脚本添加到路径中。这是解决问题最彻底的方法,也是推荐的解决方案。
  2. 你可以一次性修复你的任务,让它以登录或交互方式运行。这不建议,因为可能会有其他后果。不过,它也可以是单项任务的快速且简单的解决方案。下面是一个任务示例,用作为壳:
{
  "type": "npm",
  "script": "watch",
  "options": {
    "shell": {
      "args": ["-c", "-l"]
    }
  }
}

以上内容NPM任务将运行命令为 (-c),就像任务系统默认的那样。不过,这个任务也同样运行作为登录壳(-我).