src/vs/workbench/contrib/tasks/common/tasks.ts

1442 LOC · 1051 covered · 391 uncovered · 115 ranges · 131 concepts · 17 introducers · 59 tests

File neighbourhood

The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.

1 > /*--------------------------------------------------------------------------------------------- taskConfiguration.ts ×80
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import * as nls from '../../../../nls.js';
7 > import * as Types from '../../../../base/common/types.js';
8 > import * as resources from '../../../../base/common/resources.js';
9 > import { IJSONSchemaMap } from '../../../../base/common/jsonSchema.js';
10 > import * as Objects from '../../../../base/common/objects.js';
11 > import { UriComponents, URI } from '../../../../base/common/uri.js';
12 >
13 > import { ProblemMatcher } from './problemMatcher.js';
14 > import { IWorkspaceFolder, IWorkspace } from '../../../../platform/workspace/common/workspace.js';
15 > import { RawContextKey, ContextKeyExpression } from '../../../../platform/contextkey/common/contextkey.js';
16 > import { TaskDefinitionRegistry } from './taskDefinitionRegistry.js';
17 > import { IExtensionDescription } from '../../../../platform/extensions/common/extensions.js';
18 > import { ConfigurationTarget } from '../../../../platform/configuration/common/configuration.js';
19 > import { TerminalExitReason } from '../../../../platform/terminal/common/terminal.js';
20 > import { Codicon } from '../../../../base/common/codicons.js';
21 > import { registerIcon } from '../../../../platform/theme/common/iconRegistry.js';
22 >
23 >
24 >
25 > export const USER_TASKS_GROUP_KEY = 'settings';
26 >
27 > export const TASK_RUNNING_STATE = new RawContextKey<boolean>('taskRunning', false, nls.localize('tasks.taskRunningContext', "Whether a task is currently running."));
28 > /** Whether the active terminal is a task terminal. */
29 > export const TASK_TERMINAL_ACTIVE = new RawContextKey<boolean>('taskTerminalActive', false, nls.localize('taskTerminalActive', "Whether the active terminal is a task terminal."));
30 > export const TASKS_CATEGORY = nls.localize2('tasksCategory', "Tasks");
31 >
32 > export enum ShellQuoting {
33 > /**
34 > * Use character escaping.
35 > */
36 > Escape = 1,
37 >
38 > /**
39 > * Use strong quoting
40 > */
41 > Strong = 2,
42 >
43 > /**
44 > * Use weak quoting.
45 > */
46 > Weak = 3,
47 > }
48 >
49 > export const CUSTOMIZED_TASK_TYPE = '$customized';
50 >
51 > export namespace ShellQuoting {
52 > export function from(this: void, value: string): ShellQuoting {
53 if (!value) {
54 return ShellQuoting.Strong;
55 }
56 switch (value.toLowerCase()) {
57 case 'escape':
58 return ShellQuoting.Escape;
59 case 'strong':
60 return ShellQuoting.Strong;
61 case 'weak':
62 return ShellQuoting.Weak;
63 default:
64 return ShellQuoting.Strong;
65 }
66 }
68 >
69 > export interface IShellQuotingOptions {
70 > /**
71 > * The character used to do character escaping.
72 > */
73 > escape?: string | {
74 > escapeChar: string;
75 > charsToEscape: string;
76 > };
77 >
78 > /**
79 > * The character used for string quoting.
80 > */
81 > strong?: string;
82 >
83 > /**
84 > * The character used for weak quoting.
85 > */
86 > weak?: string;
87 > }
88 >
89 > export interface IShellConfiguration {
90 > /**
91 > * The shell executable.
92 > */
93 > executable?: string;
94 >
95 > /**
96 > * The arguments to be passed to the shell executable.
97 > */
98 > args?: string[];
99 >
100 > /**
101 > * Which kind of quotes the shell supports.
102 > */
103 > quoting?: IShellQuotingOptions;
104 > }
105 >
106 > export interface CommandOptions {
107 >
108 > /**
109 > * The shell to use if the task is a shell command.
110 > */
111 > shell?: IShellConfiguration;
112 >
113 > /**
114 > * The current working directory of the executed program or shell.
115 > * If omitted VSCode's current workspace root is used.
116 > */
117 > cwd?: string;
118 >
119 > /**
120 > * The environment of the executed program or shell. If omitted
121 > * the parent process' environment is used.
122 > */
123 > env?: { [key: string]: string };
124 > }
125 >
126 > export namespace CommandOptions {
127 > export const defaults: CommandOptions = { cwd: '${workspaceFolder}' };
128 > }
129 >
130 > export enum RevealKind {
131 > /**
132 > * Always brings the terminal to front if the task is executed.
133 > */
134 > Always = 1,
135 >
136 > /**
137 > * Only brings the terminal to front if a problem is detected executing the task
138 > * e.g. the task couldn't be started,
139 > * the task ended with an exit code other than zero,
140 > * or the problem matcher found an error.
141 > */
142 > Silent = 2,
143 >
144 > /**
145 > * The terminal never comes to front when the task is executed.
146 > */
147 > Never = 3
148 > }
149 >
150 > export namespace RevealKind {
151 > export function fromString(this: void, value: string): RevealKind {
152 > switch (value.toLowerCase()) { tasks.ts ×5
153 > case 'always':
154 > return RevealKind.Always; tasks.ts ×1
155 > case 'silent': tasks.ts ×5
156 > return RevealKind.Silent; tasks.ts ×1
157 > case 'never': tasks.ts ×5
158 > return RevealKind.Never; tasks.ts ×1
159 > default: tasks.ts ×5
160 return RevealKind.Always;
161 > } tasks.ts ×5
162 > }
164 >
165 > export enum RevealProblemKind {
166 > /**
167 > * Never reveals the problems panel when this task is executed.
168 > */
169 > Never = 1,
170 >
171 >
172 > /**
173 > * Only reveals the problems panel if a problem is found.
174 > */
175 > OnProblem = 2,
176 >
177 > /**
178 > * Never reveals the problems panel when this task is executed.
179 > */
180 > Always = 3
181 > }
182 >
183 > export namespace RevealProblemKind {
184 > export function fromString(this: void, value: string): RevealProblemKind {
185 switch (value.toLowerCase()) {
186 case 'always':
187 return RevealProblemKind.Always;
188 case 'never':
189 return RevealProblemKind.Never;
190 case 'onproblem':
191 return RevealProblemKind.OnProblem;
192 default:
193 return RevealProblemKind.OnProblem;
194 }
195 }
197 >
198 > export enum PanelKind {
199 >
200 > /**
201 > * Shares a panel with other tasks. This is the default.
202 > */
203 > Shared = 1,
204 >
205 > /**
206 > * Uses a dedicated panel for this tasks. The panel is not
207 > * shared with other tasks.
208 > */
209 > Dedicated = 2,
210 >
211 > /**
212 > * Creates a new panel whenever this task is executed.
213 > */
214 > New = 3
215 > }
216 >
217 > export namespace PanelKind {
218 > export function fromString(value: string): PanelKind {
219 switch (value.toLowerCase()) {
220 case 'shared':
221 return PanelKind.Shared;
222 case 'dedicated':
223 return PanelKind.Dedicated;
224 case 'new':
225 return PanelKind.New;
226 default:
227 return PanelKind.Shared;
228 }
229 }
231 >
232 > export interface IPresentationOptions {
233 > /**
234 > * Controls whether the task output is reveal in the user interface.
235 > * Defaults to `RevealKind.Always`.
236 > */
237 > reveal: RevealKind;
238 >
239 > /**
240 > * Controls whether the problems pane is revealed when running this task or not.
241 > * Defaults to `RevealProblemKind.Never`.
242 > */
243 > revealProblems: RevealProblemKind;
244 >
245 > /**
246 > * Controls whether the command associated with the task is echoed
247 > * in the user interface.
248 > */
249 > echo: boolean;
250 >
251 > /**
252 > * Controls whether the panel showing the task output is taking focus.
253 > */
254 > focus: boolean;
255 >
256 > /**
257 > * Controls if the task panel is used for this task only (dedicated),
258 > * shared between tasks (shared) or if a new panel is created on
259 > * every task execution (new). Defaults to `TaskInstanceKind.Shared`
260 > */
261 > panel: PanelKind;
262 >
263 > /**
264 > * Controls whether to show the "Terminal will be reused by tasks, press any key to close it" message.
265 > */
266 > showReuseMessage: boolean;
267 >
268 > /**
269 > * Controls whether to clear the terminal before executing the task.
270 > */
271 > clear: boolean;
272 >
273 > /**
274 > * Controls whether the task is executed in a specific terminal group using split panes.
275 > */
276 > group?: string;
277 >
278 > /**
279 > * Controls whether the terminal that the task runs in is closed when the task completes.
280 > */
281 > close?: boolean;
282 >
283 > /**
284 > * Controls whether to preserve the task name in the terminal after task completion.
285 > */
286 > preserveTerminalName?: boolean;
287 > }
288 >
289 > export namespace PresentationOptions {
290 > export const defaults: IPresentationOptions = {
291 > echo: true, reveal: RevealKind.Always, revealProblems: RevealProblemKind.Never, focus: false, panel: PanelKind.Shared, showReuseMessage: true, clear: false, preserveTerminalName: false
292 > };
293 > }
294 >
295 > export enum RuntimeType {
296 > Shell = 1,
297 > Process = 2,
298 > CustomExecution = 3
299 > }
300 >
301 > export namespace RuntimeType {
302 > export function fromString(value: string): RuntimeType {
303 > switch (value.toLowerCase()) { tasks.ts ×4
304 > case 'shell':
305 > return RuntimeType.Shell;
306 > case 'process':
307 return RuntimeType.Process;
308 > case 'customExecution': tasks.ts ×4
309 return RuntimeType.CustomExecution;
310 > default: tasks.ts ×4
311 return RuntimeType.Process;
312 > } tasks.ts ×4
313 > }
314 > export function toString(value: RuntimeType): string { taskConfiguration.ts ×80
315 switch (value) {
316 case RuntimeType.Shell: return 'shell';
317 case RuntimeType.Process: return 'process';
318 case RuntimeType.CustomExecution: return 'customExecution';
319 default: return 'process';
320 }
321 }
323 >
324 > export interface IQuotedString {
325 > value: string;
326 > quoting: ShellQuoting;
327 > }
328 >
329 > export type CommandString = string | IQuotedString;
330 >
331 > export namespace CommandString {
332 > export function value(value: CommandString): string {
333 > if (Types.isString(value)) { taskConfiguration.ts ×3
334 > return value;
335 > } else {
336 return value.value;
337 }
340 >
341 > export interface ICommandConfiguration {
342 >
343 > /**
344 > * The task type
345 > */
346 > runtime?: RuntimeType;
347 >
348 > /**
349 > * The command to execute
350 > */
351 > name?: CommandString;
352 >
353 > /**
354 > * Additional command options.
355 > */
356 > options?: CommandOptions;
357 >
358 > /**
359 > * Command arguments.
360 > */
361 > args?: CommandString[];
362 >
363 > /**
364 > * The task selector if needed.
365 > */
366 > taskSelector?: string;
367 >
368 > /**
369 > * Whether to suppress the task name when merging global args
370 > *
371 > */
372 > suppressTaskName?: boolean;
373 >
374 > /**
375 > * Describes how the task is presented in the UI.
376 > */
377 > presentation?: IPresentationOptions;
378 > }
379 >
380 > export namespace TaskGroup {
381 > export const Clean: TaskGroup = { _id: 'clean', isDefault: false };
382 >
383 > export const Build: TaskGroup = { _id: 'build', isDefault: false };
384 >
385 > export const Rebuild: TaskGroup = { _id: 'rebuild', isDefault: false };
386 >
387 > export const Test: TaskGroup = { _id: 'test', isDefault: false };
388 >
389 > export function is(value: unknown): value is string {
390 > return value === Clean._id || value === Build._id || value === Rebuild._id || value === Test._id; taskConfiguration.ts ×2
391 > }
393 > export function from(value: string | TaskGroup | undefined): TaskGroup | undefined {
394 > if (value === undefined) { tasks.ts ×4
395 > return undefined; tasks.ts ×1
396 > } else if (Types.isString(value)) { tasks.ts ×4
397 if (is(value)) {
398 return { _id: value, isDefault: false };
399 }
400 return undefined;
401 > } else { tasks.ts ×1
402 > return value;
403 > }
404 > } tasks.ts ×4
406 >
407 > export interface TaskGroup {
408 > _id: string;
409 > isDefault?: boolean | string;
410 > }
411 >
412 > export const enum TaskScope {
413 > Global = 1,
414 > Workspace = 2,
415 > Folder = 3
416 > }
417 >
418 > export namespace TaskSourceKind {
419 > export const Workspace: 'workspace' = 'workspace';
420 > export const Extension: 'extension' = 'extension';
421 > export const InMemory: 'inMemory' = 'inMemory';
422 > export const WorkspaceFile: 'workspaceFile' = 'workspaceFile';
423 > export const User: 'user' = 'user';
424 >
425 > export function toConfigurationTarget(kind: string): ConfigurationTarget {
426 switch (kind) {
427 case TaskSourceKind.User: return ConfigurationTarget.USER;
428 case TaskSourceKind.WorkspaceFile: return ConfigurationTarget.WORKSPACE;
429 default: return ConfigurationTarget.WORKSPACE_FOLDER;
430 }
431 }
433 >
434 > export interface ITaskSourceConfigElement {
435 > workspaceFolder?: IWorkspaceFolder;
436 > workspace?: IWorkspace;
437 > file: string;
438 > index: number;
439 > element: unknown;
440 > }
441 >
442 > export interface ITaskConfig {
443 > label: string;
444 > task?: CommandString;
445 > type?: string;
446 > command?: string | CommandString;
447 > args?: string[] | CommandString[];
448 > presentation?: IPresentationOptions;
449 > isBackground?: boolean;
450 > problemMatcher?: Types.SingleOrMany<string>;
451 > group?: string | TaskGroup;
452 > }
453 >
454 > interface IBaseTaskSource {
455 > readonly kind: string;
456 > readonly label: string;
457 > }
458 >
459 > export interface IWorkspaceTaskSource extends IBaseTaskSource {
460 > readonly kind: 'workspace';
461 > readonly config: ITaskSourceConfigElement;
462 > readonly customizes?: KeyedTaskIdentifier;
463 > }
464 >
465 > export interface IExtensionTaskSource extends IBaseTaskSource {
466 > readonly kind: 'extension';
467 > readonly extension?: string;
468 > readonly scope: TaskScope;
469 > readonly workspaceFolder: IWorkspaceFolder | undefined;
470 > }
471 >
472 > export interface IExtensionTaskSourceTransfer {
473 > __workspaceFolder: UriComponents;
474 > __definition: { type: string;[name: string]: unknown };
475 > }
476 >
477 > export interface IInMemoryTaskSource extends IBaseTaskSource {
478 > readonly kind: 'inMemory';
479 > }
480 >
481 > export interface IUserTaskSource extends IBaseTaskSource {
482 > readonly kind: 'user';
483 > readonly config: ITaskSourceConfigElement;
484 > readonly customizes?: KeyedTaskIdentifier;
485 > }
486 >
487 > export interface WorkspaceFileTaskSource extends IBaseTaskSource {
488 > readonly kind: 'workspaceFile';
489 > readonly config: ITaskSourceConfigElement;
490 > readonly customizes?: KeyedTaskIdentifier;
491 > }
492 >
493 > export type TaskSource = IWorkspaceTaskSource | IExtensionTaskSource | IInMemoryTaskSource | IUserTaskSource | WorkspaceFileTaskSource;
494 > export type FileBasedTaskSource = IWorkspaceTaskSource | IUserTaskSource | WorkspaceFileTaskSource;
495 > export interface ITaskIdentifier {
496 > type: string;
497 > [name: string]: unknown;
498 > }
499 >
500 > export interface KeyedTaskIdentifier extends ITaskIdentifier {
501 > _key: string;
502 > }
503 >
504 > export interface ITaskDependency {
505 > uri: URI | string;
506 > task: string | KeyedTaskIdentifier | undefined;
507 > }
508 >
509 > export const enum DependsOrder {
510 > parallel = 'parallel',
511 > sequence = 'sequence'
512 > }
513 >
514 > export interface IConfigurationProperties {
515 >
516 > /**
517 > * The task's name
518 > */
519 > name?: string;
520 >
521 > /**
522 > * The task's name
523 > */
524 > identifier?: string;
525 >
526 > /**
527 > * The task's group;
528 > */
529 > group?: string | TaskGroup;
530 >
531 > /**
532 > * The presentation options
533 > */
534 > presentation?: IPresentationOptions;
535 >
536 > /**
537 > * The command options;
538 > */
539 > options?: CommandOptions;
540 >
541 > /**
542 > * Whether the task is a background task or not.
543 > */
544 > isBackground?: boolean;
545 >
546 > /**
547 > * Whether the task should prompt on close for confirmation if running.
548 > */
549 > promptOnClose?: boolean;
550 >
551 > /**
552 > * The other tasks this task depends on.
553 > */
554 > dependsOn?: ITaskDependency[];
555 >
556 > /**
557 > * The order the dependsOn tasks should be executed in.
558 > */
559 > dependsOrder?: DependsOrder;
560 >
561 > /**
562 > * A description of the task.
563 > */
564 > detail?: string;
565 >
566 > /**
567 > * The problem watchers to use for this task
568 > */
569 > problemMatchers?: Array<string | ProblemMatcher>;
570 >
571 > /**
572 > * The icon for this task in the terminal tabs list
573 > */
574 > icon?: { id?: string; color?: string };
575 >
576 > /**
577 > * Do not show this task in the run task quickpick
578 > */
579 > hide?: boolean;
580 >
581 > /**
582 > * Show this task in the Agents run action dropdown
583 > */
584 > inAgents?: boolean;
585 > }
586 >
587 > export enum RunOnOptions {
588 > default = 1,
589 > folderOpen = 2,
590 > worktreeCreated = 3
591 > }
592 >
593 > export const enum InstancePolicy {
594 > terminateNewest = 'terminateNewest',
595 > terminateOldest = 'terminateOldest',
596 > prompt = 'prompt',
597 > warn = 'warn',
598 > silent = 'silent'
599 > }
600 >
601 > export interface IRunOptions {
602 > reevaluateOnRerun?: boolean;
603 > runOn?: RunOnOptions;
604 > instanceLimit?: number;
605 > instancePolicy?: InstancePolicy;
606 > }
607 >
608 > export namespace RunOptions {
609 > export const defaults: IRunOptions = { reevaluateOnRerun: true, runOn: RunOnOptions.default, instanceLimit: 1, instancePolicy: InstancePolicy.prompt };
610 > }
611 >
612 > export abstract class CommonTask {
613 >
614 > /**
615 > * The task's internal id
616 > */
617 > readonly _id: string;
618 >
619 > /**
620 > * The cached label.
621 > */
622 > _label: string = '';
623 >
624 > type?: string;
625 >
626 > runOptions: IRunOptions;
627 >
628 > configurationProperties: IConfigurationProperties;
629 >
630 > _source: IBaseTaskSource;
631 >
632 > private _taskLoadMessages: string[] | undefined;
633 >
634 > protected constructor(id: string, label: string | undefined, type: string | undefined, runOptions: IRunOptions,
635 > configurationProperties: IConfigurationProperties, source: IBaseTaskSource) { taskConfiguration.ts ×6
636 > this._id = id;
637 > if (label) {
638 > this._label = label; taskConfiguration.ts ×45
639 > }
640 > if (type) { taskConfiguration.ts ×6
641 > this.type = type; taskConfiguration.ts ×13
642 > }
643 > this.runOptions = runOptions; taskConfiguration.ts ×6
644 > this.configurationProperties = configurationProperties;
645 > this._source = source;
646 > }
648 > public getDefinition(useSource?: boolean): KeyedTaskIdentifier | undefined {
649 return undefined;
650 }
652 > public getMapKey(): string {
653 return this._id;
654 }
656 > public getKey(): string | undefined {
657 return undefined;
658 }
660 > protected abstract getFolderId(): string | undefined;
661 >
662 > public getCommonTaskId(): string {
663 interface IRecentTaskKey {
664 folder: string | undefined;
665 id: string;
666 }
667
668 const key: IRecentTaskKey = { folder: this.getFolderId(), id: this._id };
669 return JSON.stringify(key);
670 }
672 > public clone(): Task {
673 return this.fromObject(Object.assign({}, this as unknown as Record<string, unknown>));
674 }
676 > protected abstract fromObject(object: Record<string, unknown>): Task;
677 >
678 > public getWorkspaceFolder(): IWorkspaceFolder | undefined {
679 return undefined;
680 }
682 > public getWorkspaceFileName(): string | undefined {
683 return undefined;
684 }
686 > public getTelemetryKind(): string {
687 return 'unknown';
688 }
690 > public matches(key: string | KeyedTaskIdentifier | undefined, compareId: boolean = false): boolean {
691 if (key === undefined) {
692 return false;
693 }
694 if (Types.isString(key)) {
695 return key === this._label || key === this.configurationProperties.identifier || (compareId && key === this._id);
696 }
697 const identifier = this.getDefinition(true);
698 return identifier !== undefined && identifier._key === key._key;
699 }
701 > public getQualifiedLabel(): string {
702 const workspaceFolder = this.getWorkspaceFolder();
703 if (workspaceFolder) {
704 return `${this._label} (${workspaceFolder.name})`;
705 } else {
706 return this._label;
707 }
708 }
710 > public getTaskExecution(): ITaskExecution {
711 const result: ITaskExecution = {
712 id: this._id,
713 task: this as unknown as Task
714 };
715 return result;
716 }
718 > public addTaskLoadMessages(messages: string[] | undefined) {
719 > if (this._taskLoadMessages === undefined) { taskConfiguration.ts ×22
720 > this._taskLoadMessages = [];
721 > }
722 > if (messages) {
723 > this._taskLoadMessages = this._taskLoadMessages.concat(messages); taskConfiguration.ts ×1
724 > }
727 > get taskLoadMessages(): string[] | undefined {
728 return this._taskLoadMessages;
729 }
731 >
732 > /**
733 > * For tasks of type shell or process, this is created upon parse
734 > * of the tasks.json or workspace file.
735 > * For ContributedTasks of all other types, this is the result of
736 > * resolving a ConfiguringTask.
737 > */
738 > export class CustomTask extends CommonTask {
739 >
740 > declare type: '$customized'; // CUSTOMIZED_TASK_TYPE
741 >
742 > instance: number | undefined;
743 >
744 > /**
745 > * Indicated the source of the task (e.g. tasks.json or extension)
746 > */
747 > override _source: FileBasedTaskSource;
748 >
749 > hasDefinedMatchers: boolean;
750 >
751 > /**
752 > * The command configuration
753 > */
754 > command: ICommandConfiguration = {};
755 >
756 > public constructor(id: string, source: FileBasedTaskSource, label: string, type: string, command: ICommandConfiguration | undefined,
757 > hasDefinedMatchers: boolean, runOptions: IRunOptions, configurationProperties: IConfigurationProperties) { taskConfiguration.ts ×45
758 > super(id, label, undefined, runOptions, configurationProperties, source);
759 > this._source = source;
760 > this.hasDefinedMatchers = hasDefinedMatchers;
761 > if (command) {
762 > this.command = command; taskConfiguration.ts ×41
763 > }
766 > public override clone(): CustomTask {
767 return new CustomTask(this._id, this._source, this._label, this.type, this.command, this.hasDefinedMatchers, this.runOptions, this.configurationProperties);
768 }
770 > public customizes(): KeyedTaskIdentifier | undefined {
771 if (this._source && this._source.customizes) {
772 return this._source.customizes;
773 }
774 return undefined;
775 }
777 > public override getDefinition(useSource: boolean = false): KeyedTaskIdentifier {
778 if (useSource && this._source.customizes !== undefined) {
779 return this._source.customizes;
780 } else {
781 let type: string;
782 const commandRuntime = this.command ? this.command.runtime : undefined;
783 switch (commandRuntime) {
784 case RuntimeType.Shell:
785 type = 'shell';
786 break;
787
788 case RuntimeType.Process:
789 type = 'process';
790 break;
791
792 case RuntimeType.CustomExecution:
793 type = 'customExecution';
794 break;
795
796 case undefined:
797 type = '$composite';
798 break;
799
800 default:
801 throw new Error('Unexpected task runtime');
802 }
803
804 const result: KeyedTaskIdentifier = {
805 type,
806 _key: this._id,
807 id: this._id
808 };
809 return result;
810 }
811 }
813 > public static is(value: unknown): value is CustomTask {
814 return value instanceof CustomTask;
815 }
817 > public override getMapKey(): string {
818 const workspaceFolder = this._source.config.workspaceFolder;
819 return workspaceFolder ? `${workspaceFolder.uri.toString()}|${this._id}|${this.instance}` : `${this._id}|${this.instance}`;
820 }
822 > protected getFolderId(): string | undefined {
823 return this._source.kind === TaskSourceKind.User ? USER_TASKS_GROUP_KEY : this._source.config.workspaceFolder?.uri.toString();
824 }
826 > public override getCommonTaskId(): string {
827 return this._source.customizes ? super.getCommonTaskId() : (this.getKey() ?? super.getCommonTaskId());
828 }
830 > /**
831 > * @returns A key representing the task
832 > */
833 > public override getKey(): string | undefined {
834 interface ICustomKey {
835 type: string;
836 folder: string;
837 id: string;
838 }
839 const workspaceFolder = this.getFolderId();
840 if (!workspaceFolder) {
841 return undefined;
842 }
843 let id: string = this.configurationProperties.identifier!;
844 if (this._source.kind !== TaskSourceKind.Workspace) {
845 id += this._source.kind;
846 }
847 const key: ICustomKey = { type: CUSTOMIZED_TASK_TYPE, folder: workspaceFolder, id };
848 return JSON.stringify(key);
849 }
851 > public override getWorkspaceFolder(): IWorkspaceFolder | undefined {
852 return this._source.config.workspaceFolder;
853 }
855 > public override getWorkspaceFileName(): string | undefined {
856 return (this._source.config.workspace && this._source.config.workspace.configuration) ? resources.basename(this._source.config.workspace.configuration) : undefined;
857 }
859 > public override getTelemetryKind(): string {
860 if (this._source.customizes) {
861 return 'workspace>extension';
862 } else {
863 return 'workspace';
864 }
865 }
867 > protected fromObject(object: Record<string, unknown>): CustomTask {
868 const obj = object as unknown as CustomTask;
869 return new CustomTask(obj._id, obj._source, obj._label, obj.type, obj.command, obj.hasDefinedMatchers, obj.runOptions, obj.configurationProperties);
870 }
872 >
873 > /**
874 > * After a contributed task has been parsed, but before
875 > * the task has been resolved via the extension, its properties
876 > * are stored in this
877 > */
878 > export class ConfiguringTask extends CommonTask {
879 >
880 > /**
881 > * Indicated the source of the task (e.g. tasks.json or extension)
882 > */
883 > override _source: FileBasedTaskSource;
884 >
885 > configures: KeyedTaskIdentifier;
886 >
887 > public constructor(id: string, source: FileBasedTaskSource, label: string | undefined, type: string | undefined,
888 > configures: KeyedTaskIdentifier, runOptions: IRunOptions, configurationProperties: IConfigurationProperties) { taskConfiguration.ts ×13
889 > super(id, label, type, runOptions, configurationProperties, source);
890 > this._source = source;
891 > this.configures = configures;
892 > }
894 > public static is(value: unknown): value is ConfiguringTask {
895 return value instanceof ConfiguringTask;
896 }
898 > protected fromObject(object: Record<string, unknown>): Task {
899 return object as unknown as Task;
900 }
902 > public override getDefinition(): KeyedTaskIdentifier {
903 return this.configures;
904 }
906 > public override getWorkspaceFileName(): string | undefined {
907 return (this._source.config.workspace && this._source.config.workspace.configuration) ? resources.basename(this._source.config.workspace.configuration) : undefined;
908 }
910 > public override getWorkspaceFolder(): IWorkspaceFolder | undefined {
911 return this._source.config.workspaceFolder;
912 }
914 > protected getFolderId(): string | undefined {
915 return this._source.kind === TaskSourceKind.User ? USER_TASKS_GROUP_KEY : this._source.config.workspaceFolder?.uri.toString();
916 }
918 > public override getKey(): string | undefined {
919 interface ICustomKey {
920 type: string;
921 folder: string;
922 id: string;
923 }
924 const workspaceFolder = this.getFolderId();
925 if (!workspaceFolder) {
926 return undefined;
927 }
928 let id: string = this.configurationProperties.identifier!;
929 if (this._source.kind !== TaskSourceKind.Workspace) {
930 id += this._source.kind;
931 }
932 const key: ICustomKey = { type: CUSTOMIZED_TASK_TYPE, folder: workspaceFolder, id };
933 return JSON.stringify(key);
934 }
936 >
937 > /**
938 > * A task from an extension created via resolveTask or provideTask
939 > */
940 > export class ContributedTask extends CommonTask {
941 >
942 > /**
943 > * Indicated the source of the task (e.g. tasks.json or extension)
944 > * Set in the super constructor
945 > */
946 > declare _source: IExtensionTaskSource;
947 >
948 > instance: number | undefined;
949 >
950 > defines: KeyedTaskIdentifier;
951 >
952 > hasDefinedMatchers: boolean;
953 >
954 > /**
955 > * The command configuration
956 > */
957 > command: ICommandConfiguration;
958 >
959 > /**
960 > * The icon for the task
961 > */
962 > icon: { id?: string; color?: string } | undefined;
963 >
964 > /**
965 > * Don't show the task in the run task quickpick
966 > */
967 > hide?: boolean;
968 >
969 > public constructor(id: string, source: IExtensionTaskSource, label: string, type: string | undefined, defines: KeyedTaskIdentifier,
970 command: ICommandConfiguration, hasDefinedMatchers: boolean, runOptions: IRunOptions,
971 configurationProperties: IConfigurationProperties) {
972 super(id, label, type, runOptions, configurationProperties, source);
973 this.defines = defines;
974 this.hasDefinedMatchers = hasDefinedMatchers;
975 this.command = command;
976 this.icon = configurationProperties.icon;
977 this.hide = configurationProperties.hide;
978 }
980 > public override clone(): ContributedTask {
981 return new ContributedTask(this._id, this._source, this._label, this.type, this.defines, this.command, this.hasDefinedMatchers, this.runOptions, this.configurationProperties);
982 }
984 > public override getDefinition(): KeyedTaskIdentifier {
985 return this.defines;
986 }
988 > public static is(value: unknown): value is ContributedTask {
989 return value instanceof ContributedTask;
990 }
992 > public override getMapKey(): string {
993 const workspaceFolder = this._source.workspaceFolder;
994 return workspaceFolder
995 ? `${this._source.scope.toString()}|${workspaceFolder.uri.toString()}|${this._id}|${this.instance}`
996 : `${this._source.scope.toString()}|${this._id}|${this.instance}`;
997 }
999 > protected getFolderId(): string | undefined {
1000 if (this._source.scope === TaskScope.Folder && this._source.workspaceFolder) {
1001 return this._source.workspaceFolder.uri.toString();
1002 }
1003 return undefined;
1004 }
1006 > public override getKey(): string | undefined {
1007 interface IContributedKey {
1008 type: string;
1009 scope: number;
1010 folder?: string;
1011 id: string;
1012 }
1013
1014 const key: IContributedKey = { type: 'contributed', scope: this._source.scope, id: this._id };
1015 key.folder = this.getFolderId();
1016 return JSON.stringify(key);
1017 }
1019 > public override getWorkspaceFolder(): IWorkspaceFolder | undefined {
1020 return this._source.workspaceFolder;
1021 }
1023 > public override getTelemetryKind(): string {
1024 return 'extension';
1025 }
1027 > protected fromObject(object: Record<string, unknown>): ContributedTask {
1028 const obj = object as unknown as ContributedTask;
1029 return new ContributedTask(obj._id, obj._source, obj._label, obj.type, obj.defines, obj.command, obj.hasDefinedMatchers, obj.runOptions, obj.configurationProperties);
1030 }
1032 >
1033 > export class InMemoryTask extends CommonTask {
1034 > /**
1035 > * Indicated the source of the task (e.g. tasks.json or extension)
1036 > */
1037 > override _source: IInMemoryTaskSource;
1038 >
1039 > instance: number | undefined;
1040 >
1041 > declare type: 'inMemory';
1042 >
1043 > public constructor(id: string, source: IInMemoryTaskSource, label: string, type: string,
1044 runOptions: IRunOptions, configurationProperties: IConfigurationProperties) {
1045 super(id, label, type, runOptions, configurationProperties, source);
1046 this._source = source;
1047 }
1049 > public override clone(): InMemoryTask {
1050 return new InMemoryTask(this._id, this._source, this._label, this.type, this.runOptions, this.configurationProperties);
1051 }
1053 > public static is(value: unknown): value is InMemoryTask {
1054 > return value instanceof InMemoryTask; tasks.ts ×4
1055 > }
1057 > public override getTelemetryKind(): string {
1058 return 'composite';
1059 }
1061 > public override getMapKey(): string {
1062 return `${this._id}|${this.instance}`;
1063 }
1065 > protected getFolderId(): undefined {
1066 return undefined;
1067 }
1069 > protected fromObject(object: Record<string, unknown>): InMemoryTask {
1070 const obj = object as unknown as InMemoryTask;
1071 return new InMemoryTask(obj._id, obj._source, obj._label, obj.type, obj.runOptions, obj.configurationProperties);
1072 }
1074 >
1075 > export type Task = CustomTask | ContributedTask | InMemoryTask;
1076 >
1077 > export interface ITaskExecution {
1078 > id: string;
1079 > task: Task;
1080 > }
1081 >
1082 > export enum ExecutionEngine {
1083 > Process = 1,
1084 > Terminal = 2
1085 > }
1086 >
1087 > export namespace ExecutionEngine {
1088 > export const _default: ExecutionEngine = ExecutionEngine.Terminal;
1089 > }
1090 >
1091 > export const enum JsonSchemaVersion {
1092 > V0_1_0 = 1,
1093 > V2_0_0 = 2
1094 > }
1095 >
1096 > export interface ITaskSet {
1097 > tasks: Task[];
1098 > extension?: IExtensionDescription;
1099 > }
1100 >
1101 > export interface ITaskDefinition {
1102 > extensionId: string;
1103 > taskType: string;
1104 > required: string[];
1105 > properties: IJSONSchemaMap;
1106 > when?: ContextKeyExpression;
1107 > }
1108 >
1109 > export class TaskSorter {
1110 >
1111 > private _order: Map<string, number> = new Map();
1112 >
1113 > constructor(workspaceFolders: IWorkspaceFolder[]) {
1114 for (let i = 0; i < workspaceFolders.length; i++) {
1115 this._order.set(workspaceFolders[i].uri.toString(), i);
1116 }
1117 }
1119 > public compare(a: Task | ConfiguringTask, b: Task | ConfiguringTask): number {
1120 const aw = a.getWorkspaceFolder();
1121 const bw = b.getWorkspaceFolder();
1122 if (aw && bw) {
1123 let ai = this._order.get(aw.uri.toString());
1124 ai = ai === undefined ? 0 : ai + 1;
1125 let bi = this._order.get(bw.uri.toString());
1126 bi = bi === undefined ? 0 : bi + 1;
1127 if (ai === bi) {
1128 return a._label.localeCompare(b._label);
1129 } else {
1130 return ai - bi;
1131 }
1132 } else if (!aw && bw) {
1133 return -1;
1134 } else if (aw && !bw) {
1135 return +1;
1136 } else {
1137 return 0;
1138 }
1139 }
1141 >
1142 >
1143 >
1144 > export const enum TaskRunType {
1145 > SingleRun = 'singleRun',
1146 > Background = 'background'
1147 > }
1148 >
1149 > export interface ITaskChangedEvent {
1150 > kind: TaskEventKind.Changed;
1151 > }
1152 >
1153 >
1154 >
1155 > export enum TaskEventKind {
1156 > /** Indicates that a task's properties or configuration have changed */
1157 > Changed = 'changed',
1158 >
1159 > /** Indicates that a task has begun executing */
1160 > ProcessStarted = 'processStarted',
1161 >
1162 > /** Indicates that a task process has completed */
1163 > ProcessEnded = 'processEnded',
1164 >
1165 > /** Indicates that a task was terminated, either by user action or by the system */
1166 > Terminated = 'terminated',
1167 >
1168 > /** Indicates that a task has started running */
1169 > Start = 'start',
1170 >
1171 > /** Indicates that a task has acquired all needed input/variables to execute */
1172 > AcquiredInput = 'acquiredInput',
1173 >
1174 > /** Indicates that a dependent task has started */
1175 > DependsOnStarted = 'dependsOnStarted',
1176 >
1177 > /** Indicates that a task is actively running/processing */
1178 > Active = 'active',
1179 >
1180 > /** Indicates that a task is paused/waiting but not complete */
1181 > Inactive = 'inactive',
1182 >
1183 > /** Indicates that a task has completed fully */
1184 > End = 'end',
1185 >
1186 > /** Indicates that a task's problem matcher has started */
1187 > ProblemMatcherStarted = 'problemMatcherStarted',
1188 >
1189 > /** Indicates that a task's problem matcher has ended */
1190 > ProblemMatcherEnded = 'problemMatcherEnded',
1191 >
1192 > /** Indicates that a task's problem matcher has found errors */
1193 > ProblemMatcherFoundErrors = 'problemMatcherFoundErrors'
1194 > }
1195 >
1196 > interface ITaskCommon {
1197 > taskId: string;
1198 > runType: TaskRunType;
1199 > taskName: string | undefined;
1200 > group: string | TaskGroup | undefined;
1201 > __task: Task;
1202 > }
1203 >
1204 > export interface ITaskProcessStartedEvent extends ITaskCommon {
1205 > kind: TaskEventKind.ProcessStarted;
1206 > terminalId: number;
1207 > processId: number;
1208 > }
1209 >
1210 > export interface ITaskProcessEndedEvent extends ITaskCommon {
1211 > kind: TaskEventKind.ProcessEnded;
1212 > terminalId: number | undefined;
1213 > exitCode?: number;
1214 > durationMs?: number;
1215 > }
1216 >
1217 > export interface ITaskInactiveEvent extends ITaskCommon {
1218 > kind: TaskEventKind.Inactive;
1219 > terminalId: number | undefined;
1220 > durationMs: number | undefined;
1221 > }
1222 >
1223 > export interface ITaskTerminatedEvent extends ITaskCommon {
1224 > kind: TaskEventKind.Terminated;
1225 > terminalId: number;
1226 > exitReason: TerminalExitReason | undefined;
1227 > }
1228 >
1229 > export interface ITaskStartedEvent extends ITaskCommon {
1230 > kind: TaskEventKind.Start;
1231 > terminalId: number;
1232 > resolvedVariables: Map<string, string>;
1233 > }
1234 >
1235 > export interface ITaskProblemMatcherEndedEvent extends ITaskCommon {
1236 > kind: TaskEventKind.ProblemMatcherEnded;
1237 > hasErrors: boolean;
1238 > }
1239 >
1240 > export interface ITaskGeneralEvent extends ITaskCommon {
1241 > kind: TaskEventKind.AcquiredInput | TaskEventKind.DependsOnStarted | TaskEventKind.Active | TaskEventKind.Inactive | TaskEventKind.End | TaskEventKind.ProblemMatcherStarted | TaskEventKind.ProblemMatcherFoundErrors;
1242 > terminalId: number | undefined;
1243 > }
1244 >
1245 > export type ITaskEvent =
1246 > | ITaskChangedEvent
1247 > | ITaskProcessStartedEvent
1248 > | ITaskProcessEndedEvent
1249 > | ITaskTerminatedEvent
1250 > | ITaskStartedEvent
1251 > | ITaskGeneralEvent
1252 > | ITaskProblemMatcherEndedEvent;
1253 >
1254 > export const enum TaskRunSource {
1255 > System,
1256 > User,
1257 > FolderOpen,
1258 > ConfigurationChange,
1259 > Reconnect,
1260 > ChatAgent
1261 > }
1262 >
1263 > export namespace TaskEvent {
1264 > function common(task: Task): ITaskCommon {
1265 return {
1266 taskId: task._id,
1267 taskName: task.configurationProperties.name,
1268 runType: task.configurationProperties.isBackground ? TaskRunType.Background : TaskRunType.SingleRun,
1269 group: task.configurationProperties.group,
1270 __task: task,
1271 };
1272 }
1274 > export function start(task: Task, terminalId: number, resolvedVariables: Map<string, string>): ITaskStartedEvent {
1275 return {
1276 ...common(task),
1277 kind: TaskEventKind.Start,
1278 terminalId,
1279 resolvedVariables,
1280 };
1281 }
1283 > export function processStarted(task: Task, terminalId: number, processId: number): ITaskProcessStartedEvent {
1284 return {
1285 ...common(task),
1286 kind: TaskEventKind.ProcessStarted,
1287 terminalId,
1288 processId,
1289 };
1290 }
1291 > export function processEnded(task: Task, terminalId: number | undefined, exitCode: number | undefined, durationMs?: number): ITaskProcessEndedEvent { taskConfiguration.ts ×80
1292 return {
1293 ...common(task),
1294 kind: TaskEventKind.ProcessEnded,
1295 terminalId,
1296 exitCode,
1297 durationMs,
1298 };
1299 }
1301 > export function inactive(task: Task, terminalId?: number, durationMs?: number): ITaskInactiveEvent {
1302 return {
1303 ...common(task),
1304 kind: TaskEventKind.Inactive,
1305 terminalId,
1306 durationMs,
1307 };
1308 }
1310 > export function terminated(task: Task, terminalId: number, exitReason: TerminalExitReason | undefined): ITaskTerminatedEvent {
1311 return {
1312 ...common(task),
1313 kind: TaskEventKind.Terminated,
1314 exitReason,
1315 terminalId,
1316 };
1317 }
1319 > export function general(kind: TaskEventKind.AcquiredInput | TaskEventKind.DependsOnStarted | TaskEventKind.Active | TaskEventKind.Inactive | TaskEventKind.End | TaskEventKind.ProblemMatcherStarted | TaskEventKind.ProblemMatcherFoundErrors, task: Task, terminalId?: number): ITaskGeneralEvent {
1320 return {
1321 ...common(task),
1322 kind,
1323 terminalId,
1324 };
1325 }
1327 > export function problemMatcherEnded(task: Task, hasErrors: boolean, terminalId?: number): ITaskProblemMatcherEndedEvent {
1328 return {
1329 ...common(task),
1330 kind: TaskEventKind.ProblemMatcherEnded,
1331 hasErrors,
1332 };
1333 }
1335 > export function changed(): ITaskChangedEvent {
1336 return { kind: TaskEventKind.Changed };
1337 }
1339 >
1340 > export namespace KeyedTaskIdentifier {
1341 > function sortedStringify(literal: Record<string, unknown>): string {
1342 > const keys = Object.keys(literal).sort(); taskConfiguration.ts ×13
1343 > let result: string = '';
1344 > for (const key of keys) {
1345 > let stringified = literal[key];
1346 > if (stringified instanceof Object) {
1347 stringified = sortedStringify(stringified as Record<string, unknown>);
1348 > } else if (typeof stringified === 'string') { taskConfiguration.ts ×13
1349 > stringified = stringified.replace(/,/g, ',,');
1350 > }
1351 > result += key + ',' + stringified + ',';
1352 > }
1353 > return result;
1354 > }
1355 > export function create(value: ITaskIdentifier): KeyedTaskIdentifier { taskConfiguration.ts ×80
1356 > const resultKey = sortedStringify(value); taskConfiguration.ts ×13
1357 > const result = { _key: resultKey, type: value.taskType as string };
1358 > Object.assign(result, value);
1359 > return result;
1360 > }
1362 >
1363 > export const enum TaskSettingId {
1364 > AutoDetect = 'task.autoDetect',
1365 > SaveBeforeRun = 'task.saveBeforeRun',
1366 > ShowDecorations = 'task.showDecorations',
1367 > ProblemMatchersNeverPrompt = 'task.problemMatchers.neverPrompt',
1368 > SlowProviderWarning = 'task.slowProviderWarning',
1369 > QuickOpenHistory = 'task.quickOpen.history',
1370 > QuickOpenDetail = 'task.quickOpen.detail',
1371 > QuickOpenSkip = 'task.quickOpen.skip',
1372 > QuickOpenShowAll = 'task.quickOpen.showAll',
1373 > AllowAutomaticTasks = 'task.allowAutomaticTasks',
1374 > Reconnection = 'task.reconnection',
1375 > VerboseLogging = 'task.verboseLogging',
1376 > NotifyWindowOnTaskCompletion = 'task.notifyWindowOnTaskCompletion'
1377 > }
1378 >
1379 > export const enum TasksSchemaProperties {
1380 > Tasks = 'tasks',
1381 > SuppressTaskName = 'tasks.suppressTaskName',
1382 > Windows = 'tasks.windows',
1383 > Osx = 'tasks.osx',
1384 > Linux = 'tasks.linux',
1385 > ShowOutput = 'tasks.showOutput',
1386 > IsShellCommand = 'tasks.isShellCommand',
1387 > ServiceTestSetting = 'tasks.service.testSetting',
1388 > }
1389 >
1390 > export namespace TaskDefinition {
1391 > export function createTaskIdentifier(external: ITaskIdentifier, reporter: { error(message: string): void }): KeyedTaskIdentifier | undefined {
1392 > const definition = TaskDefinitionRegistry.get(external.type); taskConfiguration.ts ×13
1393 > if (definition === undefined) {
1394 > // We have no task definition so we can't sanitize the literal. Take it as is
1395 > const copy = Objects.deepClone(external);
1396 > delete copy._key;
1397 > return KeyedTaskIdentifier.create(copy);
1398 > }
1399
1400 const literal: { type: string;[name: string]: unknown } = Object.create(null);
1401 literal.type = definition.taskType;
1402 const required: Set<string> = new Set();
1403 definition.required.forEach(element => required.add(element));
1404
1405 const properties = definition.properties;
1406 for (const property of Object.keys(properties)) {
1407 const value = external[property];
1408 if (value !== undefined && value !== null) {
1409 literal[property] = value;
1410 } else if (required.has(property)) {
1411 const schema = properties[property];
1412 if (schema.default !== undefined) {
1413 literal[property] = Objects.deepClone(schema.default);
1414 } else {
1415 switch (schema.type) {
1416 case 'boolean':
1417 literal[property] = false;
1418 break;
1419 case 'number':
1420 case 'integer':
1421 literal[property] = 0;
1422 break;
1423 case 'string':
1424 literal[property] = '';
1425 break;
1426 default:
1427 reporter.error(nls.localize(
1428 'TaskDefinition.missingRequiredProperty',
1429 'Error: the task identifier \'{0}\' is missing the required property \'{1}\'. The task identifier will be ignored.', JSON.stringify(external, undefined, 0), property
1430 ));
1431 return undefined;
1432 }
1433 }
1434 }
1435 }
1436 return KeyedTaskIdentifier.create(literal);
1439 >
1440 > export const rerunTaskIcon = registerIcon('rerun-task', Codicon.refresh, nls.localize('rerunTaskIcon', 'View icon of the rerun task.'));
1441 > export const RerunForActiveTerminalCommandId = 'workbench.action.tasks.rerunForActiveTerminal';
1442 > export const RerunAllRunningTasksCommandId = 'workbench.action.tasks.rerunAllRunningTasks';