現已釋出!閱讀關於 11 月新增功能和修復的內容。

任務提供程式

使用者通常在 Visual Studio Code 中透過 tasks.json 檔案定義 任務。但是,在軟體開發過程中,有些任務可以透過 VS Code 擴充套件中的任務提供者自動檢測到。當從 VS Code 中執行“任務: 執行任務”命令時,所有活動的任務提供者都會貢獻使用者可以執行的任務。雖然 tasks.json 檔案允許使用者手動為特定的資料夾或工作區定義任務,但任務提供者可以檢測工作區的詳細資訊,然後自動建立相應的 VS Code 任務。例如,任務提供者可以檢查是否存在特定的構建檔案(如 makeRakefile),並建立一個構建任務。本主題介紹擴充套件如何自動檢測並向終端使用者提供任務。

本指南將教你如何構建一個任務提供者,該提供者可以自動檢測在 Rakefiles 中定義的任務。完整的原始碼位於:https://github.com/microsoft/vscode-extension-samples/tree/main/task-provider-sample

任務定義

為了在系統中唯一地標識一個任務,貢獻任務的擴充套件需要定義標識任務的屬性。在 Rake 示例中,任務定義如下所示:

"taskDefinitions": [
    {
        "type": "rake",
        "required": [
            "task"
        ],
        "properties": {
            "task": {
                "type": "string",
                "description": "The Rake task to customize"
            },
            "file": {
                "type": "string",
                "description": "The Rake file that provides the task. Can be omitted."
            }
        }
    }
]

這為 rake 任務貢獻了一個任務定義。任務定義有兩個屬性:taskfiletask 是 Rake 任務的名稱,file 指向包含該任務的 Rakefiletask 屬性是必需的,file 屬性是可選的。如果省略 file 屬性,則使用工作區資料夾根目錄下的 Rakefile

when 子句

任務定義可以包含一個可選的 when 屬性。when 屬性指定了該型別任務可用的條件。when 屬性的功能與 VS Code 中 其他地方具有 when 屬性的功能相同。在建立任務定義時,應始終考慮以下上下文:

  • shellExecutionSupported:當 VS Code 可以執行 ShellExecution 任務時為 true,例如當 VS Code 作為桌面應用程式執行時,或使用遠端擴充套件(如 Dev Containers)時。
  • processExecutionSupported:當 VS Code 可以執行 ProcessExecution 任務時為 true,例如當 VS Code 作為桌面應用程式執行時,或使用遠端擴充套件(如 Dev Containers)時。目前,它將始終具有與 shellExecutionSupported 相同的值。
  • customExecutionSupported:當 VS Code 可以執行 CustomExecution 時為 true。此值始終為 true。

任務提供者

與支援程式碼補全的語言提供者類似,擴充套件可以註冊一個任務提供者來計算所有可用的任務。這透過 vscode.tasks 名稱空間完成,如下面的程式碼片段所示:

import * as vscode from 'vscode';

let rakePromise: Thenable<vscode.Task[]> | undefined = undefined;
const taskProvider = vscode.tasks.registerTaskProvider('rake', {
  provideTasks: () => {
    if (!rakePromise) {
      rakePromise = getRakeTasks();
    }
    return rakePromise;
  },
  resolveTask(_task: vscode.Task): vscode.Task | undefined {
    const task = _task.definition.task;
    // A Rake task consists of a task and an optional file as specified in RakeTaskDefinition
    // Make sure that this looks like a Rake task by checking that there is a task.
    if (task) {
      // resolveTask requires that the same definition object be used.
      const definition: RakeTaskDefinition = <any>_task.definition;
      return new vscode.Task(
        definition,
        _task.scope ?? vscode.TaskScope.Workspace,
        definition.task,
        'rake',
        new vscode.ShellExecution(`rake ${definition.task}`)
      );
    }
    return undefined;
  }
});

