@opensumi/ide-task 2.21.13 → 2.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/lib/browser/index.js +2 -2
  2. package/lib/browser/index.js.map +1 -1
  3. package/lib/browser/parser.js +4 -4
  4. package/lib/browser/parser.js.map +1 -1
  5. package/lib/browser/task-config.d.ts +4 -4
  6. package/lib/browser/task-config.d.ts.map +1 -1
  7. package/lib/browser/task-config.js +31 -31
  8. package/lib/browser/task-config.js.map +1 -1
  9. package/lib/browser/task-executor.d.ts.map +1 -1
  10. package/lib/browser/task-executor.js +16 -22
  11. package/lib/browser/task-executor.js.map +1 -1
  12. package/lib/browser/task-preferences.contribution.js.map +1 -1
  13. package/lib/browser/task-preferences.provider.d.ts +2 -2
  14. package/lib/browser/task-preferences.provider.d.ts.map +1 -1
  15. package/lib/browser/task-preferences.provider.js +2 -2
  16. package/lib/browser/task-preferences.provider.js.map +1 -1
  17. package/lib/browser/task.contribution.js.map +1 -1
  18. package/lib/browser/task.schema.d.ts +2 -2
  19. package/lib/browser/task.schema.d.ts.map +1 -1
  20. package/lib/browser/task.schema.js +5 -1
  21. package/lib/browser/task.schema.js.map +1 -1
  22. package/lib/browser/task.service.d.ts +3 -1
  23. package/lib/browser/task.service.d.ts.map +1 -1
  24. package/lib/browser/task.service.js +10 -5
  25. package/lib/browser/task.service.js.map +1 -1
  26. package/lib/browser/terminal-task-system.js +11 -11
  27. package/lib/browser/terminal-task-system.js.map +1 -1
  28. package/lib/common/index.d.ts +1 -1
  29. package/lib/common/index.d.ts.map +1 -1
  30. package/lib/common/task.d.ts +4 -4
  31. package/lib/common/task.d.ts.map +1 -1
  32. package/lib/common/task.js +7 -7
  33. package/lib/common/task.js.map +1 -1
  34. package/package.json +15 -14
  35. package/src/browser/index.ts +33 -0
  36. package/src/browser/parser.ts +944 -0
  37. package/src/browser/problem-collector.ts +71 -0
  38. package/src/browser/problem-line-matcher.ts +461 -0
  39. package/src/browser/task-config.ts +2302 -0
  40. package/src/browser/task-executor.ts +296 -0
  41. package/src/browser/task-preferences.contribution.ts +9 -0
  42. package/src/browser/task-preferences.provider.ts +23 -0
  43. package/src/browser/task-preferences.ts +14 -0
  44. package/src/browser/task.contribution.ts +70 -0
  45. package/src/browser/task.schema.ts +368 -0
  46. package/src/browser/task.service.ts +504 -0
  47. package/src/browser/terminal-task-system.ts +340 -0
  48. package/src/common/index.ts +165 -0
  49. package/src/common/task.ts +1174 -0
  50. package/src/index.ts +1 -0
