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

2220 LOC · 1733 covered · 487 uncovered · 416 ranges · 131 concepts · 91 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 >
8 > import * as Objects from '../../../../base/common/objects.js';
9 > import { IStringDictionary } from '../../../../base/common/collections.js';
10 > import { IJSONSchemaMap } from '../../../../base/common/jsonSchema.js';
11 > import { Platform } from '../../../../base/common/platform.js';
12 > import * as Types from '../../../../base/common/types.js';
13 > import * as UUID from '../../../../base/common/uuid.js';
14 >
15 > import { ValidationStatus, IProblemReporter as IProblemReporterBase } from '../../../../base/common/parsers.js';
16 > import {
17 > INamedProblemMatcher, ProblemMatcherParser, Config as ProblemMatcherConfig,
18 > isNamedProblemMatcher, ProblemMatcherRegistry, ProblemMatcher
19 > } from './problemMatcher.js';
20 >
21 > import { IWorkspaceFolder, IWorkspace } from '../../../../platform/workspace/common/workspace.js';
22 > import * as Tasks from './tasks.js';
23 > import { ITaskDefinitionRegistry, TaskDefinitionRegistry } from './taskDefinitionRegistry.js';
24 > import { ConfiguredInput } from '../../../services/configurationResolver/common/configurationResolver.js';
25 > import { URI } from '../../../../base/common/uri.js';
26 > import { ShellExecutionSupportedContext, ProcessExecutionSupportedContext } from './taskService.js';
27 > import { IContextKeyService, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';
28 >
29 > export const enum ShellQuoting {
30 > /**
31 > * Default is character escaping.
32 > */
33 > escape = 1,
34 >
35 > /**
36 > * Default is strong quoting
37 > */
38 > strong = 2,
39 >
40 > /**
41 > * Default is weak quoting.
42 > */
43 > weak = 3
44 > }
45 >
46 > export interface IShellQuotingOptions {
47 > /**
48 > * The character used to do character escaping.
49 > */
50 > escape?: string | {
51 > escapeChar: string;
52 > charsToEscape: string;
53 > };
54 >
55 > /**
56 > * The character used for string quoting.
57 > */
58 > strong?: string;
59 >
60 > /**
61 > * The character used for weak quoting.
62 > */
63 > weak?: string;
64 > }
65 >
66 > export interface IShellConfiguration {
67 > executable?: string;
68 > args?: string[];
69 > quoting?: IShellQuotingOptions;
70 > }
71 >
72 > export interface ICommandOptionsConfig {
73 > /**
74 > * The current working directory of the executed program or shell.
75 > * If omitted VSCode's current workspace root is used.
76 > */
77 > cwd?: string;
78 >
79 > /**
80 > * The additional environment of the executed program or shell. If omitted
81 > * the parent process' environment is used.
82 > */
83 > env?: IStringDictionary<string>;
84 >
85 > /**
86 > * The shell configuration;
87 > */
88 > shell?: IShellConfiguration;
89 > }
90 >
91 > export interface IPresentationOptionsConfig {
92 > /**
93 > * Controls whether the terminal executing a task is brought to front or not.
94 > * Defaults to `RevealKind.Always`.
95 > */
96 > reveal?: string;
97 >
98 > /**
99 > * Controls whether the problems panel is revealed when running this task or not.
100 > * Defaults to `RevealKind.Never`.
101 > */
102 > revealProblems?: string;
103 >
104 > /**
105 > * Controls whether the executed command is printed to the output window or terminal as well.
106 > */
107 > echo?: boolean;
108 >
109 > /**
110 > * Controls whether the terminal is focus when this task is executed
111 > */
112 > focus?: boolean;
113 >
114 > /**
115 > * Controls whether the task runs in a new terminal
116 > */
117 > panel?: string;
118 >
119 > /**
120 > * Controls whether to show the "Terminal will be reused by tasks, press any key to close it" message.
121 > */
122 > showReuseMessage?: boolean;
123 >
124 > /**
125 > * Controls whether the terminal should be cleared before running the task.
126 > */
127 > clear?: boolean;
128 >
129 > /**
130 > * Controls whether the task is executed in a specific terminal group using split panes.
131 > */
132 > group?: string;
133 >
134 > /**
135 > * Controls whether the terminal that the task runs in is closed when the task completes.
136 > * Note that if the terminal process exits with a non-zero exit code, it will not close.
137 > */
138 > close?: boolean;
139 >
140 > /**
141 > * Controls whether to preserve the task name in the terminal after task completion.
142 > */
143 > preserveTerminalName?: boolean;
144 > }
145 >
146 > export interface IRunOptionsConfig {
147 > reevaluateOnRerun?: boolean;
148 > runOn?: string;
149 > instanceLimit?: number;
150 > instancePolicy?: Tasks.InstancePolicy;
151 > }
152 >
153 > export interface ITaskIdentifier {
154 > type?: string;
155 > [name: string]: unknown;
156 > }
157 >
158 > export namespace ITaskIdentifier {
159 > export function is(value: unknown): value is ITaskIdentifier {
160 const candidate: ITaskIdentifier = value as ITaskIdentifier;
161 return candidate !== undefined && Types.isString((value as ITaskIdentifier).type);
162 }
164 >
165 > export interface ILegacyTaskProperties {
166 > /**
167 > * @deprecated Use `isBackground` instead.
168 > * Whether the executed command is kept alive and is watching the file system.
169 > */
170 > isWatching?: boolean;
171 >
172 > /**
173 > * @deprecated Use `group` instead.
174 > * Whether this task maps to the default build command.
175 > */
176 > isBuildCommand?: boolean;
177 >
178 > /**
179 > * @deprecated Use `group` instead.
180 > * Whether this task maps to the default test command.
181 > */
182 > isTestCommand?: boolean;
183 > }
184 >
185 > export interface ILegacyCommandProperties {
186 >
187 > /**
188 > * Whether this is a shell or process
189 > */
190 > type?: string;
191 >
192 > /**
193 > * @deprecated Use presentation options
194 > * Controls whether the output view of the running tasks is brought to front or not.
195 > * See BaseTaskRunnerConfiguration#showOutput for details.
196 > */
197 > showOutput?: string;
198 >
199 > /**
200 > * @deprecated Use presentation options
201 > * Controls whether the executed command is printed to the output windows as well.
202 > */
203 > echoCommand?: boolean;
204 >
205 > /**
206 > * @deprecated Use presentation instead
207 > */
208 > terminal?: IPresentationOptionsConfig;
209 >
210 > /**
211 > * @deprecated Use inline commands.
212 > * See BaseTaskRunnerConfiguration#suppressTaskName for details.
213 > */
214 > suppressTaskName?: boolean;
215 >
216 > /**
217 > * Some commands require that the task argument is highlighted with a special
218 > * prefix (e.g. /t: for msbuild). This property can be used to control such
219 > * a prefix.
220 > */
221 > taskSelector?: string;
222 >
223 > /**
224 > * @deprecated use the task type instead.
225 > * Specifies whether the command is a shell command and therefore must
226 > * be executed in a shell interpreter (e.g. cmd.exe, bash, ...).
227 > *
228 > * Defaults to false if omitted.
229 > */
230 > isShellCommand?: boolean | IShellConfiguration;
231 > }
232 >
233 > export type CommandString = Types.SingleOrMany<string> | { value: Types.SingleOrMany<string>; quoting: 'escape' | 'strong' | 'weak' };
234 >
235 > export namespace CommandString {
236 > export function value(value: CommandString): string {
237 if (Types.isString(value)) {
238 return value;
239 } else if (Types.isStringArray(value)) {
240 return value.join(' ');
241 } else {
242 if (Types.isString(value.value)) {
243 return value.value;
244 } else {
245 return value.value.join(' ');
246 }
247 }
248 }
250 >
251 > export interface IBaseCommandProperties {
252 >
253 > /**
254 > * The command to be executed. Can be an external program or a shell
255 > * command.
256 > */
257 > command?: CommandString;
258 >
259 > /**
260 > * The command options used when the command is executed. Can be omitted.
261 > */
262 > options?: ICommandOptionsConfig;
263 >
264 > /**
265 > * The arguments passed to the command or additional arguments passed to the
266 > * command when using a global command.
267 > */
268 > args?: CommandString[];
269 > }
270 >
271 >
272 > export interface ICommandProperties extends IBaseCommandProperties {
273 >
274 > /**
275 > * Windows specific command properties
276 > */
277 > windows?: IBaseCommandProperties;
278 >
279 > /**
280 > * OSX specific command properties
281 > */
282 > osx?: IBaseCommandProperties;
283 >
284 > /**
285 > * linux specific command properties
286 > */
287 > linux?: IBaseCommandProperties;
288 > }
289 >
290 > export interface IGroupKind {
291 > kind?: string;
292 > isDefault?: boolean | string;
293 > }
294 >
295 > export interface IConfigurationProperties {
296 > /**
297 > * The task's name
298 > */
299 > taskName?: string;
300 >
301 > /**
302 > * The UI label used for the task.
303 > */
304 > label?: string;
305 >
306 > /**
307 > * An optional identifier which can be used to reference a task
308 > * in a dependsOn or other attributes.
309 > */
310 > identifier?: string;
311 >
312 > /**
313 > * Whether the executed command is kept alive and runs in the background.
314 > */
315 > isBackground?: boolean;
316 >
317 > /**
318 > * Whether the task should prompt on close for confirmation if running.
319 > */
320 > promptOnClose?: boolean;
321 >
322 > /**
323 > * Defines the group the task belongs too.
324 > */
325 > group?: string | IGroupKind;
326 >
327 > /**
328 > * A description of the task.
329 > */
330 > detail?: string;
331 >
332 > /**
333 > * The other tasks the task depend on
334 > */
335 > dependsOn?: string | ITaskIdentifier | Array<string | ITaskIdentifier>;
336 >
337 > /**
338 > * The order the dependsOn tasks should be executed in.
339 > */
340 > dependsOrder?: string;
341 >
342 > /**
343 > * Controls the behavior of the used terminal
344 > */
345 > presentation?: IPresentationOptionsConfig;
346 >
347 > /**
348 > * Controls shell options.
349 > */
350 > options?: ICommandOptionsConfig;
351 >
352 > /**
353 > * The problem matcher(s) to use to capture problems in the tasks
354 > * output.
355 > */
356 > problemMatcher?: ProblemMatcherConfig.ProblemMatcherType;
357 >
358 > /**
359 > * Task run options. Control run related properties.
360 > */
361 > runOptions?: IRunOptionsConfig;
362 >
363 > /**
364 > * The icon for this task in the terminal tabs list
365 > */
366 > icon?: { id: string; color?: string };
367 >
368 > /**
369 > * The icon's color in the terminal tabs list
370 > */
371 > color?: string;
372 >
373 > /**
374 > * Do not show this task in the run task quickpick
375 > */
376 > hide?: boolean;
377 >
378 > /**
379 > * Show this task in the Agents run action dropdown
380 > */
381 > inAgents?: boolean;
382 > }
383 >
384 > export interface ICustomTask extends ICommandProperties, IConfigurationProperties {
385 > /**
386 > * Custom tasks have the type CUSTOMIZED_TASK_TYPE
387 > */
388 > type?: string;
389 >
390 > }
391 >
392 > export interface IConfiguringTask extends IConfigurationProperties {
393 > /**
394 > * The contributed type of the task
395 > */
396 > type?: string;
397 > }
398 >
399 > /**
400 > * The base task runner configuration
401 > */
402 > export interface IBaseTaskRunnerConfiguration {
403 >
404 > /**
405 > * The command to be executed. Can be an external program or a shell
406 > * command.
407 > */
408 > command?: CommandString;
409 >
410 > /**
411 > * @deprecated Use type instead
412 > *
413 > * Specifies whether the command is a shell command and therefore must
414 > * be executed in a shell interpreter (e.g. cmd.exe, bash, ...).
415 > *
416 > * Defaults to false if omitted.
417 > */
418 > isShellCommand?: boolean;
419 >
420 > /**
421 > * The task type
422 > */
423 > type?: string;
424 >
425 > /**
426 > * The command options used when the command is executed. Can be omitted.
427 > */
428 > options?: ICommandOptionsConfig;
429 >
430 > /**
431 > * The arguments passed to the command. Can be omitted.
432 > */
433 > args?: CommandString[];
434 >
435 > /**
436 > * Controls whether the output view of the running tasks is brought to front or not.
437 > * Valid values are:
438 > * "always": bring the output window always to front when a task is executed.
439 > * "silent": only bring it to front if no problem matcher is defined for the task executed.
440 > * "never": never bring the output window to front.
441 > *
442 > * If omitted "always" is used.
443 > */
444 > showOutput?: string;
445 >
446 > /**
447 > * Controls whether the executed command is printed to the output windows as well.
448 > */
449 > echoCommand?: boolean;
450 >
451 > /**
452 > * The group
453 > */
454 > group?: string | IGroupKind;
455 >
456 > /**
457 > * Controls the behavior of the used terminal
458 > */
459 > presentation?: IPresentationOptionsConfig;
460 >
461 > /**
462 > * If set to false the task name is added as an additional argument to the
463 > * command when executed. If set to true the task name is suppressed. If
464 > * omitted false is used.
465 > */
466 > suppressTaskName?: boolean;
467 >
468 > /**
469 > * Some commands require that the task argument is highlighted with a special
470 > * prefix (e.g. /t: for msbuild). This property can be used to control such
471 > * a prefix.
472 > */
473 > taskSelector?: string;
474 >
475 > /**
476 > * The problem matcher(s) to used if a global command is executed (e.g. no tasks
477 > * are defined). A tasks.json file can either contain a global problemMatcher
478 > * property or a tasks property but not both.
479 > */
480 > problemMatcher?: ProblemMatcherConfig.ProblemMatcherType;
481 >
482 > /**
483 > * @deprecated Use `isBackground` instead.
484 > *
485 > * Specifies whether a global command is a watching the filesystem. A task.json
486 > * file can either contain a global isWatching property or a tasks property
487 > * but not both.
488 > */
489 > isWatching?: boolean;
490 >
491 > /**
492 > * Specifies whether a global command is a background task.
493 > */
494 > isBackground?: boolean;
495 >
496 > /**
497 > * Whether the task should prompt on close for confirmation if running.
498 > */
499 > promptOnClose?: boolean;
500 >
501 > /**
502 > * The configuration of the available tasks. A tasks.json file can either
503 > * contain a global problemMatcher property or a tasks property but not both.
504 > */
505 > tasks?: Array<ICustomTask | IConfiguringTask>;
506 >
507 > /**
508 > * Problem matcher declarations.
509 > */
510 > declares?: ProblemMatcherConfig.INamedProblemMatcher[];
511 >
512 > /**
513 > * Optional user input variables.
514 > */
515 > inputs?: ConfiguredInput[];
516 > }
517 >
518 > /**
519 > * A configuration of an external build system. BuildConfiguration.buildSystem
520 > * must be set to 'program'
521 > */
522 > export interface IExternalTaskRunnerConfiguration extends IBaseTaskRunnerConfiguration {
523 >
524 > _runner?: string;
525 >
526 > /**
527 > * Determines the runner to use
528 > */
529 > runner?: string;
530 >
531 > /**
532 > * The config's version number
533 > */
534 > version: string;
535 >
536 > /**
537 > * Windows specific task configuration
538 > */
539 > windows?: IBaseTaskRunnerConfiguration;
540 >
541 > /**
542 > * Mac specific task configuration
543 > */
544 > osx?: IBaseTaskRunnerConfiguration;
545 >
546 > /**
547 > * Linux specific task configuration
548 > */
549 > linux?: IBaseTaskRunnerConfiguration;
550 > }
551 >
552 > enum ProblemMatcherKind {
553 > Unknown,
554 > String,
555 > ProblemMatcher,
556 > Array
557 > }
558 >
559 > type TaskConfigurationValueWithErrors<T> = {
560 > value?: T;
561 > errors?: string[];
562 > };
563 >
564 > const EMPTY_ARRAY: never[] = [];
565 > Object.freeze(EMPTY_ARRAY);
566 >
567 > function assignProperty<T, K extends keyof T>(target: T, source: Partial<T>, key: K) { taskConfiguration.ts ×12
568 > const sourceAtKey = source[key];
569 > if (sourceAtKey !== undefined) {
570 > target[key] = sourceAtKey!; taskConfiguration.ts ×11
571 > }
574 > function fillProperty<T, K extends keyof T>(target: T, source: Partial<T>, key: K) { taskConfiguration.ts ×16
575 > const sourceAtKey = source[key];
576 > if (target[key] === undefined && sourceAtKey !== undefined) {
577 > target[key] = sourceAtKey!;
578 > }
579 > }
581 >
582 > interface IParserType<T> {
583 > isEmpty(value: T | undefined): boolean;
584 > assignProperties(target: T | undefined, source: T | undefined): T | undefined;
585 > fillProperties(target: T | undefined, source: T | undefined): T | undefined;
586 > fillDefaults(value: T | undefined, context: IParseContext): T | undefined;
587 > freeze(value: T): Readonly<T> | undefined;
588 > }
589 >
590 > interface IMetaData<T, U> {
591 > property: keyof T;
592 > type?: IParserType<U>;
593 > }
594 >
595 >
596 > // eslint-disable-next-line @typescript-eslint/no-explicit-any -- IMetaData array holds heterogeneous parser types
597 > function _isEmpty<T>(this: void, value: T | undefined, properties: IMetaData<T, any>[] | undefined, allowEmptyArray: boolean = false): boolean { taskConfiguration.ts ×6
598 > if (value === undefined || value === null || properties === undefined) {
599 > return true; taskConfiguration.ts ×2
600 > }
601 > for (const meta of properties) { taskConfiguration.ts ×6
602 > const property = value[meta.property];
603 > if (property !== undefined && property !== null) {
604 > if (meta.type !== undefined && !meta.type.isEmpty(property)) {
605 > return false; taskConfiguration.ts ×3
606 > } else if (!Array.isArray(property) || (property.length > 0) || allowEmptyArray) { taskConfiguration.ts ×6
607 > return false;
608 > }
609 > }
610 > }
611 > return true; taskConfiguration.ts ×2
612 > }
614 > // eslint-disable-next-line @typescript-eslint/no-explicit-any -- IMetaData array holds heterogeneous parser types
615 > function _assignProperties<T>(this: void, target: T | undefined, source: T | undefined, properties: IMetaData<T, any>[]): T | undefined { taskConfiguration.ts ×12
616 > if (!source || _isEmpty(source, properties)) {
617 > return target;
618 > }
619 > if (!target || _isEmpty(target, properties)) {
620 return source;
621 }
622 for (const meta of properties) {
623 const property = meta.property;
624 let value: T[keyof T] | undefined;
625 if (meta.type !== undefined) {
626 value = meta.type.assignProperties(target[property], source[property]);
627 } else {
628 value = source[property];
629 }
630 if (value !== undefined && value !== null) {
631 (target as Record<string, unknown>)[property as string] = value;
632 }
633 }
634 return target;
635 }
637 > // eslint-disable-next-line @typescript-eslint/no-explicit-any -- IMetaData array holds heterogeneous parser types
638 > function _fillProperties<T>(this: void, target: T | undefined, source: T | undefined, properties: IMetaData<T, any>[] | undefined, allowEmptyArray: boolean = false): T | undefined { taskConfiguration.ts ×16
639 > if (!source || _isEmpty(source, properties)) {
640 return target;
641 }
642 > if (!target || _isEmpty(target, properties, allowEmptyArray)) { taskConfiguration.ts ×16
643 > return source;
644 > }
645 > for (const meta of properties!) { taskConfiguration.ts ×2
646 > const property = meta.property;
647 > let value: T[keyof T] | undefined;
648 > if (meta.type) {
649 value = meta.type.fillProperties(target[property], source[property]);
650 > } else if (target[property] === undefined) { taskConfiguration.ts ×2
651 > value = source[property];
652 > }
653 > if (value !== undefined && value !== null) {
654 > (target as Record<string, unknown>)[property as string] = value;
655 > }
656 > }
657 > return target;
658 > }
660 > // eslint-disable-next-line @typescript-eslint/no-explicit-any -- IMetaData array holds heterogeneous parser types
661 > function _fillDefaults<T>(this: void, target: T | undefined, defaults: T | undefined, properties: IMetaData<T, any>[], context: IParseContext): T | undefined { taskConfiguration.ts ×45
662 > if (target && Object.isFrozen(target)) {
663 > return target; taskConfiguration.ts ×16
664 > }
665 > if (target === undefined || target === null || defaults === undefined || defaults === null) { taskConfiguration.ts ×45
666 > if (defaults !== undefined && defaults !== null) {
667 > return Objects.deepClone(defaults);
668 > } else {
669 return undefined;
670 }
672 > for (const meta of properties) { taskConfiguration.ts ×4
673 > const property = meta.property;
674 > if (target[property] !== undefined) {
675 > continue;
676 > }
677 > let value: T[keyof T] | undefined;
678 > if (meta.type) {
679 > value = meta.type.fillDefaults(target[property], context); taskConfiguration.ts ×10
680 > } else { taskConfiguration.ts ×4
681 > value = defaults[property]; taskConfiguration.ts ×1
682 > }
684 > if (value !== undefined && value !== null) {
685 > (target as Record<string, unknown>)[property as string] = value; taskConfiguration.ts ×1
686 > }
688 > return target;
689 > }
691 > // eslint-disable-next-line @typescript-eslint/no-explicit-any -- IMetaData array holds heterogeneous parser types
692 > function _freeze<T>(this: void, target: T, properties: IMetaData<T, any>[]): Readonly<T> | undefined { taskConfiguration.ts ×16
693 > if (target === undefined || target === null) {
694 return undefined;
695 }
696 > if (Object.isFrozen(target)) { taskConfiguration.ts ×16
697 return target;
698 }
699 > for (const meta of properties) { taskConfiguration.ts ×16
700 > if (meta.type) {
701 > const value = target[meta.property];
702 > if (value) {
703 > meta.type.freeze(value);
704 > }
705 > }
706 > }
707 > Object.freeze(target);
708 > return target;
709 > }
711 > export namespace RunOnOptions {
712 > export function fromString(value: string | undefined): Tasks.RunOnOptions {
713 if (!value) {
714 return Tasks.RunOnOptions.default;
715 }
716 switch (value.toLowerCase()) {
717 case 'folderopen':
718 return Tasks.RunOnOptions.folderOpen;
719 case 'worktreecreated':
720 return Tasks.RunOnOptions.worktreeCreated;
721 case 'default':
722 default:
723 return Tasks.RunOnOptions.default;
724 }
725 }
727 >
728 > export namespace RunOptions {
729 > const properties: IMetaData<Tasks.IRunOptions, void>[] = [{ property: 'reevaluateOnRerun' }, { property: 'runOn' }, { property: 'instanceLimit' }, { property: 'instancePolicy' }];
730 > export function fromConfiguration(value: IRunOptionsConfig | undefined): Tasks.IRunOptions {
731 > return { taskConfiguration.ts ×22
732 > reevaluateOnRerun: value ? value.reevaluateOnRerun : true,
733 > runOn: value ? RunOnOptions.fromString(value.runOn) : Tasks.RunOnOptions.default,
734 > instanceLimit: value?.instanceLimit ? Math.max(value.instanceLimit, 1) : 1,
735 > instancePolicy: value ? InstancePolicy.fromString(value.instancePolicy) : Tasks.InstancePolicy.prompt
736 > };
737 > }
739 > export function assignProperties(target: Tasks.IRunOptions, source: Tasks.IRunOptions | undefined): Tasks.IRunOptions {
740 return _assignProperties(target, source, properties)!;
741 }
743 > export function fillProperties(target: Tasks.IRunOptions, source: Tasks.IRunOptions | undefined): Tasks.IRunOptions {
744 return _fillProperties(target, source, properties)!;
745 }
747 >
748 > export namespace InstancePolicy {
749 > export function fromString(value: string | undefined): Tasks.InstancePolicy {
750 if (!value) {
751 return Tasks.InstancePolicy.prompt;
752 }
753 switch (value.toLowerCase()) {
754 case 'terminatenewest':
755 return Tasks.InstancePolicy.terminateNewest;
756 case 'terminateoldest':
757 return Tasks.InstancePolicy.terminateOldest;
758 case 'warn':
759 return Tasks.InstancePolicy.warn;
760 case 'silent':
761 return Tasks.InstancePolicy.silent;
762 case 'prompt':
763 default:
764 return Tasks.InstancePolicy.prompt;
765 }
766 }
768 >
769 > export interface IParseContext {
770 > workspaceFolder: IWorkspaceFolder;
771 > workspace: IWorkspace | undefined;
772 > problemReporter: IProblemReporter;
773 > namedProblemMatchers: IStringDictionary<INamedProblemMatcher>;
774 > uuidMap: UUIDMap;
775 > engine: Tasks.ExecutionEngine;
776 > schemaVersion: Tasks.JsonSchemaVersion;
777 > platform: Platform;
778 > taskLoadIssues: string[];
779 > contextKeyService: IContextKeyService;
780 > }
781 >
782 >
783 > namespace ShellConfiguration {
784 >
785 > const properties: IMetaData<Tasks.IShellConfiguration, void>[] = [{ property: 'executable' }, { property: 'args' }, { property: 'quoting' }];
786 >
787 > export function is(value: unknown): value is IShellConfiguration {
788 > const candidate: IShellConfiguration = value as IShellConfiguration; taskConfiguration.ts ×1
789 > return candidate && (Types.isString(candidate.executable) || Types.isStringArray(candidate.args));
790 > }
792 > export function from(this: void, config: IShellConfiguration | undefined, context: IParseContext): Tasks.IShellConfiguration | undefined {
793 > if (!is(config)) { taskConfiguration.ts ×10
794 > return undefined;
795 > }
796 const result: IShellConfiguration = {};
797 if (config.executable !== undefined) {
798 result.executable = config.executable;
799 }
800 if (config.args !== undefined) {
801 result.args = config.args.slice();
802 }
803 if (config.quoting !== undefined) {
804 result.quoting = Objects.deepClone(config.quoting);
805 }
806
807 return result;
810 > export function isEmpty(this: void, value: Tasks.IShellConfiguration): boolean {
811 return _isEmpty(value, properties, true);
812 }
814 > export function assignProperties(this: void, target: Tasks.IShellConfiguration | undefined, source: Tasks.IShellConfiguration | undefined): Tasks.IShellConfiguration | undefined {
815 return _assignProperties(target, source, properties);
816 }
818 > export function fillProperties(this: void, target: Tasks.IShellConfiguration, source: Tasks.IShellConfiguration): Tasks.IShellConfiguration | undefined {
819 return _fillProperties(target, source, properties, true);
820 }
822 > export function fillDefaults(this: void, value: Tasks.IShellConfiguration, context: IParseContext): Tasks.IShellConfiguration {
823 > return value; taskConfiguration.ts ×10
824 > }
826 > export function freeze(this: void, value: Tasks.IShellConfiguration): Readonly<Tasks.IShellConfiguration> | undefined {
827 if (!value) {
828 return undefined;
829 }
830 return Object.freeze(value);
831 }
833 >
834 > namespace CommandOptions {
835 >
836 > const properties: IMetaData<Tasks.CommandOptions, Tasks.IShellConfiguration>[] = [{ property: 'cwd' }, { property: 'env' }, { property: 'shell', type: ShellConfiguration }];
837 > const defaults: ICommandOptionsConfig = { cwd: '${workspaceFolder}' };
838 >
839 > export function from(this: void, options: ICommandOptionsConfig, context: IParseContext): Tasks.CommandOptions | undefined {
840 > const result: Tasks.CommandOptions = {}; taskConfiguration.ts ×10
841 > if (options.cwd !== undefined) {
842 > if (Types.isString(options.cwd)) { taskConfiguration.ts ×2
843 > result.cwd = options.cwd;
844 > } else {
845 context.taskLoadIssues.push(nls.localize('ConfigurationParser.invalidCWD', 'Warning: options.cwd must be of type string. Ignoring value {0}\n', options.cwd));
846 }
848 > if (options.env !== undefined) { taskConfiguration.ts ×10
849 > result.env = Objects.deepClone(options.env); taskConfiguration.ts ×1
850 > }
851 > result.shell = ShellConfiguration.from(options.shell, context); taskConfiguration.ts ×10
852 > return isEmpty(result) ? undefined : result;
853 > }
855 > export function isEmpty(value: Tasks.CommandOptions | undefined): boolean {
856 > return _isEmpty(value, properties); taskConfiguration.ts ×10
857 > }
859 > export function assignProperties(target: Tasks.CommandOptions | undefined, source: Tasks.CommandOptions | undefined): Tasks.CommandOptions | undefined {
860 > if ((source === undefined) || isEmpty(source)) { taskConfiguration.ts ×12
861 > return target;
862 > }
863 > if ((target === undefined) || isEmpty(target)) {
864 return source;
865 }
866 assignProperty(target, source, 'cwd');
867 if (target.env === undefined) {
868 target.env = source.env;
869 } else if (source.env !== undefined) {
870 const env: { [key: string]: string } = Object.create(null);
871 if (target.env !== undefined) {
872 Object.keys(target.env).forEach(key => env[key] = target.env![key]);
873 }
874 if (source.env !== undefined) {
875 Object.keys(source.env).forEach(key => env[key] = source.env![key]);
876 }
877 target.env = env;
878 }
879 target.shell = ShellConfiguration.assignProperties(target.shell, source.shell);
880 return target;
883 > export function fillProperties(target: Tasks.CommandOptions | undefined, source: Tasks.CommandOptions | undefined): Tasks.CommandOptions | undefined {
884 > return _fillProperties(target, source, properties); taskConfiguration.ts ×16
885 > }
887 > export function fillDefaults(value: Tasks.CommandOptions | undefined, context: IParseContext): Tasks.CommandOptions | undefined {
888 > return _fillDefaults(value, defaults, properties, context); taskConfiguration.ts ×45
889 > }
891 > export function freeze(value: Tasks.CommandOptions): Readonly<Tasks.CommandOptions> | undefined {
892 > return _freeze(value, properties); taskConfiguration.ts ×16
893 > }
895 >
896 > namespace CommandConfiguration {
897 >
898 > export namespace PresentationOptions {
899 > const properties: IMetaData<Tasks.IPresentationOptions, void>[] = [{ property: 'echo' }, { property: 'reveal' }, { property: 'revealProblems' }, { property: 'focus' }, { property: 'panel' }, { property: 'showReuseMessage' }, { property: 'clear' }, { property: 'group' }, { property: 'close' }, { property: 'preserveTerminalName' }];
900 >
901 > interface IPresentationOptionsShape extends ILegacyCommandProperties {
902 > presentation?: IPresentationOptionsConfig;
903 > }
904 >
905 > export function from(this: void, config: IPresentationOptionsShape, context: IParseContext): Tasks.IPresentationOptions | undefined {
906 > let echo: boolean; taskConfiguration.ts ×45
907 > let reveal: Tasks.RevealKind;
908 > let revealProblems: Tasks.RevealProblemKind;
909 > let focus: boolean;
910 > let panel: Tasks.PanelKind;
911 > let showReuseMessage: boolean;
912 > let clear: boolean;
913 > let group: string | undefined;
914 > let close: boolean | undefined;
915 > let preserveTerminalName: boolean | undefined;
916 > let hasProps = false;
917 > if (Types.isBoolean(config.echoCommand)) {
918 > echo = config.echoCommand; taskConfiguration.ts ×1
919 > hasProps = true;
920 > }
921 > if (Types.isString(config.showOutput)) { taskConfiguration.ts ×45
922 > reveal = Tasks.RevealKind.fromString(config.showOutput); tasks.ts ×5
923 > hasProps = true;
924 > }
925 > const presentation = config.presentation || config.terminal; taskConfiguration.ts ×45
926 > if (presentation) {
927 if (Types.isBoolean(presentation.echo)) {
928 echo = presentation.echo;
929 }
930 if (Types.isString(presentation.reveal)) {
931 reveal = Tasks.RevealKind.fromString(presentation.reveal);
932 }
933 if (Types.isString(presentation.revealProblems)) {
934 revealProblems = Tasks.RevealProblemKind.fromString(presentation.revealProblems);
935 }
936 if (Types.isBoolean(presentation.focus)) {
937 focus = presentation.focus;
938 }
939 if (Types.isString(presentation.panel)) {
940 panel = Tasks.PanelKind.fromString(presentation.panel);
941 }
942 if (Types.isBoolean(presentation.showReuseMessage)) {
943 showReuseMessage = presentation.showReuseMessage;
944 }
945 if (Types.isBoolean(presentation.clear)) {
946 clear = presentation.clear;
947 }
948 if (Types.isString(presentation.group)) {
949 group = presentation.group;
950 }
951 if (Types.isBoolean(presentation.close)) {
952 close = presentation.close;
953 }
954 if (Types.isBoolean(presentation.preserveTerminalName)) {
955 preserveTerminalName = presentation.preserveTerminalName;
956 }
957 hasProps = true;
958 }
959 > if (!hasProps) { taskConfiguration.ts ×45
960 > return undefined; taskConfiguration.ts ×1
961 > }
962 > return { echo: echo!, reveal: reveal!, revealProblems: revealProblems!, focus: focus!, panel: panel!, showReuseMessage: showReuseMessage!, clear: clear!, group, close: close, preserveTerminalName }; taskConfiguration.ts ×1
965 > export function assignProperties(target: Tasks.IPresentationOptions, source: Tasks.IPresentationOptions | undefined): Tasks.IPresentationOptions | undefined {
966 > return _assignProperties(target, source, properties); taskConfiguration.ts ×12
967 > }
969 > export function fillProperties(target: Tasks.IPresentationOptions, source: Tasks.IPresentationOptions | undefined): Tasks.IPresentationOptions | undefined {
970 > return _fillProperties(target, source, properties); taskConfiguration.ts ×16
971 > }
973 > export function fillDefaults(value: Tasks.IPresentationOptions, context: IParseContext): Tasks.IPresentationOptions | undefined {
974 > const defaultEcho = context.engine === Tasks.ExecutionEngine.Terminal ? true : false; taskConfiguration.ts ×45
975 > return _fillDefaults(value, { echo: defaultEcho, reveal: Tasks.RevealKind.Always, revealProblems: Tasks.RevealProblemKind.Never, focus: false, panel: Tasks.PanelKind.Shared, showReuseMessage: true, clear: false, preserveTerminalName: false }, properties, context);
976 > }
978 > export function freeze(value: Tasks.IPresentationOptions): Readonly<Tasks.IPresentationOptions> | undefined {
979 > return _freeze(value, properties); taskConfiguration.ts ×16
980 > }
982 > export function isEmpty(this: void, value: Tasks.IPresentationOptions): boolean {
983 > return _isEmpty(value, properties); taskConfiguration.ts ×3
984 > }
986 >
987 > namespace ShellString {
988 > export function from(this: void, value: CommandString | undefined): Tasks.CommandString | undefined {
989 > if (value === undefined || value === null) { taskConfiguration.ts ×45
990 > return undefined; taskConfiguration.ts ×1
991 > }
992 > if (Types.isString(value)) { taskConfiguration.ts ×1
993 > return value;
994 > } else if (Types.isStringArray(value)) {
995 return value.join(' ');
996 } else {
997 const quoting = Tasks.ShellQuoting.from(value.quoting);
998 const result = Types.isString(value.value) ? value.value : Types.isStringArray(value.value) ? value.value.join(' ') : undefined;
999 if (result) {
1000 return {
1001 value: result,
1002 quoting: quoting
1003 };
1004 } else {
1005 return undefined;
1006 }
1007 }
1010 >
1011 > interface IBaseCommandConfigurationShape extends IBaseCommandProperties, ILegacyCommandProperties {
1012 > }
1013 >
1014 > interface ICommandConfigurationShape extends IBaseCommandConfigurationShape {
1015 > windows?: IBaseCommandConfigurationShape;
1016 > osx?: IBaseCommandConfigurationShape;
1017 > linux?: IBaseCommandConfigurationShape;
1018 > }
1019 >
1020 > // eslint-disable-next-line @typescript-eslint/no-explicit-any -- IMetaData array holds heterogeneous parser types
1021 > const properties: IMetaData<Tasks.ICommandConfiguration, any>[] = [
1022 > { property: 'runtime' }, { property: 'name' }, { property: 'options', type: CommandOptions },
1023 > { property: 'args' }, { property: 'taskSelector' }, { property: 'suppressTaskName' },
1024 > { property: 'presentation', type: PresentationOptions }
1025 > ];
1026 >
1027 > export function from(this: void, config: ICommandConfigurationShape, context: IParseContext): Tasks.ICommandConfiguration | undefined {
1028 > let result: Tasks.ICommandConfiguration = fromBase(config, context)!; taskConfiguration.ts ×45
1029 >
1030 > let osConfig: Tasks.ICommandConfiguration | undefined = undefined;
1031 > if (config.windows && context.platform === Platform.Windows) {
1032 osConfig = fromBase(config.windows, context);
1033 > } else if (config.osx && context.platform === Platform.Mac) { taskConfiguration.ts ×45
1034 osConfig = fromBase(config.osx, context);
1035 > } else if (config.linux && context.platform === Platform.Linux) { taskConfiguration.ts ×45
1036 > osConfig = fromBase(config.linux, context); taskConfiguration.ts ×12
1037 > }
1038 > if (osConfig) { taskConfiguration.ts ×45
1039 > result = assignProperties(result, osConfig, context.schemaVersion === Tasks.JsonSchemaVersion.V2_0_0); taskConfiguration.ts ×12
1040 > }
1041 > return isEmpty(result) ? undefined : result; taskConfiguration.ts ×45
1042 > }
1044 > function fromBase(this: void, config: IBaseCommandConfigurationShape, context: IParseContext): Tasks.ICommandConfiguration | undefined {
1045 > const name: Tasks.CommandString | undefined = ShellString.from(config.command); taskConfiguration.ts ×45
1046 > let runtime: Tasks.RuntimeType;
1047 > if (Types.isString(config.type)) {
1048 > if (config.type === 'shell' || config.type === 'process') { tasks.ts ×4
1049 > runtime = Tasks.RuntimeType.fromString(config.type);
1050 > }
1051 > }
1052 > if (Types.isBoolean(config.isShellCommand) || ShellConfiguration.is(config.isShellCommand)) { taskConfiguration.ts ×45
1053 > runtime = Tasks.RuntimeType.Shell; taskConfiguration.ts ×1
1054 > } else if (config.isShellCommand !== undefined) { taskConfiguration.ts ×45
1055 runtime = !!config.isShellCommand ? Tasks.RuntimeType.Shell : Tasks.RuntimeType.Process;
1056 }
1058 > const result: Tasks.ICommandConfiguration = {
1059 > name: name,
1060 > runtime: runtime!,
1061 > presentation: PresentationOptions.from(config, context)!
1062 > };
1063 >
1064 > if (config.args !== undefined) {
1065 > result.args = []; taskConfiguration.ts ×2
1066 > for (const arg of config.args) {
1067 > const converted = ShellString.from(arg);
1068 > if (converted !== undefined) {
1069 > result.args.push(converted);
1070 > } else {
1071 context.taskLoadIssues.push(
1072 nls.localize(
1073 'ConfigurationParser.inValidArg',
1074 'Error: command argument must either be a string or a quoted string. Provided value is:\n{0}',
1075 arg ? JSON.stringify(arg, undefined, 4) : 'undefined'
1076 ));
1077 }
1079 > }
1080 > if (config.options !== undefined) { taskConfiguration.ts ×45
1081 > result.options = CommandOptions.from(config.options, context); taskConfiguration.ts ×10
1082 > if (result.options && result.options.shell === undefined && ShellConfiguration.is(config.isShellCommand)) {
1083 result.options.shell = ShellConfiguration.from(config.isShellCommand, context);
1084 if (context.engine !== Tasks.ExecutionEngine.Terminal) {
1085 context.taskLoadIssues.push(nls.localize('ConfigurationParser.noShell', 'Warning: shell configuration is only supported when executing tasks in the terminal.'));
1086 }
1087 }
1090 > if (Types.isString(config.taskSelector)) {
1091 > result.taskSelector = config.taskSelector; taskConfiguration.ts ×2
1092 > }
1093 > if (Types.isBoolean(config.suppressTaskName)) { taskConfiguration.ts ×45
1094 > result.suppressTaskName = config.suppressTaskName; taskConfiguration.ts ×2
1095 > }
1097 > return isEmpty(result) ? undefined : result;
1098 > }
1100 > export function hasCommand(value: Tasks.ICommandConfiguration): boolean {
1101 > return value && !!value.name; taskConfiguration.ts ×45
1102 > }
1104 > export function isEmpty(value: Tasks.ICommandConfiguration | undefined): boolean {
1105 > return _isEmpty(value, properties); taskConfiguration.ts ×45
1106 > }
1108 > export function assignProperties(target: Tasks.ICommandConfiguration, source: Tasks.ICommandConfiguration, overwriteArgs: boolean): Tasks.ICommandConfiguration {
1109 > if (isEmpty(source)) { taskConfiguration.ts ×12
1110 return target;
1111 }
1112 > if (isEmpty(target)) { taskConfiguration.ts ×12
1113 return source;
1114 }
1115 > assignProperty(target, source, 'name'); taskConfiguration.ts ×12
1116 > assignProperty(target, source, 'runtime');
1117 > assignProperty(target, source, 'taskSelector');
1118 > assignProperty(target, source, 'suppressTaskName');
1119 > if (source.args !== undefined) {
1120 > if (target.args === undefined || overwriteArgs) { taskConfiguration.ts ×3
1121 > target.args = source.args; taskConfiguration.ts ×3
1122 > } else { taskConfiguration.ts ×3
1123 > target.args = target.args.concat(source.args); taskConfiguration.ts ×1
1124 > }
1126 > target.presentation = PresentationOptions.assignProperties(target.presentation!, source.presentation)!; taskConfiguration.ts ×12
1127 > target.options = CommandOptions.assignProperties(target.options, source.options);
1128 > return target;
1129 > }
1131 > export function fillProperties(target: Tasks.ICommandConfiguration, source: Tasks.ICommandConfiguration): Tasks.ICommandConfiguration | undefined {
1132 return _fillProperties(target, source, properties);
1133 }
1135 > export function fillGlobals(target: Tasks.ICommandConfiguration, source: Tasks.ICommandConfiguration | undefined, taskName: string | undefined): Tasks.ICommandConfiguration {
1136 > if ((source === undefined) || isEmpty(source)) { taskConfiguration.ts ×45
1137 > return target; taskConfiguration.ts ×1
1138 > }
1139 > target = target || { taskConfiguration.ts ×16
1140 name: undefined,
1141 runtime: undefined,
1142 presentation: undefined
1143 };
1144 > if (target.name === undefined) { taskConfiguration.ts ×45
1145 > fillProperty(target, source, 'name'); taskConfiguration.ts ×3
1146 > fillProperty(target, source, 'taskSelector');
1147 > fillProperty(target, source, 'suppressTaskName');
1148 > let args: Tasks.CommandString[] = source.args ? source.args.slice() : [];
1149 > if (!target.suppressTaskName && taskName) {
1150 > if (target.taskSelector !== undefined) { taskConfiguration.ts ×3
1151 > args.push(target.taskSelector + taskName); taskConfiguration.ts ×2
1152 > } else { taskConfiguration.ts ×3
1153 > args.push(taskName); taskConfiguration.ts ×1
1154 > }
1156 > if (target.args) { taskConfiguration.ts ×3
1157 > args = args.concat(target.args); taskConfiguration.ts ×1
1158 > }
1159 > target.args = args; taskConfiguration.ts ×3
1160 > }
1161 > fillProperty(target, source, 'runtime'); taskConfiguration.ts ×16
1162 >
1163 > target.presentation = PresentationOptions.fillProperties(target.presentation!, source.presentation)!;
1164 > target.options = CommandOptions.fillProperties(target.options, source.options);
1165 >
1166 > return target;
1169 > export function fillDefaults(value: Tasks.ICommandConfiguration | undefined, context: IParseContext): void {
1170 > if (!value || Object.isFrozen(value)) { taskConfiguration.ts ×45
1171 > return; taskConfiguration.ts ×1
1172 > }
1173 > if (value.name !== undefined && value.runtime === undefined) { taskConfiguration.ts ×45
1174 > value.runtime = Tasks.RuntimeType.Process; taskConfiguration.ts ×1
1175 > }
1176 > value.presentation = PresentationOptions.fillDefaults(value.presentation!, context)!; taskConfiguration.ts ×45
1177 > if (!isEmpty(value)) {
1178 > value.options = CommandOptions.fillDefaults(value.options, context);
1179 > }
1180 > if (value.args === undefined) {
1181 > value.args = EMPTY_ARRAY; taskConfiguration.ts ×1
1182 > }
1183 > if (value.suppressTaskName === undefined) { taskConfiguration.ts ×45
1184 > value.suppressTaskName = (context.schemaVersion === Tasks.JsonSchemaVersion.V2_0_0); taskConfiguration.ts ×1
1185 > }
1188 > export function freeze(value: Tasks.ICommandConfiguration): Readonly<Tasks.ICommandConfiguration> | undefined {
1189 > return _freeze(value, properties); taskConfiguration.ts ×16
1190 > }
1192 >
1193 > export namespace ProblemMatcherConverter {
1194 >
1195 > export function namedFrom(this: void, declares: ProblemMatcherConfig.INamedProblemMatcher[] | undefined, context: IParseContext): IStringDictionary<INamedProblemMatcher> {
1196 > const result: IStringDictionary<INamedProblemMatcher> = Object.create(null); taskConfiguration.ts ×41
1197 >
1198 > if (!Array.isArray(declares)) {
1199 > return result;
1200 > }
1201 (<ProblemMatcherConfig.INamedProblemMatcher[]>declares).forEach((value) => {
1202 const namedProblemMatcher = (new ProblemMatcherParser(context.problemReporter)).parse(value);
1203 if (isNamedProblemMatcher(namedProblemMatcher)) {
1204 result[namedProblemMatcher.name] = namedProblemMatcher;
1205 } else {
1206 context.problemReporter.error(nls.localize('ConfigurationParser.noName', 'Error: Problem Matcher in declare scope must have a name:\n{0}\n', JSON.stringify(value, undefined, 4)));
1207 }
1208 });
1209 return result;
1212 > export function fromWithOsConfig(this: void, external: IConfigurationProperties & { [key: string]: unknown }, context: IParseContext): TaskConfigurationValueWithErrors<ProblemMatcher[]> {
1213 > let result: TaskConfigurationValueWithErrors<ProblemMatcher[]> = {}; taskConfiguration.ts ×22
1214 > const osExternal = external as unknown as { windows?: { problemMatcher?: ProblemMatcherConfig.ProblemMatcherType }; osx?: { problemMatcher?: ProblemMatcherConfig.ProblemMatcherType }; linux?: { problemMatcher?: ProblemMatcherConfig.ProblemMatcherType } };
1215 > if (osExternal.windows?.problemMatcher && context.platform === Platform.Windows) {
1216 result = from(osExternal.windows.problemMatcher, context);
1217 > } else if (osExternal.osx?.problemMatcher && context.platform === Platform.Mac) { taskConfiguration.ts ×22
1218 result = from(osExternal.osx.problemMatcher, context);
1219 > } else if (osExternal.linux?.problemMatcher && context.platform === Platform.Linux) { taskConfiguration.ts ×22
1220 result = from(osExternal.linux.problemMatcher, context);
1221 > } else if (external.problemMatcher) { taskConfiguration.ts ×22
1222 > result = from(external.problemMatcher, context); problemMatcher.ts ×30
1223 > }
1224 > return result; taskConfiguration.ts ×22
1225 > }
1227 > export function from(this: void, config: ProblemMatcherConfig.ProblemMatcherType | undefined, context: IParseContext): TaskConfigurationValueWithErrors<ProblemMatcher[]> {
1228 > const result: ProblemMatcher[] = []; taskConfiguration.ts ×2
1229 > if (config === undefined) {
1230 > return { value: result }; taskConfiguration.ts ×1
1231 > }
1232 > const errors: string[] = []; taskConfiguration.ts ×11
1233 > function addResult(matcher: TaskConfigurationValueWithErrors<ProblemMatcher>) {
1234 > if (matcher.value) {
1235 > result.push(matcher.value); taskConfiguration.ts ×1
1236 > }
1237 > if (matcher.errors) { taskConfiguration.ts ×11
1238 > errors.push(...matcher.errors); taskConfiguration.ts ×2
1239 > }
1241 > const kind = getProblemMatcherKind(config);
1242 > if (kind === ProblemMatcherKind.Unknown) {
1243 const error = nls.localize(
1244 'ConfigurationParser.unknownMatcherKind',
1245 'Warning: the defined problem matcher is unknown. Supported types are string | ProblemMatcher | Array<string | ProblemMatcher>.\n{0}\n',
1246 JSON.stringify(config, null, 4));
1247 context.problemReporter.warn(error);
1248 > } else if (kind === ProblemMatcherKind.String || kind === ProblemMatcherKind.ProblemMatcher) { taskConfiguration.ts ×11
1249 > addResult(resolveProblemMatcher(config as ProblemMatcherConfig.ProblemMatcher, context)); taskConfiguration.ts ×1
1250 > } else if (kind === ProblemMatcherKind.Array) { taskConfiguration.ts ×11
1251 > const problemMatchers = <(string | ProblemMatcherConfig.ProblemMatcher)[]>config; taskConfiguration.ts ×2
1252 > problemMatchers.forEach(problemMatcher => {
1253 > addResult(resolveProblemMatcher(problemMatcher, context));
1254 > });
1255 > }
1256 > return { value: result, errors }; taskConfiguration.ts ×11
1259 > function getProblemMatcherKind(this: void, value: ProblemMatcherConfig.ProblemMatcherType): ProblemMatcherKind {
1260 > if (Types.isString(value)) { taskConfiguration.ts ×11
1261 > return ProblemMatcherKind.String; taskConfiguration.ts ×1
1262 > } else if (Array.isArray(value)) { taskConfiguration.ts ×11
1263 > return ProblemMatcherKind.Array; taskConfiguration.ts ×2
1264 > } else if (!Types.isUndefined(value)) { taskConfiguration.ts ×1
1265 > return ProblemMatcherKind.ProblemMatcher; problemMatcher.ts ×30
1266 > } else {
1267 return ProblemMatcherKind.Unknown;
1268 }
1271 > function resolveProblemMatcher(this: void, value: string | ProblemMatcherConfig.ProblemMatcher, context: IParseContext): TaskConfigurationValueWithErrors<ProblemMatcher> {
1272 > if (Types.isString(value)) { taskConfiguration.ts ×11
1273 > let variableName = <string>value; taskConfiguration.ts ×2
1274 > if (variableName.length > 1 && variableName[0] === '$') {
1275 > variableName = variableName.substring(1);
1276 > const global = ProblemMatcherRegistry.get(variableName);
1277 > if (global) {
1278 > return { value: Objects.deepClone(global) }; taskConfiguration.ts ×2
1279 > }
1280 > let localProblemMatcher: ProblemMatcher & Partial<INamedProblemMatcher> = context.namedProblemMatchers[variableName]; taskConfiguration.ts ×1
1281 > if (localProblemMatcher) {
1282 > localProblemMatcher = Objects.deepClone(localProblemMatcher); taskConfiguration.ts ×1
1283 > // remove the name
1284 > delete localProblemMatcher.name;
1285 > return { value: localProblemMatcher };
1286 > }
1288 > return { errors: [nls.localize('ConfigurationParser.invalidVariableReference', 'Error: Invalid problemMatcher reference: {0}\n', value)] }; taskConfiguration.ts ×2
1289 > } else { taskConfiguration.ts ×1
1290 > const json = <ProblemMatcherConfig.ProblemMatcher>value; problemMatcher.ts ×30
1291 > return { value: new ProblemMatcherParser(context.problemReporter).parse(json) };
1292 > }
1295 >
1296 > export namespace GroupKind {
1297 > export function from(this: void, external: string | IGroupKind | undefined): Tasks.TaskGroup | undefined {
1298 > if (external === undefined) { taskConfiguration.ts ×6
1299 > return undefined; taskConfiguration.ts ×1
1300 > } else if (Types.isString(external) && Tasks.TaskGroup.is(external)) { taskConfiguration.ts ×6
1301 return { _id: external, isDefault: false };
1302 > } else if (Types.isString(external.kind) && Tasks.TaskGroup.is(external.kind)) { taskConfiguration.ts ×2
1303 const group: string = external.kind;
1304 const isDefault: boolean | string = Types.isUndefined(external.isDefault) ? false : external.isDefault;
1305
1306 return { _id: group, isDefault };
1307 }
1308 > return undefined; taskConfiguration.ts ×2
1311 > export function to(group: Tasks.TaskGroup | string): IGroupKind | string {
1312 if (Types.isString(group)) {
1313 return group;
1314 } else if (!group.isDefault) {
1315 return group._id;
1316 }
1317 return {
1318 kind: group._id,
1319 isDefault: group.isDefault,
1320 };
1321 }
1323 >
1324 > namespace TaskDependency {
1325 > function uriFromSource(context: IParseContext, source: TaskConfigSource): URI | string {
1326 switch (source) {
1327 case TaskConfigSource.User: return Tasks.USER_TASKS_GROUP_KEY;
1328 case TaskConfigSource.TasksJson: return context.workspaceFolder.uri;
1329 default: return context.workspace && context.workspace.configuration ? context.workspace.configuration : context.workspaceFolder.uri;
1330 }
1331 }
1333 > export function from(this: void, external: string | ITaskIdentifier, context: IParseContext, source: TaskConfigSource): Tasks.ITaskDependency | undefined {
1334 if (Types.isString(external)) {
1335 return { uri: uriFromSource(context, source), task: external };
1336 } else if (ITaskIdentifier.is(external)) {
1337 return {
1338 uri: uriFromSource(context, source),
1339 task: Tasks.TaskDefinition.createTaskIdentifier(external as Tasks.ITaskIdentifier, context.problemReporter)
1340 };
1341 } else {
1342 return undefined;
1343 }
1344 }
1346 >
1347 > namespace DependsOrder {
1348 > export function from(order: string | undefined): Tasks.DependsOrder {
1349 > switch (order) { taskConfiguration.ts ×22
1350 > case Tasks.DependsOrder.sequence:
1351 return Tasks.DependsOrder.sequence;
1352 > case Tasks.DependsOrder.parallel: taskConfiguration.ts ×22
1353 > default:
1354 > return Tasks.DependsOrder.parallel;
1355 > }
1356 > }
1358 >
1359 > namespace ConfigurationProperties {
1360 >
1361 > // eslint-disable-next-line @typescript-eslint/no-explicit-any -- IMetaData array holds heterogeneous parser types
1362 > const properties: IMetaData<Tasks.IConfigurationProperties, any>[] = [
1363 > { property: 'name' },
1364 > { property: 'identifier' },
1365 > { property: 'group' },
1366 > { property: 'isBackground' },
1367 > { property: 'promptOnClose' },
1368 > { property: 'dependsOn' },
1369 > { property: 'presentation', type: CommandConfiguration.PresentationOptions },
1370 > { property: 'problemMatchers' },
1371 > { property: 'options' },
1372 > { property: 'icon' },
1373 > { property: 'hide' },
1374 > { property: 'inAgents' }
1375 > ];
1376 >
1377 > export function from(this: void, external: IConfigurationProperties & { [key: string]: unknown }, context: IParseContext,
1378 > includeCommandOptions: boolean, source: TaskConfigSource, properties?: IJSONSchemaMap): TaskConfigurationValueWithErrors<Tasks.IConfigurationProperties> { taskConfiguration.ts ×22
1379 > if (!external) {
1380 return {};
1381 }
1382 > const result: Tasks.IConfigurationProperties & { [key: string]: unknown } = {}; taskConfiguration.ts ×22
1383 >
1384 > if (properties) {
1385 > for (const propertyName of Object.keys(properties)) { taskConfiguration.ts ×13
1386 if (external[propertyName] !== undefined) {
1387 result[propertyName] = Objects.deepClone(external[propertyName]);
1388 }
1389 }
1392 > if (Types.isString(external.taskName)) {
1393 > result.name = external.taskName; taskConfiguration.ts ×1
1394 > }
1395 > if (Types.isString(external.label) && context.schemaVersion === Tasks.JsonSchemaVersion.V2_0_0) { taskConfiguration.ts ×22
1396 > result.name = external.label; taskConfiguration.ts ×3
1397 > }
1398 > if (Types.isString(external.identifier)) { taskConfiguration.ts ×22
1399 result.identifier = external.identifier;
1400 }
1401 > result.icon = external.icon; taskConfiguration.ts ×22
1402 > result.hide = external.hide;
1403 > result.inAgents = external.inAgents;
1404 > if (external.isBackground !== undefined) {
1405 result.isBackground = !!external.isBackground;
1406 }
1407 > if (external.promptOnClose !== undefined) { taskConfiguration.ts ×22
1408 > result.promptOnClose = !!external.promptOnClose; taskConfiguration.ts ×1
1409 > }
1410 > result.group = GroupKind.from(external.group); taskConfiguration.ts ×22
1411 > if (external.dependsOn !== undefined) {
1412 if (Array.isArray(external.dependsOn)) {
1413 result.dependsOn = external.dependsOn.reduce((dependencies: Tasks.ITaskDependency[], item): Tasks.ITaskDependency[] => {
1414 const dependency = TaskDependency.from(item, context, source);
1415 if (dependency) {
1416 dependencies.push(dependency);
1417 }
1418 return dependencies;
1419 }, []);
1420 } else {
1421 const dependsOnValue = TaskDependency.from(external.dependsOn, context, source);
1422 result.dependsOn = dependsOnValue ? [dependsOnValue] : undefined;
1423 }
1424 }
1425 > result.dependsOrder = DependsOrder.from(external.dependsOrder); taskConfiguration.ts ×22
1426 > if (includeCommandOptions && (external.presentation !== undefined || (external as ILegacyCommandProperties).terminal !== undefined)) {
1427 result.presentation = CommandConfiguration.PresentationOptions.from(external, context);
1428 }
1429 > if (includeCommandOptions && (external.options !== undefined)) { taskConfiguration.ts ×22
1430 result.options = CommandOptions.from(external.options, context);
1431 }
1432 > const configProblemMatcher = ProblemMatcherConverter.fromWithOsConfig(external, context); taskConfiguration.ts ×22
1433 > if (configProblemMatcher.value !== undefined) {
1434 > result.problemMatchers = configProblemMatcher.value; problemMatcher.ts ×30
1435 > }
1436 > if (external.detail) { taskConfiguration.ts ×22
1437 result.detail = external.detail;
1438 }
1439 > return isEmpty(result) ? {} : { value: result, errors: configProblemMatcher.errors }; taskConfiguration.ts ×22
1440 > }
1442 > export function isEmpty(this: void, value: Tasks.IConfigurationProperties): boolean {
1443 > return _isEmpty(value, properties); taskConfiguration.ts ×22
1444 > }
1446 > const label = 'Workspace';
1447 >
1448 > namespace ConfiguringTask {
1449 >
1450 > const grunt = 'grunt.';
1451 > const jake = 'jake.';
1452 > const gulp = 'gulp.';
1453 > const npm = 'vscode.npm.';
1454 > const typescript = 'vscode.typescript.';
1455 >
1456 > interface ICustomizeShape {
1457 > customize: string;
1458 > }
1459 >
1460 > export function from(this: void, external: IConfiguringTask, context: IParseContext, index: number, source: TaskConfigSource, registry?: Partial<ITaskDefinitionRegistry>): Tasks.ConfiguringTask | undefined {
1461 > if (!external) { taskConfiguration.ts ×13
1462 return undefined;
1463 }
1464 > const type = external.type; taskConfiguration.ts ×13
1465 > const customize = (external as ICustomizeShape).customize;
1466 > if (!type && !customize) {
1467 context.problemReporter.error(nls.localize('ConfigurationParser.noTaskType', 'Error: tasks configuration must have a type property. The configuration will be ignored.\n{0}\n', JSON.stringify(external, null, 4)));
1468 return undefined;
1469 }
1470 > const typeDeclaration = type ? registry?.get?.(type) || TaskDefinitionRegistry.get(type) : undefined; taskConfiguration.ts ×13
1471 > if (!typeDeclaration) {
1472 const message = nls.localize('ConfigurationParser.noTypeDefinition', 'Error: there is no registered task type \'{0}\'. Did you miss installing an extension that provides a corresponding task provider?', type);
1473 context.problemReporter.error(message);
1474 return undefined;
1475 }
1476 > let identifier: Tasks.ITaskIdentifier | undefined; taskConfiguration.ts ×13
1477 > if (Types.isString(customize)) {
1478 if (customize.indexOf(grunt) === 0) {
1479 identifier = { type: 'grunt', task: customize.substring(grunt.length) };
1480 } else if (customize.indexOf(jake) === 0) {
1481 identifier = { type: 'jake', task: customize.substring(jake.length) };
1482 } else if (customize.indexOf(gulp) === 0) {
1483 identifier = { type: 'gulp', task: customize.substring(gulp.length) };
1484 } else if (customize.indexOf(npm) === 0) {
1485 identifier = { type: 'npm', script: customize.substring(npm.length + 4) };
1486 } else if (customize.indexOf(typescript) === 0) {
1487 identifier = { type: 'typescript', tsconfig: customize.substring(typescript.length + 6) };
1488 }
1489 > } else { taskConfiguration.ts ×13
1490 > if (Types.isString(external.type)) {
1491 > identifier = external as Tasks.ITaskIdentifier;
1492 > }
1493 > }
1494 > if (identifier === undefined) {
1495 context.problemReporter.error(nls.localize(
1496 'ConfigurationParser.missingType',
1497 'Error: the task configuration \'{0}\' is missing the required property \'type\'. The task configuration will be ignored.', JSON.stringify(external, undefined, 0)
1498 ));
1499 return undefined;
1500 }
1501 > const taskIdentifier: Tasks.KeyedTaskIdentifier | undefined = Tasks.TaskDefinition.createTaskIdentifier(identifier, context.problemReporter); taskConfiguration.ts ×13
1502 > if (taskIdentifier === undefined) {
1503 context.problemReporter.error(nls.localize(
1504 'ConfigurationParser.incorrectType',
1505 'Error: the task configuration \'{0}\' is using an unknown type. The task configuration will be ignored.', JSON.stringify(external, undefined, 0)
1506 ));
1507 return undefined;
1508 }
1509 > const configElement: Tasks.ITaskSourceConfigElement = { taskConfiguration.ts ×13
1510 > workspaceFolder: context.workspaceFolder,
1511 > file: '.vscode/tasks.json',
1512 > index,
1513 > element: external
1514 > };
1515 > let taskSource: Tasks.FileBasedTaskSource;
1516 > switch (source) {
1517 > case TaskConfigSource.User: {
1518 taskSource = { kind: Tasks.TaskSourceKind.User, config: configElement, label };
1519 break;
1520 }
1521 > case TaskConfigSource.WorkspaceFile: { taskConfiguration.ts ×13
1522 taskSource = { kind: Tasks.TaskSourceKind.WorkspaceFile, config: configElement, label };
1523 break;
1524 }
1525 > default: { taskConfiguration.ts ×13
1526 > taskSource = { kind: Tasks.TaskSourceKind.Workspace, config: configElement, label };
1527 > break;
1528 > }
1529 > }
1530 > const result: Tasks.ConfiguringTask = new Tasks.ConfiguringTask(
1531 > `${typeDeclaration.extensionId}.${taskIdentifier._key}`,
1532 > taskSource,
1533 > undefined,
1534 > type,
1535 > taskIdentifier,
1536 > RunOptions.fromConfiguration(external.runOptions),
1537 > { hide: external.hide, inAgents: external.inAgents }
1538 > );
1539 > const configuration = ConfigurationProperties.from(external as IConfigurationProperties & { [key: string]: unknown }, context, true, source, typeDeclaration.properties);
1540 > result.addTaskLoadMessages(configuration.errors);
1541 > if (configuration.value) {
1542 > result.configurationProperties = Object.assign(result.configurationProperties, configuration.value);
1543 > if (result.configurationProperties.name) {
1544 > result._label = result.configurationProperties.name;
1545 > } else {
1546 let label = result.configures.type;
1547 if (typeDeclaration.required && typeDeclaration.required.length > 0) {
1548 for (const required of typeDeclaration.required) {
1549 const value = result.configures[required];
1550 if (value) {
1551 label = label + ': ' + value;
1552 break;
1553 }
1554 }
1555 }
1556 result._label = label;
1557 }
1558 > if (!result.configurationProperties.identifier) { taskConfiguration.ts ×13
1559 > result.configurationProperties.identifier = taskIdentifier._key;
1560 > }
1561 > }
1562 > return result;
1563 > }
1565 >
1566 > namespace CustomTask {
1567 > export function from(this: void, external: ICustomTask, context: IParseContext, index: number, source: TaskConfigSource): Tasks.CustomTask | undefined {
1568 > if (!external) { taskConfiguration.ts ×10
1569 return undefined;
1570 }
1571 > let type = external.type; taskConfiguration.ts ×10
1572 > if (type === undefined || type === null) {
1573 > type = Tasks.CUSTOMIZED_TASK_TYPE; taskConfiguration.ts ×1
1574 > }
1575 > if (type !== Tasks.CUSTOMIZED_TASK_TYPE && type !== 'shell' && type !== 'process') { taskConfiguration.ts ×10
1576 context.problemReporter.error(nls.localize('ConfigurationParser.notCustom', 'Error: tasks is not declared as a custom task. The configuration will be ignored.\n{0}\n', JSON.stringify(external, null, 4)));
1577 return undefined;
1578 }
1579 > let taskName = external.taskName; taskConfiguration.ts ×10
1580 > if (Types.isString(external.label) && context.schemaVersion === Tasks.JsonSchemaVersion.V2_0_0) {
1581 > taskName = external.label; taskConfiguration.ts ×3
1582 > }
1583 > if (!taskName) { taskConfiguration.ts ×10
1584 > context.problemReporter.error(nls.localize('ConfigurationParser.noTaskName', 'Error: a task must provide a label property. The task will be ignored.\n{0}\n', JSON.stringify(external, null, 4))); taskConfiguration.ts ×1
1585 > return undefined;
1586 > }
1588 > let taskSource: Tasks.FileBasedTaskSource;
1589 > switch (source) {
1590 > case TaskConfigSource.User: {
1591 taskSource = { kind: Tasks.TaskSourceKind.User, config: { index, element: external, file: '.vscode/tasks.json', workspaceFolder: context.workspaceFolder }, label };
1592 break;
1593 }
1594 > case TaskConfigSource.WorkspaceFile: { taskConfiguration.ts ×10
1595 taskSource = { kind: Tasks.TaskSourceKind.WorkspaceFile, config: { index, element: external, file: '.vscode/tasks.json', workspaceFolder: context.workspaceFolder, workspace: context.workspace }, label };
1596 break;
1597 }
1598 > default: { taskConfiguration.ts ×10
1599 > taskSource = { kind: Tasks.TaskSourceKind.Workspace, config: { index, element: external, file: '.vscode/tasks.json', workspaceFolder: context.workspaceFolder }, label }; taskConfiguration.ts ×11
1600 > break;
1601 > }
1604 > const result: Tasks.CustomTask = new Tasks.CustomTask(
1605 > context.uuidMap.getUUID(taskName),
1606 > taskSource,
1607 > taskName,
1608 > Tasks.CUSTOMIZED_TASK_TYPE,
1609 > undefined,
1610 > false,
1611 > RunOptions.fromConfiguration(external.runOptions),
1612 > {
1613 > name: taskName,
1614 > identifier: taskName,
1615 > }
1616 > );
1617 > const configuration = ConfigurationProperties.from(external as IConfigurationProperties & { [key: string]: unknown }, context, false, source);
1618 > result.addTaskLoadMessages(configuration.errors);
1619 > if (configuration.value) {
1620 > result.configurationProperties = Object.assign(result.configurationProperties, configuration.value);
1621 > }
1622 > const supportLegacy: boolean = true; //context.schemaVersion === Tasks.JsonSchemaVersion.V2_0_0;
1623 > if (supportLegacy) {
1624 > const legacy: ILegacyTaskProperties = external as ILegacyTaskProperties;
1625 > if (result.configurationProperties.isBackground === undefined && legacy.isWatching !== undefined) {
1626 > result.configurationProperties.isBackground = !!legacy.isWatching; taskConfiguration.ts ×1
1627 > }
1628 > if (result.configurationProperties.group === undefined) { taskConfiguration.ts ×11
1629 > if (legacy.isBuildCommand === true) {
1630 > result.configurationProperties.group = Tasks.TaskGroup.Build; taskConfiguration.ts ×2
1631 > } else if (legacy.isTestCommand === true) { taskConfiguration.ts ×11
1632 > result.configurationProperties.group = Tasks.TaskGroup.Test; taskConfiguration.ts ×2
1633 > }
1635 > }
1636 > const command: Tasks.ICommandConfiguration = CommandConfiguration.from(external, context)!;
1637 > if (command) {
1638 > result.command = command; taskConfiguration.ts ×1
1639 > }
1640 > if (external.command !== undefined) { taskConfiguration.ts ×11
1641 > // if the task has its own command then we suppress the taskConfiguration.ts ×1
1642 > // task name by default.
1643 > command.suppressTaskName = true;
1644 > }
1645 > return result; taskConfiguration.ts ×11
1648 > export function fillGlobals(task: Tasks.CustomTask, globals: IGlobals): void {
1649 > // We only merge a command from a global definition if there is no dependsOn taskConfiguration.ts ×45
1650 > // or there is a dependsOn and a defined command.
1651 > if (CommandConfiguration.hasCommand(task.command) || task.configurationProperties.dependsOn === undefined) {
1652 > task.command = CommandConfiguration.fillGlobals(task.command, globals.command, task.configurationProperties.name);
1653 > }
1654 > if (task.configurationProperties.problemMatchers === undefined && globals.problemMatcher !== undefined) {
1655 task.configurationProperties.problemMatchers = Objects.deepClone(globals.problemMatcher);
1656 task.hasDefinedMatchers = true;
1657 }
1658 > // promptOnClose is inferred from isBackground if available taskConfiguration.ts ×45
1659 > if (task.configurationProperties.promptOnClose === undefined && task.configurationProperties.isBackground === undefined && globals.promptOnClose !== undefined) {
1660 > task.configurationProperties.promptOnClose = globals.promptOnClose; taskConfiguration.ts ×1
1661 > }
1664 > export function fillDefaults(task: Tasks.CustomTask, context: IParseContext): void {
1665 > CommandConfiguration.fillDefaults(task.command, context); taskConfiguration.ts ×45
1666 > if (task.configurationProperties.promptOnClose === undefined) {
1667 > task.configurationProperties.promptOnClose = task.configurationProperties.isBackground !== undefined ? !task.configurationProperties.isBackground : true; taskConfiguration.ts ×1
1668 > }
1669 > if (task.configurationProperties.isBackground === undefined) { taskConfiguration.ts ×45
1670 > task.configurationProperties.isBackground = false; taskConfiguration.ts ×1
1671 > }
1672 > if (task.configurationProperties.problemMatchers === undefined) { taskConfiguration.ts ×45
1673 > task.configurationProperties.problemMatchers = EMPTY_ARRAY; taskConfiguration.ts ×1
1674 > }
1677 > export function createCustomTask(contributedTask: Tasks.ContributedTask, configuredProps: Tasks.ConfiguringTask | Tasks.CustomTask): Tasks.CustomTask {
1678 const result: Tasks.CustomTask = new Tasks.CustomTask(
1679 configuredProps._id,
1680 Object.assign({}, configuredProps._source, { customizes: contributedTask.defines }),
1681 configuredProps.configurationProperties.name || contributedTask._label,
1682 Tasks.CUSTOMIZED_TASK_TYPE,
1683 contributedTask.command,
1684 false,
1685 contributedTask.runOptions,
1686 {
1687 name: configuredProps.configurationProperties.name || contributedTask.configurationProperties.name,
1688 identifier: configuredProps.configurationProperties.identifier || contributedTask.configurationProperties.identifier,
1689 icon: configuredProps.configurationProperties.icon,
1690 hide: configuredProps.configurationProperties.hide,
1691 inAgents: configuredProps.configurationProperties.inAgents
1692 },
1693
1694 );
1695 result.addTaskLoadMessages(configuredProps.taskLoadMessages);
1696 const resultConfigProps: Tasks.IConfigurationProperties = result.configurationProperties;
1697
1698 assignProperty(resultConfigProps, configuredProps.configurationProperties, 'group');
1699 assignProperty(resultConfigProps, configuredProps.configurationProperties, 'isBackground');
1700 assignProperty(resultConfigProps, configuredProps.configurationProperties, 'dependsOn');
1701 assignProperty(resultConfigProps, configuredProps.configurationProperties, 'problemMatchers');
1702 assignProperty(resultConfigProps, configuredProps.configurationProperties, 'promptOnClose');
1703 assignProperty(resultConfigProps, configuredProps.configurationProperties, 'detail');
1704 result.command.presentation = CommandConfiguration.PresentationOptions.assignProperties(
1705 result.command.presentation!, configuredProps.configurationProperties.presentation)!;
1706 result.command.options = CommandOptions.assignProperties(result.command.options, configuredProps.configurationProperties.options);
1707 result.runOptions = RunOptions.assignProperties(result.runOptions, configuredProps.runOptions);
1708
1709 const contributedConfigProps: Tasks.IConfigurationProperties = contributedTask.configurationProperties;
1710 fillProperty(resultConfigProps, contributedConfigProps, 'group');
1711 fillProperty(resultConfigProps, contributedConfigProps, 'isBackground');
1712 fillProperty(resultConfigProps, contributedConfigProps, 'dependsOn');
1713 fillProperty(resultConfigProps, contributedConfigProps, 'problemMatchers');
1714 fillProperty(resultConfigProps, contributedConfigProps, 'promptOnClose');
1715 fillProperty(resultConfigProps, contributedConfigProps, 'detail');
1716 result.command.presentation = CommandConfiguration.PresentationOptions.fillProperties(
1717 result.command.presentation, contributedConfigProps.presentation)!;
1718 result.command.options = CommandOptions.fillProperties(result.command.options, contributedConfigProps.options);
1719 result.runOptions = RunOptions.fillProperties(result.runOptions, contributedTask.runOptions);
1720
1721 if (contributedTask.hasDefinedMatchers === true) {
1722 result.hasDefinedMatchers = true;
1723 }
1724
1725 return result;
1726 }
1728 >
1729 > export interface ITaskParseResult {
1730 > custom: Tasks.CustomTask[];
1731 > configured: Tasks.ConfiguringTask[];
1732 > }
1733 >
1734 > export namespace TaskParser {
1735 >
1736 > function isCustomTask(value: ICustomTask | IConfiguringTask): value is ICustomTask {
1737 > const type = value.type; taskConfiguration.ts ×9
1738 > const customize = (value as unknown as Record<string, unknown>).customize;
1739 > return customize === undefined && (type === undefined || type === null || type === Tasks.CUSTOMIZED_TASK_TYPE || type === 'shell' || type === 'process');
1740 > }
1742 > const builtinTypeContextMap: IStringDictionary<RawContextKey<boolean>> = {
1743 > shell: ShellExecutionSupportedContext,
1744 > process: ProcessExecutionSupportedContext
1745 > };
1746 >
1747 > export function from(this: void, externals: Array<ICustomTask | IConfiguringTask> | undefined, globals: IGlobals, context: IParseContext, source: TaskConfigSource, registry?: Partial<ITaskDefinitionRegistry>): ITaskParseResult {
1748 > const result: ITaskParseResult = { custom: [], configured: [] }; taskConfiguration.ts ×3
1749 > if (!externals) {
1750 > return result; taskConfiguration.ts ×11
1751 > }
1752 > const defaultBuildTask: { task: Tasks.Task | undefined; rank: number } = { task: undefined, rank: -1 }; taskConfiguration.ts ×9
1753 > const defaultTestTask: { task: Tasks.Task | undefined; rank: number } = { task: undefined, rank: -1 };
1754 > const schema2_0_0: boolean = context.schemaVersion === Tasks.JsonSchemaVersion.V2_0_0;
1755 > const baseLoadIssues = Objects.deepClone(context.taskLoadIssues);
1756 > for (let index = 0; index < externals.length; index++) {
1757 > const external = externals[index];
1758 > const definition = external.type ? registry?.get?.(external.type) || TaskDefinitionRegistry.get(external.type) : undefined;
1759 > let typeNotSupported: boolean = false;
1760 > if (definition && definition.when && !context.contextKeyService.contextMatchesRules(definition.when)) {
1761 typeNotSupported = true;
1762 > } else if (!definition && external.type) { taskConfiguration.ts ×9
1763 > for (const key of Object.keys(builtinTypeContextMap)) { taskConfiguration.ts ×2
1764 > if (external.type === key) {
1765 > typeNotSupported = !ShellExecutionSupportedContext.evaluate(context.contextKeyService.getContext(null));
1766 > break;
1767 > }
1768 > }
1769 > }
1771 > if (typeNotSupported) {
1772 context.problemReporter.info(nls.localize(
1773 'taskConfiguration.providerUnavailable', 'Warning: {0} tasks are unavailable in the current environment.\n',
1774 external.type
1775 ));
1776 continue;
1777 }
1779 > if (isCustomTask(external)) {
1780 > const customTask = CustomTask.from(external, context, index, source); taskConfiguration.ts ×10
1781 > if (customTask) {
1782 > CustomTask.fillGlobals(customTask, globals); taskConfiguration.ts ×11
1783 > CustomTask.fillDefaults(customTask, context);
1784 > if (schema2_0_0) {
1785 > if ((customTask.command === undefined || customTask.command.name === undefined) && (customTask.configurationProperties.dependsOn === undefined || customTask.configurationProperties.dependsOn.length === 0)) { taskConfiguration.ts ×2
1786 context.problemReporter.error(nls.localize(
1787 'taskConfiguration.noCommandOrDependsOn', 'Error: the task \'{0}\' neither specifies a command nor a dependsOn property. The task will be ignored. Its definition is:\n{1}',
1788 customTask.configurationProperties.name, JSON.stringify(external, undefined, 4)
1789 ));
1790 continue;
1791 }
1792 > } else { taskConfiguration.ts ×11
1793 > if (customTask.command === undefined || customTask.command.name === undefined) { taskConfiguration.ts ×2
1794 > context.problemReporter.warn(nls.localize( taskConfiguration.ts ×3
1795 > 'taskConfiguration.noCommand', 'Error: the task \'{0}\' doesn\'t define a command. The task will be ignored. Its definition is:\n{1}',
1796 > customTask.configurationProperties.name, JSON.stringify(external, undefined, 4)
1797 > ));
1798 > continue;
1799 > }
1801 > if (customTask.configurationProperties.group === Tasks.TaskGroup.Build && defaultBuildTask.rank < 2) { taskConfiguration.ts ×11
1802 > defaultBuildTask.task = customTask; taskConfiguration.ts ×2
1803 > defaultBuildTask.rank = 2;
1804 > } else if (customTask.configurationProperties.group === Tasks.TaskGroup.Test && defaultTestTask.rank < 2) { taskConfiguration.ts ×2
1805 > defaultTestTask.task = customTask; taskConfiguration.ts ×2
1806 > defaultTestTask.rank = 2;
1807 > } else if (customTask.configurationProperties.name === 'build' && defaultBuildTask.rank < 1) { taskConfiguration.ts ×1
1808 > defaultBuildTask.task = customTask; taskConfiguration.ts ×2
1809 > defaultBuildTask.rank = 1;
1810 > } else if (customTask.configurationProperties.name === 'test' && defaultTestTask.rank < 1) { taskConfiguration.ts ×1
1811 > defaultTestTask.task = customTask; taskConfiguration.ts ×2
1812 > defaultTestTask.rank = 1;
1813 > }
1814 > customTask.addTaskLoadMessages(context.taskLoadIssues); taskConfiguration.ts ×2
1815 > result.custom.push(customTask);
1816 > }
1817 > } else { taskConfiguration.ts ×9
1818 > const configuredTask = ConfiguringTask.from(external, context, index, source, registry); taskConfiguration.ts ×13
1819 > if (configuredTask) {
1820 > configuredTask.addTaskLoadMessages(context.taskLoadIssues);
1821 > result.configured.push(configuredTask);
1822 > }
1823 > }
1824 > context.taskLoadIssues = Objects.deepClone(baseLoadIssues); taskConfiguration.ts ×1
1825 > }
1826 > // There is some special logic for tasks with the labels "build" and "test". taskConfiguration.ts ×9
1827 > // Even if they are not marked as a task group Build or Test, we automagically group them as such.
1828 > // However, if they are already grouped as Build or Test, we don't need to add this grouping.
1829 > const defaultBuildGroupName = Types.isString(defaultBuildTask.task?.configurationProperties.group) ? defaultBuildTask.task?.configurationProperties.group : defaultBuildTask.task?.configurationProperties.group?._id; taskConfiguration.ts ×3
1830 > const defaultTestTaskGroupName = Types.isString(defaultTestTask.task?.configurationProperties.group) ? defaultTestTask.task?.configurationProperties.group : defaultTestTask.task?.configurationProperties.group?._id;
1831 > if ((defaultBuildGroupName !== Tasks.TaskGroup.Build._id) && (defaultBuildTask.rank > -1) && (defaultBuildTask.rank < 2) && defaultBuildTask.task) {
1832 > defaultBuildTask.task.configurationProperties.group = Tasks.TaskGroup.Build; taskConfiguration.ts ×2
1833 > } else if ((defaultTestTaskGroupName !== Tasks.TaskGroup.Test._id) && (defaultTestTask.rank > -1) && (defaultTestTask.rank < 2) && defaultTestTask.task) { taskConfiguration.ts ×9
1834 > defaultTestTask.task.configurationProperties.group = Tasks.TaskGroup.Test; taskConfiguration.ts ×2
1835 > }
1837 > return result;
1840 > export function assignTasks(target: Tasks.CustomTask[], source: Tasks.CustomTask[]): Tasks.CustomTask[] {
1841 > if (source === undefined || source.length === 0) { taskConfiguration.ts ×11
1842 > return target;
1843 > }
1844 > if (target === undefined || target.length === 0) {
1845 return source;
1846 }
1847
1848 if (source) {
1849 // Tasks are keyed by ID but we need to merge by name
1850 const map: IStringDictionary<Tasks.CustomTask> = Object.create(null);
1851 target.forEach((task) => {
1852 map[task.configurationProperties.name!] = task;
1853 });
1854
1855 source.forEach((task) => {
1856 map[task.configurationProperties.name!] = task;
1857 });
1858 const newTarget: Tasks.CustomTask[] = [];
1859 target.forEach(task => {
1860 newTarget.push(map[task.configurationProperties.name!]);
1861 delete map[task.configurationProperties.name!];
1862 });
1863 Object.keys(map).forEach(key => newTarget.push(map[key]));
1864 target = newTarget;
1865 }
1866 return target;
1869 >
1870 > export interface IGlobals {
1871 > command?: Tasks.ICommandConfiguration;
1872 > problemMatcher?: ProblemMatcher[];
1873 > promptOnClose?: boolean;
1874 > suppressTaskName?: boolean;
1875 > }
1876 >
1877 > namespace Globals {
1878 >
1879 > export function from(config: IExternalTaskRunnerConfiguration, context: IParseContext): IGlobals {
1880 > let result = fromBase(config, context); taskConfiguration.ts ×41
1881 > let osGlobals: IGlobals | undefined = undefined;
1882 > if (config.windows && context.platform === Platform.Windows) {
1883 osGlobals = fromBase(config.windows, context);
1884 > } else if (config.osx && context.platform === Platform.Mac) { taskConfiguration.ts ×41
1885 osGlobals = fromBase(config.osx, context);
1886 > } else if (config.linux && context.platform === Platform.Linux) { taskConfiguration.ts ×41
1887 > osGlobals = fromBase(config.linux, context); taskConfiguration.ts ×11
1888 > }
1889 > if (osGlobals) { taskConfiguration.ts ×41
1890 > result = Globals.assignProperties(result, osGlobals); taskConfiguration.ts ×11
1891 > }
1892 > const command = CommandConfiguration.from(config, context); taskConfiguration.ts ×41
1893 > if (command) {
1894 > result.command = command; taskConfiguration.ts ×16
1895 > }
1896 > Globals.fillDefaults(result, context); taskConfiguration.ts ×41
1897 > Globals.freeze(result);
1898 > return result;
1899 > }
1901 > export function fromBase(this: void, config: IBaseTaskRunnerConfiguration, context: IParseContext): IGlobals {
1902 > const result: IGlobals = {}; taskConfiguration.ts ×41
1903 > if (config.suppressTaskName !== undefined) {
1904 > result.suppressTaskName = !!config.suppressTaskName; taskConfiguration.ts ×2
1905 > }
1906 > if (config.promptOnClose !== undefined) { taskConfiguration.ts ×41
1907 > result.promptOnClose = !!config.promptOnClose; taskConfiguration.ts ×1
1908 > }
1909 > if (config.problemMatcher) { taskConfiguration.ts ×41
1910 > result.problemMatcher = ProblemMatcherConverter.from(config.problemMatcher, context).value; taskConfiguration.ts ×2
1911 > }
1912 > return result; taskConfiguration.ts ×41
1913 > }
1915 > export function isEmpty(value: IGlobals): boolean {
1916 > return !value || value.command === undefined && value.promptOnClose === undefined && value.suppressTaskName === undefined; taskConfiguration.ts ×11
1917 > }
1919 > export function assignProperties(target: IGlobals, source: IGlobals): IGlobals {
1920 > if (isEmpty(source)) { taskConfiguration.ts ×11
1921 > return target;
1922 > }
1923 if (isEmpty(target)) {
1924 return source;
1925 }
1926 assignProperty(target, source, 'promptOnClose');
1927 assignProperty(target, source, 'suppressTaskName');
1928 return target;
1931 > export function fillDefaults(value: IGlobals, context: IParseContext): void {
1932 > if (!value) { taskConfiguration.ts ×41
1933 return;
1934 }
1935 > CommandConfiguration.fillDefaults(value.command, context); taskConfiguration.ts ×41
1936 > if (value.suppressTaskName === undefined) {
1937 > value.suppressTaskName = (context.schemaVersion === Tasks.JsonSchemaVersion.V2_0_0); taskConfiguration.ts ×1
1938 > }
1939 > if (value.promptOnClose === undefined) { taskConfiguration.ts ×41
1940 > value.promptOnClose = true; taskConfiguration.ts ×1
1941 > }
1944 > export function freeze(value: IGlobals): void {
1945 > Object.freeze(value); taskConfiguration.ts ×41
1946 > if (value.command) {
1947 > CommandConfiguration.freeze(value.command); taskConfiguration.ts ×16
1948 > }
1951 >
1952 > export namespace ExecutionEngine {
1953 >
1954 > export function from(config: IExternalTaskRunnerConfiguration): Tasks.ExecutionEngine {
1955 > const runner = config.runner || config._runner; taskConfiguration.ts ×41
1956 > let result: Tasks.ExecutionEngine | undefined;
1957 > if (runner) {
1958 switch (runner) {
1959 case 'terminal':
1960 result = Tasks.ExecutionEngine.Terminal;
1961 break;
1962 case 'process':
1963 result = Tasks.ExecutionEngine.Process;
1964 break;
1965 }
1966 }
1967 > const schemaVersion = JsonSchemaVersion.from(config); taskConfiguration.ts ×41
1968 > if (schemaVersion === Tasks.JsonSchemaVersion.V0_1_0) {
1969 > return result || Tasks.ExecutionEngine.Process; taskConfiguration.ts ×2
1970 > } else if (schemaVersion === Tasks.JsonSchemaVersion.V2_0_0) { taskConfiguration.ts ×41
1971 > return Tasks.ExecutionEngine.Terminal; tasks.ts ×4
1972 > } else {
1973 throw new Error('Shouldn\'t happen.');
1974 }
1977 >
1978 > export namespace JsonSchemaVersion {
1979 >
1980 > const _default: Tasks.JsonSchemaVersion = Tasks.JsonSchemaVersion.V2_0_0;
1981 >
1982 > export function from(config: IExternalTaskRunnerConfiguration): Tasks.JsonSchemaVersion {
1983 > const version = config.version; taskConfiguration.ts ×41
1984 > if (!version) {
1985 return _default;
1986 }
1987 > switch (version) { taskConfiguration.ts ×41
1988 > case '0.1.0':
1989 > return Tasks.JsonSchemaVersion.V0_1_0; taskConfiguration.ts ×2
1990 > case '2.0.0': taskConfiguration.ts ×41
1991 > return Tasks.JsonSchemaVersion.V2_0_0; tasks.ts ×4
1992 > default: taskConfiguration.ts ×41
1993 return _default;
1995 > }
1997 >
1998 > export interface IParseResult {
1999 > validationStatus: ValidationStatus;
2000 > custom: Tasks.CustomTask[];
2001 > configured: Tasks.ConfiguringTask[];
2002 > engine: Tasks.ExecutionEngine;
2003 > }
2004 >
2005 > export interface IProblemReporter extends IProblemReporterBase {
2006 > }
2007 >
2008 > export class UUIDMap {
2009 >
2010 > private last: IStringDictionary<Types.SingleOrMany<string>> | undefined;
2011 > private current: IStringDictionary<Types.SingleOrMany<string>>;
2012 >
2013 > constructor(other?: UUIDMap) {
2014 > this.current = Object.create(null);
2015 > if (other) {
2016 for (const key of Object.keys(other.current)) {
2017 const value = other.current[key];
2018 if (Array.isArray(value)) {
2019 this.current[key] = value.slice();
2020 } else {
2021 this.current[key] = value;
2022 }
2023 }
2024 }
2026 >
2027 > public start(): void {
2028 > this.last = this.current; taskConfiguration.ts ×41
2029 > this.current = Object.create(null);
2030 > }
2032 > public getUUID(identifier: string): string {
2033 > const lastValue = this.last ? this.last[identifier] : undefined; taskConfiguration.ts ×45
2034 > let result: string | undefined = undefined;
2035 > if (lastValue !== undefined) {
2036 if (Array.isArray(lastValue)) {
2037 result = lastValue.shift();
2038 if (lastValue.length === 0) {
2039 delete this.last![identifier];
2040 }
2041 } else {
2042 result = lastValue;
2043 delete this.last![identifier];
2044 }
2045 }
2046 > if (result === undefined) { taskConfiguration.ts ×45
2047 > result = UUID.generateUuid();
2048 > }
2049 > const currentValue = this.current[identifier];
2050 > if (currentValue === undefined) {
2051 > this.current[identifier] = result;
2052 > } else {
2053 if (Array.isArray(currentValue)) {
2054 currentValue.push(result);
2055 } else {
2056 const arrayValue: string[] = [currentValue];
2057 arrayValue.push(result);
2058 this.current[identifier] = arrayValue;
2059 }
2060 }
2061 > return result; taskConfiguration.ts ×45
2062 > }
2064 > public finish(): void {
2065 > this.last = undefined; taskConfiguration.ts ×41
2066 > }
2068 >
2069 > export enum TaskConfigSource {
2070 > TasksJson,
2071 > WorkspaceFile,
2072 > User
2073 > }
2074 >
2075 > class ConfigurationParser {
2076 >
2077 > private workspaceFolder: IWorkspaceFolder;
2078 > private workspace: IWorkspace | undefined;
2079 > private problemReporter: IProblemReporter;
2080 > private uuidMap: UUIDMap;
2081 > private platform: Platform;
2082 >
2083 > constructor(workspaceFolder: IWorkspaceFolder, workspace: IWorkspace | undefined, platform: Platform, problemReporter: IProblemReporter, uuidMap: UUIDMap) {
2084 > this.workspaceFolder = workspaceFolder; taskConfiguration.ts ×41
2085 > this.workspace = workspace;
2086 > this.platform = platform;
2087 > this.problemReporter = problemReporter;
2088 > this.uuidMap = uuidMap;
2089 > }
2091 > public run(fileConfig: IExternalTaskRunnerConfiguration, source: TaskConfigSource, contextKeyService: IContextKeyService): IParseResult {
2092 > const engine = ExecutionEngine.from(fileConfig); taskConfiguration.ts ×41
2093 > const schemaVersion = JsonSchemaVersion.from(fileConfig);
2094 > const context: IParseContext = {
2095 > workspaceFolder: this.workspaceFolder,
2096 > workspace: this.workspace,
2097 > problemReporter: this.problemReporter,
2098 > uuidMap: this.uuidMap,
2099 > namedProblemMatchers: {},
2100 > engine,
2101 > schemaVersion,
2102 > platform: this.platform,
2103 > taskLoadIssues: [],
2104 > contextKeyService
2105 > };
2106 > const taskParseResult = this.createTaskRunnerConfiguration(fileConfig, context, source);
2107 > return {
2108 > validationStatus: this.problemReporter.status,
2109 > custom: taskParseResult.custom,
2110 > configured: taskParseResult.configured,
2111 > engine
2112 > };
2113 > }
2115 > private createTaskRunnerConfiguration(fileConfig: IExternalTaskRunnerConfiguration, context: IParseContext, source: TaskConfigSource): ITaskParseResult {
2116 > const globals = Globals.from(fileConfig, context); taskConfiguration.ts ×41
2117 > if (this.problemReporter.status.isFatal()) {
2118 return { custom: [], configured: [] };
2119 }
2120 > context.namedProblemMatchers = ProblemMatcherConverter.namedFrom(fileConfig.declares, context); taskConfiguration.ts ×41
2121 > let globalTasks: Tasks.CustomTask[] | undefined = undefined;
2122 > let externalGlobalTasks: Array<IConfiguringTask | ICustomTask> | undefined = undefined;
2123 > if (fileConfig.windows && context.platform === Platform.Windows) {
2124 globalTasks = TaskParser.from(fileConfig.windows.tasks, globals, context, source).custom;
2125 externalGlobalTasks = fileConfig.windows.tasks;
2126 > } else if (fileConfig.osx && context.platform === Platform.Mac) { taskConfiguration.ts ×41
2127 globalTasks = TaskParser.from(fileConfig.osx.tasks, globals, context, source).custom;
2128 externalGlobalTasks = fileConfig.osx.tasks;
2129 > } else if (fileConfig.linux && context.platform === Platform.Linux) { taskConfiguration.ts ×41
2130 > globalTasks = TaskParser.from(fileConfig.linux.tasks, globals, context, source).custom; taskConfiguration.ts ×11
2131 > externalGlobalTasks = fileConfig.linux.tasks;
2132 > }
2133 > if (context.schemaVersion === Tasks.JsonSchemaVersion.V2_0_0 && globalTasks && globalTasks.length > 0 && externalGlobalTasks && externalGlobalTasks.length > 0) { taskConfiguration.ts ×41
2134 const taskContent: string[] = [];
2135 for (const task of externalGlobalTasks) {
2136 taskContent.push(JSON.stringify(task, null, 4));
2137 }
2138 context.problemReporter.error(
2139 nls.localize(
2140 { key: 'TaskParse.noOsSpecificGlobalTasks', comment: ['\"Task version 2.0.0\" refers to the 2.0.0 version of the task system. The \"version 2.0.0\" is not localizable as it is a json key and value.'] },
2141 'Task version 2.0.0 doesn\'t support global OS specific tasks. Convert them to a task with a OS specific command. Affected tasks are:\n{0}', taskContent.join('\n'))
2142 );
2143 }
2145 > let result: ITaskParseResult = { custom: [], configured: [] };
2146 > if (fileConfig.tasks) {
2147 > result = TaskParser.from(fileConfig.tasks, globals, context, source); taskConfiguration.ts ×1
2148 > }
2149 > if (globalTasks) { taskConfiguration.ts ×41
2150 > result.custom = TaskParser.assignTasks(result.custom, globalTasks); taskConfiguration.ts ×11
2151 > }
2153 > if ((!result.custom || result.custom.length === 0) && (globals.command && globals.command.name)) {
2154 > const matchers: ProblemMatcher[] = ProblemMatcherConverter.from(fileConfig.problemMatcher, context).value ?? []; taskConfiguration.ts ×3
2155 > const isBackground = fileConfig.isBackground ? !!fileConfig.isBackground : fileConfig.isWatching ? !!fileConfig.isWatching : undefined;
2156 > const name = Tasks.CommandString.value(globals.command.name);
2157 > const task: Tasks.CustomTask = new Tasks.CustomTask(
2158 > context.uuidMap.getUUID(name),
2159 > Object.assign({}, source, 'workspace', { config: { index: -1, element: fileConfig, workspaceFolder: context.workspaceFolder } }) satisfies Tasks.IWorkspaceTaskSource,
2160 > name,
2161 > Tasks.CUSTOMIZED_TASK_TYPE,
2162 > {
2163 > name: undefined,
2164 > runtime: undefined,
2165 > presentation: undefined,
2166 > suppressTaskName: true
2167 > },
2168 > false,
2169 > { reevaluateOnRerun: true },
2170 > {
2171 > name: name,
2172 > identifier: name,
2173 > group: Tasks.TaskGroup.Build,
2174 > isBackground: isBackground,
2175 > problemMatchers: matchers
2176 > }
2177 > );
2178 > const taskGroupKind = GroupKind.from(fileConfig.group);
2179 > if (taskGroupKind !== undefined) {
2180 task.configurationProperties.group = taskGroupKind;
2181 > } else if (fileConfig.group === 'none') { taskConfiguration.ts ×3
2182 > task.configurationProperties.group = undefined; taskConfiguration.ts ×1
2183 > }
2184 > CustomTask.fillGlobals(task, globals); taskConfiguration.ts ×3
2185 > CustomTask.fillDefaults(task, context);
2186 > result.custom = [task];
2187 > }
2188 > result.custom = result.custom || []; taskConfiguration.ts ×41
2189 > result.configured = result.configured || [];
2190 > return result;
2191 > }
2193 >
2194 > const uuidMaps: Map<TaskConfigSource, Map<string, UUIDMap>> = new Map();
2195 > const recentUuidMaps: Map<TaskConfigSource, Map<string, UUIDMap>> = new Map();
2196 > export function parse(workspaceFolder: IWorkspaceFolder, workspace: IWorkspace | undefined, platform: Platform, configuration: IExternalTaskRunnerConfiguration, logger: IProblemReporter, source: TaskConfigSource, contextKeyService: IContextKeyService, isRecents: boolean = false): IParseResult {
2197 > const recentOrOtherMaps = isRecents ? recentUuidMaps : uuidMaps; taskConfiguration.ts ×41
2198 > let selectedUuidMaps = recentOrOtherMaps.get(source);
2199 > if (!selectedUuidMaps) {
2200 > recentOrOtherMaps.set(source, new Map());
2201 > selectedUuidMaps = recentOrOtherMaps.get(source)!;
2202 > }
2203 > let uuidMap = selectedUuidMaps.get(workspaceFolder.uri.toString());
2204 > if (!uuidMap) {
2205 > uuidMap = new UUIDMap();
2206 > selectedUuidMaps.set(workspaceFolder.uri.toString(), uuidMap);
2207 > }
2208 > try {
2209 > uuidMap.start();
2210 > return (new ConfigurationParser(workspaceFolder, workspace, platform, logger, uuidMap)).run(configuration, source, contextKeyService);
2211 > } finally {
2212 > uuidMap.finish();
2213 > }
2214 > }
2216 >
2217 >
2218 > export function createCustomTask(contributedTask: Tasks.ContributedTask, configuredProps: Tasks.ConfiguringTask | Tasks.CustomTask): Tasks.CustomTask {
2219 return CustomTask.createCustomTask(contributedTask, configuredProps);
2220 }