provideTasks 類似,VS Code 會呼叫 resolveTask 方法以從擴充套件獲取任務。resolveTask 可以替代 provideTasks 呼叫,並且旨在為實現它的提供者提供可選的效能提升。例如,如果使用者有一個執行擴充套件提供的任務的鍵繫結,VS Code 最好呼叫該任務提供者的 resolveTask 並快速獲取一個任務,而不是呼叫 provideTasks 並等待擴充套件提供所有任務。允許使用者關閉單個任務提供者的設定是一個好習慣,因此這很常見。使用者可能會注意到來自特定提供者的任務獲取速度較慢,並關閉該提供者。在這種情況下,使用者可能仍然在其 tasks.json 中引用該提供者的某些任務。如果未實現 resolveTask,則會顯示一個警告,指出其 tasks.json 中的任務未建立。使用 resolveTask,擴充套件仍然可以為 tasks.json 中定義的任務提供任務。

getRakeTasks 的實現執行以下操作:

  • 使用 rake -AT -f Rakefile 命令列出每個工作區資料夾中 Rakefile 中定義的所有 rake 任務。
  • 解析標準輸出。
  • 為每個列出的任務建立一個 vscode.Task 實現。

由於 Rake 任務例項化需要 package.json 檔案中定義的任務定義,VS Code 還使用 TypeScript 介面定義了結構,如下所示:

interface RakeTaskDefinition extends vscode.TaskDefinition {
  /**
   * The task name
   */
  task: string;

  /**
   * The rake file containing the task
   */
  file?: string;
}

假設輸出來自第一個工作區資料夾中名為 compile 的任務,則相應的任務建立如下所示:

let task = new vscode.Task(
  { type: 'rake', task: 'compile' },
  vscode.workspace.workspaceFolders[0],
  'compile',
  'rake',
  new vscode.ShellExecution('rake compile')
);

為輸出中列出的每個任務,使用上述模式建立相應的 VS Code 任務,然後從 getRakeTasks 呼叫返回所有任務的陣列。

ShellExecution 在特定於作業系統的 shell 中執行 rake compile 命令(例如,在 Windows 上,命令將在 PowerShell 中執行;在 Ubuntu 上,將在 bash 中執行)。如果任務應直接執行程序(而不啟動 shell),則可以使用 vscode.ProcessExecutionProcessExecution 的優點是擴充套件可以完全控制傳遞給程序的引數。使用 ShellExecution 會利用 shell 命令解釋(如 bash 下的萬用字元擴充套件)。如果 ShellExecution 使用單個命令列建立,則擴充套件需要確保命令內的正確引用和轉義(例如,以處理空格)。

CustomExecution

總的來說,最好使用 ShellExecutionProcessExecution,因為它們很簡單。但是,如果您的任務在執行之間需要大量儲存狀態,作為單獨的指令碼或程序效果不佳,或者需要大量的輸出處理,那麼 CustomExecution 可能是一個不錯的選擇。CustomExecution 的現有用途通常是針對複雜的構建系統。CustomExecution 只有一個回撥,在任務執行時執行。這提供了更大的任務靈活性,但也意味著任務提供者負責任何必要的程序管理和輸出解析。任務提供者還負責實現 Pseudoterminal 並從 CustomExecution 回撥返回它。

return new vscode.Task(
  definition,
  vscode.TaskScope.Workspace,
  `${flavor} ${flags.join(' ')}`,
  CustomBuildTaskProvider.CustomBuildScriptType,
  new vscode.CustomExecution(
    async (): Promise<vscode.Pseudoterminal> => {
      // When the task is executed, this callback will run. Here, we setup for running the task.
      return new CustomBuildTaskTerminal(
        this.workspaceRoot,
        flavor,
        flags,
        () => this.sharedState,
        (state: string) => (this.sharedState = state)
      );
    }
  )
);

完整的示例,包括 Pseudoterminal 的實現,位於 https://github.com/microsoft/vscode-extension-samples/tree/main/task-provider-sample/src/customTaskProvider.ts

© . This site is unofficial and not affiliated with Microsoft.