@@ -0,0 +1,1174 @@
1
+ /* ---------------------------------------------------------------------------------------------
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 { RawContextKey } from '@opensumi/ide-core-browser/lib/raw-context-key';
7
+ import { IJSONSchemaMap, isString, path, URI, ProblemMatcher, ProblemMatch } from '@opensumi/ide-core-common';
8
+ import { UriComponents } from '@opensumi/ide-editor';
9
+
10
+ import { IWorkspaceFolder } from './index';
11
+
12
+ const { basename } = path;
13
+
14
+ interface JSONType {
15
+ [key: string]: any;
16
+ }
17
+
18
+ export interface WorkspaceFolder {
19
+ uri: UriComponents;
20
+ name: string;
21
+ index: number;
22
+ }
23
+
24
+ export const TASK_RUNNING_STATE = new RawContextKey<boolean>('taskRunning', false);
25
+
26
+ export interface TaskExecution {
27
+ id: string;
28
+ task: Task;
29
+ }
30
+
31
+ export interface IExtensionProps {
32
+ readonly id: string;
33
+ // 插件市场 id
34
+ readonly extensionId: string;
35
+ readonly name: string;
36
+ readonly activated: boolean;
37
+ readonly enabled: boolean;
38
+ readonly packageJSON: JSONType;
39
+ readonly deafaultPkgNlsJSON: JSONType | undefined;
40
+ readonly packageNlsJSON: JSONType | undefined;
41
+ readonly path: string;
42
+ readonly realPath: string;
43
+ readonly extraMetadata: JSONType;
44
+ readonly extendConfig: JSONType;
45
+ readonly enableProposedApi: boolean;
46
+ readonly isUseEnable: boolean;
47
+ workerVarId?: string;
48
+ workerScriptPath?: string;
49
+ readonly isBuiltin: boolean;
50
+ }
51
+
52
+ export enum ShellQuoting {
53
+ /**
54
+ * Use character escaping.
55
+ */
56
+ Escape = 1,
57
+
58
+ /**
59
+ * Use strong quoting
60
+ */
61
+ Strong = 2,
62
+
63
+ /**
64
+ * Use weak quoting.
65
+ */
66
+ Weak = 3,
67
+ }
68
+
69
+ export const CUSTOMIZED_TASK_TYPE = '$customized';
70
+
71
+ export namespace ShellQuoting {
72
+ export function from(this: void, value: string): ShellQuoting {
73
+ if (!value) {
74
+ return ShellQuoting.Strong;
75
+ }
76
+ switch (value.toLowerCase()) {
77
+ case 'escape':
78
+ return ShellQuoting.Escape;
79
+ case 'strong':
80
+ return ShellQuoting.Strong;
81
+ case 'weak':
82
+ return ShellQuoting.Weak;
83
+ default:
84
+ return ShellQuoting.Strong;
85
+ }
86
+ }
87
+ }
88
+
89
+ export interface ShellQuotingOptions {
90
+ /**
91
+ * The character used to do character escaping.
92
+ */
93
+ escape?:
94
+ | string
95
+ | {
96
+ escapeChar: string;
97
+ charsToEscape: string;
98
+ };
99
+
100
+ /**
101
+ * The character used for string quoting.
102
+ */
103
+ strong?: string;
104
+
105
+ /**
106
+ * The character used for weak quoting.
107
+ */
108
+ weak?: string;
109
+ }
110
+
111
+ export interface ShellConfiguration {
112
+ /**
113
+ * The shell executable.
114
+ */
115
+ executable?: string;
116
+
117
+ /**
118
+ * The arguments to be passed to the shell executable.
119
+ */
120
+ args?: string[];
121
+
122
+ /**
123
+ * Which kind of quotes the shell supports.
124
+ */
125
+ quoting?: ShellQuotingOptions;
126
+ }
127
+
128
+ export interface CommandOptions {
129
+ /**
130
+ * The shell to use if the task is a shell command.
131
+ */
132
+ shell?: ShellConfiguration;
133
+
134
+ /**
135
+ * The current working directory of the executed program or shell.
136
+ * If omitted VSCode's current workspace root is used.
137
+ */
138
+ cwd?: string;
139
+
140
+ /**
141
+ * The environment of the executed program or shell. If omitted
142
+ * the parent process' environment is used.
143
+ */
144
+ env?: { [key: string]: string };
145
+ }
146
+
147
+ export namespace CommandOptions {
148
+ export const defaults: CommandOptions = { cwd: '${workspaceFolder}' };
149
+ }
150
+
151
+ export enum RevealKind {
152
+ /**
153
+ * Always brings the terminal to front if the task is executed.
154
+ */
155
+ Always = 1,
156
+
157
+ /**
158
+ * Only brings the terminal to front if a problem is detected executing the task
159
+ * e.g. the task couldn't be started,
160
+ * the task ended with an exit code other than zero,
161
+ * or the problem matcher found an error.
162
+ */
163
+ Silent = 2,
164
+
165
+ /**
166
+ * The terminal never comes to front when the task is executed.
167
+ */
168
+ Never = 3,
169
+ }
170
+
171
+ export namespace RevealKind {
172
+ export function fromString(this: void, value: string): RevealKind {
173
+ switch (value.toLowerCase()) {
174
+ case 'always':
175
+ return RevealKind.Always;
176
+ case 'silent':
177
+ return RevealKind.Silent;
178
+ case 'never':
179
+ return RevealKind.Never;
180
+ default:
181
+ return RevealKind.Always;
182
+ }
183
+ }
184
+ }
185
+
186
+ export enum RevealProblemKind {
187
+ /**
188
+ * Never reveals the problems panel when this task is executed.
189
+ */
190
+ Never = 1,
191
+
192
+ /**
193
+ * Only reveals the problems panel if a problem is found.
194
+ */
195
+ OnProblem = 2,
196
+
197
+ /**
198
+ * Never reveals the problems panel when this task is executed.
199
+ */
200
+ Always = 3,
201
+ }
202
+
203
+ export namespace RevealProblemKind {
204
+ export function fromString(this: void, value: string): RevealProblemKind {
205
+ switch (value.toLowerCase()) {
206
+ case 'always':
207
+ return RevealProblemKind.Always;
208
+ case 'never':
209
+ return RevealProblemKind.Never;
210
+ case 'onproblem':
211
+ return RevealProblemKind.OnProblem;
212
+ default:
213
+ return RevealProblemKind.OnProblem;
214
+ }
215
+ }
216
+ }
217
+
218
+ export enum PanelKind {
219
+ /**
220
+ * Shares a panel with other tasks. This is the default.
221
+ */
222
+ Shared = 1,
223
+
224
+ /**
225
+ * Uses a dedicated panel for this tasks. The panel is not
226
+ * shared with other tasks.
227
+ */
228
+ Dedicated = 2,
229
+
230
+ /**
231
+ * Creates a new panel whenever this task is executed.
232
+ */
233
+ New = 3,
234
+ }
235
+
236
+ export namespace PanelKind {
237
+ export function fromString(value: string): PanelKind {
238
+ switch (value.toLowerCase()) {
239
+ case 'shared':
240
+ return PanelKind.Shared;
241
+ case 'dedicated':
242
+ return PanelKind.Dedicated;
243
+ case 'new':
244
+ return PanelKind.New;
245
+ default:
246
+ return PanelKind.Shared;
247
+ }
248
+ }
249
+ }
250
+
251
+ export interface PresentationOptions {
252
+ /**
253
+ * Controls whether the task output is reveal in the user interface.
254
+ * Defaults to `RevealKind.Always`.
255
+ */
256
+ reveal: RevealKind;
257
+
258
+ /**
259
+ * Controls whether the problems pane is revealed when running this task or not.
260
+ * Defaults to `RevealProblemKind.Never`.
261
+ */
262
+ revealProblems: RevealProblemKind;
263
+
264
+ /**
265
+ * Controls whether the command associated with the task is echoed
266
+ * in the user interface.
267
+ */
268
+ echo: boolean;
269
+
270
+ /**
271
+ * Controls whether the panel showing the task output is taking focus.
272
+ */
273
+ focus: boolean;
274
+
275
+ /**
276
+ * Controls if the task panel is used for this task only (dedicated),
277
+ * shared between tasks (shared) or if a new panel is created on
278
+ * every task execution (new). Defaults to `TaskInstanceKind.Shared`
279
+ */
280
+ panel: PanelKind;
281
+
282
+ /**
283
+ * Controls whether to show the "Terminal will be reused by tasks, press any key to close it" message.
284
+ */
285
+ showReuseMessage: boolean;
286
+
287
+ /**
288
+ * Controls whether to clear the terminal before executing the task.
289
+ */
290
+ clear: boolean;
291
+
292
+ /**
293
+ * Controls whether the task is executed in a specific terminal group using split panes.
294
+ */
295
+ group?: string;
296
+ }
297
+
298
+ export namespace PresentationOptions {
299
+ export const defaults: PresentationOptions = {
300
+ echo: true,
301
+ reveal: RevealKind.Always,
302
+ revealProblems: RevealProblemKind.Never,
303
+ focus: false,
304
+ panel: PanelKind.Shared,
305
+ showReuseMessage: true,
306
+ clear: false,
307
+ };
308
+ }
309
+
310
+ export enum RuntimeType {
311
+ Shell = 1,
312
+ Process = 2,
313
+ CustomExecution = 3,
314
+ CustomExecution2 = 4,
315
+ }
316
+
317
+ export namespace RuntimeType {
318
+ export function fromString(value: string): RuntimeType {
319
+ switch (value.toLowerCase()) {
320
+ case 'shell':
321
+ return RuntimeType.Shell;
322
+ case 'process':
323
+ return RuntimeType.Process;
324
+ case 'customExecution':
325
+ return RuntimeType.CustomExecution;
326
+ default:
327
+ return RuntimeType.Process;
328
+ }
329
+ }
330
+ }
331
+
332
+ export interface QuotedString {
333
+ value: string;
334
+ quoting: ShellQuoting;
335
+ }
336
+
337
+ export type CommandString = string | QuotedString;
338
+
339
+ export namespace CommandString {
340
+ export function value(value: CommandString): string {
341
+ if (isString(value)) {
342
+ return value;
343
+ } else {
344
+ return value.value;
345
+ }
346
+ }
347
+ }
348
+
349
+ export interface CommandConfiguration {
350
+ /**
351
+ * The task type
352
+ */
353
+ runtime?: RuntimeType;
354
+
355
+ /**
356
+ * The command to execute
357
+ */
358
+ name?: CommandString;
359
+
360
+ /**
361
+ * Additional command options.
362
+ */
363
+ options?: CommandOptions;
364
+
365
+ /**
366
+ * Command arguments.
367
+ */
368
+ args?: CommandString[];
369
+
370
+ /**
371
+ * The task selector if needed.
372
+ */
373
+ taskSelector?: string;
374
+
375
+ /**
376
+ * Whether to suppress the task name when merging global args
377
+ *
378
+ */
379
+ suppressTaskName?: boolean;
380
+
381
+ /**
382
+ * Describes how the task is presented in the UI.
383
+ */
384
+ presentation?: PresentationOptions;
385
+ }
386
+
387
+ export namespace TaskGroup {
388
+ export const Clean: TaskGroup = { _id: 'clean', isDefault: false };
389
+
390
+ export const Build: TaskGroup = { _id: 'build', isDefault: false };
391
+
392
+ export const Rebuild: TaskGroup = { _id: 'rebuild', isDefault: false };
393
+
394
+ export const Test: TaskGroup = { _id: 'test', isDefault: false };
395
+
396
+ export function is(value: any): value is string {
397
+ return value === Clean._id || value === Build._id || value === Rebuild._id || value === Test._id;
398
+ }
399
+
400
+ export function from(value: string | TaskGroup | undefined): TaskGroup | undefined {
401
+ if (value === undefined) {
402
+ return undefined;
403
+ } else if (isString(value)) {
404
+ if (is(value)) {
405
+ return { _id: value, isDefault: false };
406
+ }
407
+ return undefined;
408
+ } else {
409
+ return value;
410
+ }
411
+ }
412
+ }
413
+
414
+ export interface TaskGroup {
415
+ _id: string;
416
+ isDefault?: boolean;
417
+ }
418
+
419
+ export const enum TaskScope {
420
+ Global = 1,
421
+ Workspace = 2,
422
+ Folder = 3,
423
+ }
424
+
425
+ export namespace TaskSourceKind {
426
+ export const Workspace = 'workspace' as const;
427
+ export const Extension = 'extension' as const;
428
+ export const InMemory = 'inMemory' as const;
429
+ export const WorkspaceFile = 'workspaceFile' as const;
430
+ export const User = 'user' as const;
431
+ }
432
+
433
+ interface IWorkspace {
434
+ /**
435
+ * the unique identifier of the workspace.
436
+ */
437
+ readonly id: string;
438
+
439
+ /**
440
+ * Folders in the workspace.
441
+ */
442
+ readonly folders: WorkspaceFolder[];
443
+
444
+ /**
445
+ * the location of the workspace configuration
446
+ */
447
+ readonly configuration?: URI | null;
448
+ }
449
+
450
+ export interface TaskSourceConfigElement {
451
+ workspaceFolder?: WorkspaceFolder;
452
+ workspace?: IWorkspace;
453
+ file: string;
454
+ index: number;
455
+ element: any;
456
+ }
457
+
458
+ interface BaseTaskSource {
459
+ readonly kind: string;
460
+ readonly label: string;
461
+ }
462
+
463
+ export interface WorkspaceTaskSource extends BaseTaskSource {
464
+ readonly kind: 'workspace';
465
+ readonly config: TaskSourceConfigElement;
466
+ readonly customizes?: KeyedTaskIdentifier;
467
+ }
468
+
469
+ export interface ExtensionTaskSource extends BaseTaskSource {
470
+ readonly kind: 'extension';
471
+ readonly extension?: string;
472
+ readonly scope: TaskScope;
473
+ readonly workspaceFolder: IWorkspaceFolder | undefined;
474
+ }
475
+
476
+ export interface ExtensionTaskSourceTransfer {
477
+ __workspaceFolder: UriComponents;
478
+ __definition: { type: string; [name: string]: any };
479
+ }
480
+
481
+ export interface InMemoryTaskSource extends BaseTaskSource {
482
+ readonly kind: 'inMemory';
483
+ }
484
+
485
+ export interface UserTaskSource extends BaseTaskSource {
486
+ readonly kind: 'user';
487
+ readonly config: TaskSourceConfigElement;
488
+ readonly customizes?: KeyedTaskIdentifier;
489
+ }
490
+
491
+ export interface WorkspaceFileTaskSource extends BaseTaskSource {
492
+ readonly kind: 'workspaceFile';
493
+ readonly config: TaskSourceConfigElement;
494
+ readonly customizes?: KeyedTaskIdentifier;
495
+ }
496
+
497
+ export type TaskSource =
498
+ | WorkspaceTaskSource
499
+ | ExtensionTaskSource
500
+ | InMemoryTaskSource
501
+ | UserTaskSource
502
+ | WorkspaceFileTaskSource;
503
+ export type FileBasedTaskSource = WorkspaceTaskSource | UserTaskSource | WorkspaceFileTaskSource;
504
+ export interface TaskIdentifier {
505
+ type: string;
506
+ [name: string]: any;
507
+ }
508
+
509
+ export interface KeyedTaskIdentifier extends TaskIdentifier {
510
+ _key: string;
511
+ }
512
+
513
+ export interface TaskDependency {
514
+ workspaceFolder: IWorkspaceFolder;
515
+ task: string | KeyedTaskIdentifier | undefined;
516
+ }
517
+
518
+ export const enum GroupType {
519
+ default = 'default',
520
+ user = 'user',
521
+ }
522
+
523
+ export const enum DependsOrder {
524
+ parallel = 'parallel',
525
+ sequence = 'sequence',
526
+ }
527
+
528
+ export interface ConfigurationProperties {
529
+ /**
530
+ * The task's name
531
+ */
532
+ name?: string;
533
+
534
+ /**
535
+ * The task's name
536
+ */
537
+ identifier?: string;
538
+
539
+ /**
540
+ * the task's group;
541
+ */
542
+ group?: string;
543
+
544
+ /**
545
+ * The group type
546
+ */
547
+ groupType?: GroupType;
548
+
549
+ /**
550
+ * The presentation options
551
+ */
552
+ presentation?: PresentationOptions;
553
+
554
+ /**
555
+ * The command options;
556
+ */
557
+ options?: CommandOptions;
558
+
559
+ /**
560
+ * Whether the task is a background task or not.
561
+ */
562
+ isBackground?: boolean;
563
+
564
+ /**
565
+ * Whether the task should prompt on close for confirmation if running.
566
+ */
567
+ promptOnClose?: boolean;
568
+
569
+ /**
570
+ * The other tasks this task depends on.
571
+ */
572
+ dependsOn?: TaskDependency[];
573
+
574
+ /**
575
+ * The order the dependsOn tasks should be executed in.
576
+ */
577
+ dependsOrder?: DependsOrder;
578
+
579
+ /**
580
+ * A description of the task.
581
+ */
582
+ detail?: string;
583
+
584
+ /**
585
+ * The problem watchers to use for this task
586
+ */
587
+ problemMatchers?: Array<string | ProblemMatcher>;
588
+ }
589
+
590
+ export enum RunOnOptions {
591
+ default = 1,
592
+ folderOpen = 2,
593
+ }
594
+
595
+ export interface RunOptions {
596
+ reevaluateOnRerun?: boolean;
597
+ runOn?: RunOnOptions;
598
+ }
599
+
600
+ export namespace RunOptions {
601
+ export const defaults: RunOptions = { reevaluateOnRerun: true, runOn: RunOnOptions.default };
602
+ }
603
+
604
+ export abstract class CommonTask {
605
+ /**
606
+ * The task's internal id
607
+ */
608
+ _id: string;
609
+
610
+ /**
611
+ * The cached label.
612
+ */
613
+ _label = '';
614
+
615
+ type?: string;
616
+
617
+ runOptions: RunOptions;
618
+
619
+ configurationProperties: ConfigurationProperties;
620
+
621
+ _source: BaseTaskSource;
622
+
623
+ private _taskLoadMessages: string[] | undefined;
624
+
625
+ protected constructor(
626
+ id: string,
627
+ label: string | undefined,
628
+ type: string | undefined,
629
+ runOptions: RunOptions,
630
+ configurationProperties: ConfigurationProperties,
631
+ source: BaseTaskSource,
632
+ ) {
633
+ this._id = id;
634
+ if (label) {
635
+ this._label = label;
636
+ }
637
+ if (type) {
638
+ this.type = type;
639
+ }
640
+ this.runOptions = runOptions;
641
+ this.configurationProperties = configurationProperties;
642
+ this._source = source;
643
+ }
644
+
645
+ public getDefinition(useSource?: boolean): KeyedTaskIdentifier | undefined {
646
+ return undefined;
647
+ }
648
+
649
+ public getMapKey(): string {
650
+ return this._id;
651
+ }
652
+
653
+ public getRecentlyUsedKey(): string | undefined {
654
+ return undefined;
655
+ }
656
+
657
+ public clone(): Task {
658
+ return this.fromObject(Object.assign({}, this as any));
659
+ }
660
+
661
+ protected abstract fromObject(object: any): Task;
662
+
663
+ public getWorkspaceFolder(): IWorkspaceFolder | undefined {
664
+ return undefined;
665
+ }
666
+
667
+ public getWorkspaceFileName(): string | undefined {
668
+ return undefined;
669
+ }
670
+
671
+ public getTelemetryKind(): string {
672
+ return 'unknown';
673
+ }
674
+
675
+ public matches(key: string | KeyedTaskIdentifier | undefined, compareId = false): boolean {
676
+ if (key === undefined) {
677
+ return false;
678
+ }
679
+ if (isString(key)) {
680
+ return key === this._label || key === this.configurationProperties.identifier || (compareId && key === this._id);
681
+ }
682
+ const identifier = this.getDefinition(true);
683
+ return identifier !== undefined && identifier._key === key._key;
684
+ }
685
+
686
+ public getQualifiedLabel(): string {
687
+ const workspaceFolder = this.getWorkspaceFolder();
688
+ if (workspaceFolder) {
689
+ return `${this._label} (${workspaceFolder.name})`;
690
+ } else {
691
+ return this._label;
692
+ }
693
+ }
694
+
695
+ public getTaskExecution(): TaskExecution {
696
+ const result: TaskExecution = {
697
+ id: this._id,
698
+ task: this as any,
699
+ };
700
+ return result;
701
+ }
702
+
703
+ public addTaskLoadMessages(messages: string[] | undefined) {
704
+ if (this._taskLoadMessages === undefined) {
705
+ this._taskLoadMessages = [];
706
+ }
707
+ if (messages) {
708
+ this._taskLoadMessages = this._taskLoadMessages.concat(messages);
709
+ }
710
+ }
711
+
712
+ get taskLoadMessages(): string[] | undefined {
713
+ return this._taskLoadMessages;
714
+ }
715
+ }
716
+
717
+ export class CustomTask extends CommonTask {
718
+ type!: '$customized'; // CUSTOMIZED_TASK_TYPE
719
+
720
+ /**
721
+ * Indicated the source of the task (e.g. tasks.json or extension)
722
+ */
723
+ _source: FileBasedTaskSource;
724
+
725
+ hasDefinedMatchers: boolean;
726
+
727
+ /**
728
+ * The command configuration
729
+ */
730
+ command: CommandConfiguration = {};
731
+
732
+ public constructor(
733
+ id: string,
734
+ source: FileBasedTaskSource,
735
+ label: string,
736
+ type: string,
737
+ command: CommandConfiguration | undefined,
738
+ hasDefinedMatchers: boolean,
739
+ runOptions: RunOptions,
740
+ configurationProperties: ConfigurationProperties,
741
+ ) {
742
+ super(id, label, undefined, runOptions, configurationProperties, source);
743
+ this._source = source;
744
+ this.hasDefinedMatchers = hasDefinedMatchers;
745
+ if (command) {
746
+ this.command = command;
747
+ }
748
+ }
749
+
750
+ public customizes(): KeyedTaskIdentifier | undefined {
751
+ if (this._source && this._source.customizes) {
752
+ return this._source.customizes;
753
+ }
754
+ return undefined;
755
+ }
756
+
757
+ public getDefinition(useSource = false): KeyedTaskIdentifier {
758
+ if (useSource && this._source.customizes !== undefined) {
759
+ return this._source.customizes;
760
+ } else {
761
+ let type: string;
762
+ const commandRuntime = this.command ? this.command.runtime : undefined;
763
+ switch (commandRuntime) {
764
+ case RuntimeType.Shell:
765
+ type = 'shell';
766
+ break;
767
+
768
+ case RuntimeType.Process:
769
+ type = 'process';
770
+ break;
771
+
772
+ case RuntimeType.CustomExecution:
773
+ type = 'customExecution';
774
+ break;
775
+
776
+ case undefined:
777
+ type = '$composite';
778
+ break;
779
+
780
+ default:
781
+ throw new Error('Unexpected task runtime');
782
+ }
783
+
784
+ const result: KeyedTaskIdentifier = {
785
+ type,
786
+ _key: this._id,
787
+ id: this._id,
788
+ };
789
+ return result;
790
+ }
791
+ }
792
+
793
+ public static is(value: any): value is CustomTask {
794
+ return value instanceof CustomTask;
795
+ }
796
+
797
+ public getMapKey(): string {
798
+ const workspaceFolder = this._source.config.workspaceFolder;
799
+ return workspaceFolder ? `${workspaceFolder.uri.toString()}|${this._id}` : this._id;
800
+ }
801
+
802
+ public getRecentlyUsedKey(): string | undefined {
803
+ interface CustomKey {
804
+ type: string;
805
+ folder: string;
806
+ id: string;
807
+ }
808
+ const workspaceFolder = this._source.config.workspaceFolder;
809
+ if (!workspaceFolder) {
810
+ return undefined;
811
+ }
812
+ let id: string = this.configurationProperties.identifier!;
813
+ if (this._source.kind !== TaskSourceKind.Workspace) {
814
+ id += this._source.kind;
815
+ }
816
+ const key: CustomKey = { type: CUSTOMIZED_TASK_TYPE, folder: workspaceFolder.uri.toString(), id };
817
+ return JSON.stringify(key);
818
+ }
819
+
820
+ public getWorkspaceFolder(): IWorkspaceFolder | undefined {
821
+ return this._source.config.workspaceFolder;
822
+ }
823
+
824
+ public getWorkspaceFileName(): string | undefined {
825
+ return this._source.config.workspace && this._source.config.workspace.configuration
826
+ ? basename(this._source.config.workspace.configuration.toString())
827
+ : undefined;
828
+ }
829
+
830
+ public getTelemetryKind(): string {
831
+ if (this._source.customizes) {
832
+ return 'workspace>extension';
833
+ } else {
834
+ return 'workspace';
835
+ }
836
+ }
837
+
838
+ protected fromObject(object: CustomTask): CustomTask {
839
+ return new CustomTask(
840
+ object._id,
841
+ object._source,
842
+ object._label,
843
+ object.type,
844
+ object.command,
845
+ object.hasDefinedMatchers,
846
+ object.runOptions,
847
+ object.configurationProperties,
848
+ );
849
+ }
850
+ }
851
+
852
+ export class ConfiguringTask extends CommonTask {
853
+ /**
854
+ * Indicated the source of the task (e.g. tasks.json or extension)
855
+ */
856
+ _source: FileBasedTaskSource;
857
+
858
+ configures: KeyedTaskIdentifier;
859
+
860
+ public constructor(
861
+ id: string,
862
+ source: FileBasedTaskSource,
863
+ label: string | undefined,
864
+ type: string | undefined,
865
+ configures: KeyedTaskIdentifier,
866
+ runOptions: RunOptions,
867
+ configurationProperties: ConfigurationProperties,
868
+ ) {
869
+ super(id, label, type, runOptions, configurationProperties, source);
870
+ this._source = source;
871
+ this.configures = configures;
872
+ }
873
+
874
+ public static is(value: any): value is ConfiguringTask {
875
+ return value instanceof ConfiguringTask;
876
+ }
877
+
878
+ protected fromObject(object: any): Task {
879
+ return object;
880
+ }
881
+
882
+ public getDefinition(): KeyedTaskIdentifier {
883
+ return this.configures;
884
+ }
885
+
886
+ public getWorkspaceFileName(): string | undefined {
887
+ return this._source.config.workspace && this._source.config.workspace.configuration
888
+ ? basename(this._source.config.workspace.configuration.toString())
889
+ : undefined;
890
+ }
891
+ }
892
+
893
+ export class ContributedTask extends CommonTask {
894
+ /**
895
+ * Indicated the source of the task (e.g. tasks.json or extension)
896
+ * Set in the super constructor
897
+ */
898
+ _source!: ExtensionTaskSource;
899
+
900
+ defines: KeyedTaskIdentifier;
901
+
902
+ hasDefinedMatchers: boolean;
903
+
904
+ /**
905
+ * The command configuration
906
+ */
907
+ command: CommandConfiguration;
908
+
909
+ public constructor(
910
+ id: string,
911
+ source: ExtensionTaskSource,
912
+ label: string,
913
+ type: string | undefined,
914
+ defines: KeyedTaskIdentifier,
915
+ command: CommandConfiguration,
916
+ hasDefinedMatchers: boolean,
917
+ runOptions: RunOptions,
918
+ configurationProperties: ConfigurationProperties,
919
+ ) {
920
+ super(id, label, type, runOptions, configurationProperties, source);
921
+ this.defines = defines;
922
+ this.hasDefinedMatchers = hasDefinedMatchers;
923
+ this.command = command;
924
+ }
925
+
926
+ public getDefinition(): KeyedTaskIdentifier {
927
+ return this.defines;
928
+ }
929
+
930
+ public static is(value: any): value is ContributedTask {
931
+ return value instanceof ContributedTask;
932
+ }
933
+
934
+ public getMapKey(): string {
935
+ const workspaceFolder = this._source.workspaceFolder;
936
+ return workspaceFolder
937
+ ? `${this._source.scope.toString()}|${workspaceFolder.uri.toString()}|${this._id}`
938
+ : `${this._source.scope.toString()}|${this._id}`;
939
+ }
940
+
941
+ public getRecentlyUsedKey(): string | undefined {
942
+ interface ContributedKey {
943
+ type: string;
944
+ scope: number;
945
+ folder?: string;
946
+ id: string;
947
+ }
948
+
949
+ const key: ContributedKey = { type: 'contributed', scope: this._source.scope, id: this._id };
950
+ if (this._source.scope === TaskScope.Folder && this._source.workspaceFolder) {
951
+ key.folder = this._source.workspaceFolder.uri.toString();
952
+ }
953
+ return JSON.stringify(key);
954
+ }
955
+
956
+ public getWorkspaceFolder(): IWorkspaceFolder | undefined {
957
+ return this._source.workspaceFolder;
958
+ }
959
+
960
+ public getTelemetryKind(): string {
961
+ return 'extension';
962
+ }
963
+
964
+ protected fromObject(object: ContributedTask): ContributedTask {
965
+ return new ContributedTask(
966
+ object._id,
967
+ object._source,
968
+ object._label,
969
+ object.type,
970
+ object.defines,
971
+ object.command,
972
+ object.hasDefinedMatchers,
973
+ object.runOptions,
974
+ object.configurationProperties,
975
+ );
976
+ }
977
+ }
978
+
979
+ export class InMemoryTask extends CommonTask {
980
+ /**
981
+ * Indicated the source of the task (e.g. tasks.json or extension)
982
+ */
983
+ _source: InMemoryTaskSource;
984
+
985
+ type!: 'inMemory';
986
+
987
+ public constructor(
988
+ id: string,
989
+ source: InMemoryTaskSource,
990
+ label: string,
991
+ type: string,
992
+ runOptions: RunOptions,
993
+ configurationProperties: ConfigurationProperties,
994
+ ) {
995
+ super(id, label, type, runOptions, configurationProperties, source);
996
+ this._source = source;
997
+ }
998
+
999
+ public static is(value: any): value is InMemoryTask {
1000
+ return value instanceof InMemoryTask;
1001
+ }
1002
+
1003
+ public getTelemetryKind(): string {
1004
+ return 'composite';
1005
+ }
1006
+
1007
+ protected fromObject(object: InMemoryTask): InMemoryTask {
1008
+ return new InMemoryTask(
1009
+ object._id,
1010
+ object._source,
1011
+ object._label,
1012
+ object.type,
1013
+ object.runOptions,
1014
+ object.configurationProperties,
1015
+ );
1016
+ }
1017
+ }
1018
+
1019
+ export type Task = CustomTask | ContributedTask | InMemoryTask;
1020
+
1021
+ export enum ExecutionEngine {
1022
+ Process = 1,
1023
+ Terminal = 2,
1024
+ }
1025
+
1026
+ export namespace ExecutionEngine {
1027
+ export const _default: ExecutionEngine = ExecutionEngine.Terminal;
1028
+ }
1029
+
1030
+ export const enum JsonSchemaVersion {
1031
+ V0_1_0 = 1,
1032
+ V2_0_0 = 2,
1033
+ }
1034
+
1035
+ export interface TaskSet {
1036
+ tasks: Task[];
1037
+ extension?: IExtensionProps;
1038
+ type?: string;
1039
+ }
1040
+
1041
+ export interface TaskDefinition {
1042
+ extensionId: string;
1043
+ taskType: string;
1044
+ required: string[];
1045
+ properties: IJSONSchemaMap;
1046
+ }
1047
+
1048
+ export class TaskSorter {
1049
+ private _order: Map<string, number> = new Map();
1050
+
1051
+ constructor(workspaceFolders: IWorkspaceFolder[]) {
1052
+ for (let i = 0; i < workspaceFolders.length; i++) {
1053
+ this._order.set(workspaceFolders[i].uri.toString(), i);
1054
+ }
1055
+ }
1056
+
1057
+ public compare(a: Task, b: Task): number {
1058
+ const aw = a.getWorkspaceFolder();
1059
+ const bw = b.getWorkspaceFolder();
1060
+ if (aw && bw) {
1061
+ let ai = this._order.get(aw.uri.toString());
1062
+ ai = ai === undefined ? 0 : ai + 1;
1063
+ let bi = this._order.get(bw.uri.toString());
1064
+ bi = bi === undefined ? 0 : bi + 1;
1065
+ if (ai === bi) {
1066
+ return a._label.localeCompare(b._label);
1067
+ } else {
1068
+ return ai - bi;
1069
+ }
1070
+ } else if (!aw && bw) {
1071
+ return -1;
1072
+ } else if (aw && !bw) {
1073
+ return +1;
1074
+ } else {
1075
+ return 0;
1076
+ }
1077
+ }
1078
+ }
1079
+
1080
+ export const enum TaskEventKind {
1081
+ DependsOnStarted = 'dependsOnStarted',
1082
+ Start = 'start',
1083
+ ProcessStarted = 'processStarted',
1084
+ Active = 'active',
1085
+ Inactive = 'inactive',
1086
+ Changed = 'changed',
1087
+ Terminated = 'terminated',
1088
+ ProcessEnded = 'processEnded',
1089
+ BackgroundTaskBegin = 'backgroundTaskBegin',
1090
+ BackgroundTaskEnded = 'backgroundTaskEnded',
1091
+ ProblemMatched = 'problemMatched',
1092
+ End = 'end',
1093
+ }
1094
+
1095
+ export const enum TaskRunType {
1096
+ SingleRun = 'singleRun',
1097
+ Background = 'background',
1098
+ }
1099
+
1100
+ export interface TaskEvent {
1101
+ kind: TaskEventKind;
1102
+ taskId?: string;
1103
+ taskName?: string;
1104
+ runType?: TaskRunType;
1105
+ group?: string;
1106
+ processId?: number;
1107
+ exitCode?: number;
1108
+ terminalId?: string;
1109
+ problems?: ProblemMatch[];
1110
+ __task?: Task;
1111
+ }
1112
+
1113
+ export const enum TaskRunSource {
1114
+ System,
1115
+ User,
1116
+ FolderOpen,
1117
+ ConfigurationChange,
1118
+ }
1119
+
1120
+ export namespace TaskEvent {
1121
+ export function create(
1122
+ kind: TaskEventKind.ProcessStarted | TaskEventKind.ProcessEnded,
1123
+ task: Task,
1124
+ processIdOrExitCode?: number,
1125
+ ): TaskEvent;
1126
+ // tslint:disable-next-line: unified-signatures
1127
+ export function create(kind: TaskEventKind.Start, task: Task, terminalId?: string): TaskEvent;
1128
+ export function create(kind: TaskEventKind.ProblemMatched, task: Task, problems?: ProblemMatch[]): TaskEvent;
1129
+ export function create(
1130
+ kind:
1131
+ | TaskEventKind.DependsOnStarted
1132
+ | TaskEventKind.Start
1133
+ | TaskEventKind.Active
1134
+ | TaskEventKind.Inactive
1135
+ | TaskEventKind.Terminated
1136
+ | TaskEventKind.End
1137
+ | TaskEventKind.BackgroundTaskBegin
1138
+ | TaskEventKind.BackgroundTaskEnded
1139
+ | TaskEventKind.ProblemMatched,
1140
+ task: Task,
1141
+ ): TaskEvent;
1142
+ export function create(kind: TaskEventKind.Changed): TaskEvent;
1143
+ export function create(
1144
+ kind: TaskEventKind,
1145
+ task?: Task,
1146
+ processIdOrExitCodeOrTerminalIdOrProblems?: number | string | ProblemMatch[],
1147
+ ): TaskEvent {
1148
+ if (task) {
1149
+ const result: TaskEvent = {
1150
+ kind,
1151
+ taskId: task._id,
1152
+ taskName: task.configurationProperties.name,
1153
+ runType: task.configurationProperties.isBackground ? TaskRunType.Background : TaskRunType.SingleRun,
1154
+ group: task.configurationProperties.group,
1155
+ processId: undefined as number | undefined,
1156
+ exitCode: undefined as number | undefined,
1157
+ terminalId: undefined as string | undefined,
1158
+ __task: task,
1159
+ };
1160
+ if (kind === TaskEventKind.Start) {
1161
+ result.terminalId = processIdOrExitCodeOrTerminalIdOrProblems as string;
1162
+ } else if (kind === TaskEventKind.ProcessStarted) {
1163
+ result.processId = processIdOrExitCodeOrTerminalIdOrProblems as number;
1164
+ } else if (kind === TaskEventKind.ProcessEnded) {
1165
+ result.exitCode = processIdOrExitCodeOrTerminalIdOrProblems as number;
1166
+ } else if (kind === TaskEventKind.ProblemMatched) {
1167
+ result.problems = processIdOrExitCodeOrTerminalIdOrProblems as ProblemMatch[];
1168
+ }
1169
+ return Object.freeze(result);
1170
+ } else {
1171
+ return Object.freeze({ kind: TaskEventKind.Changed });
1172
+ }
1173
+ }
1174
+ }