@theia/task 1.45.1 → 1.46.0-next.72

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 (173) hide show
  1. package/README.md +193 -193
  2. package/lib/browser/index.d.ts +6 -6
  3. package/lib/browser/index.js +33 -33
  4. package/lib/browser/process/process-task-contribution.d.ts +6 -6
  5. package/lib/browser/process/process-task-contribution.js +43 -43
  6. package/lib/browser/process/process-task-frontend-module.d.ts +2 -2
  7. package/lib/browser/process/process-task-frontend-module.js +27 -27
  8. package/lib/browser/process/process-task-resolver.d.ts +17 -17
  9. package/lib/browser/process/process-task-resolver.js +101 -101
  10. package/lib/browser/provided-task-configurations.d.ts +43 -43
  11. package/lib/browser/provided-task-configurations.js +213 -213
  12. package/lib/browser/provided-task-configurations.spec.d.ts +1 -1
  13. package/lib/browser/provided-task-configurations.spec.js +43 -43
  14. package/lib/browser/quick-open-task.d.ts +144 -144
  15. package/lib/browser/quick-open-task.d.ts.map +1 -1
  16. package/lib/browser/quick-open-task.js +752 -748
  17. package/lib/browser/quick-open-task.js.map +1 -1
  18. package/lib/browser/task-configuration-manager.d.ts +64 -64
  19. package/lib/browser/task-configuration-manager.js +261 -261
  20. package/lib/browser/task-configuration-model.d.ts +32 -32
  21. package/lib/browser/task-configuration-model.js +79 -79
  22. package/lib/browser/task-configurations.d.ts +127 -127
  23. package/lib/browser/task-configurations.js +486 -486
  24. package/lib/browser/task-contribution.d.ts +182 -182
  25. package/lib/browser/task-contribution.js +206 -206
  26. package/lib/browser/task-definition-registry.d.ts +38 -38
  27. package/lib/browser/task-definition-registry.js +134 -134
  28. package/lib/browser/task-definition-registry.spec.d.ts +1 -1
  29. package/lib/browser/task-definition-registry.spec.js +170 -170
  30. package/lib/browser/task-frontend-contribution.d.ts +56 -56
  31. package/lib/browser/task-frontend-contribution.js +358 -358
  32. package/lib/browser/task-frontend-module.d.ts +5 -5
  33. package/lib/browser/task-frontend-module.js +79 -79
  34. package/lib/browser/task-name-resolver.d.ts +13 -13
  35. package/lib/browser/task-name-resolver.js +67 -67
  36. package/lib/browser/task-node.d.ts +9 -9
  37. package/lib/browser/task-node.js +17 -17
  38. package/lib/browser/task-preferences.d.ts +4 -4
  39. package/lib/browser/task-preferences.js +40 -40
  40. package/lib/browser/task-problem-matcher-registry.d.ts +40 -40
  41. package/lib/browser/task-problem-matcher-registry.js +309 -309
  42. package/lib/browser/task-problem-pattern-registry.d.ts +23 -23
  43. package/lib/browser/task-problem-pattern-registry.js +210 -210
  44. package/lib/browser/task-schema-updater.d.ts +58 -58
  45. package/lib/browser/task-schema-updater.js +688 -688
  46. package/lib/browser/task-service.d.ts +279 -279
  47. package/lib/browser/task-service.js +1119 -1119
  48. package/lib/browser/task-source-resolver.d.ts +9 -9
  49. package/lib/browser/task-source-resolver.js +51 -51
  50. package/lib/browser/task-templates.d.ts +13 -13
  51. package/lib/browser/task-templates.js +161 -161
  52. package/lib/browser/task-terminal-widget-manager.d.ts +44 -44
  53. package/lib/browser/task-terminal-widget-manager.js +228 -228
  54. package/lib/browser/tasks-monaco-contribution.d.ts +1 -1
  55. package/lib/browser/tasks-monaco-contribution.js +27 -27
  56. package/lib/common/index.d.ts +4 -4
  57. package/lib/common/index.js +31 -31
  58. package/lib/common/problem-matcher-protocol.d.ts +124 -124
  59. package/lib/common/problem-matcher-protocol.js +132 -132
  60. package/lib/common/process/task-protocol.d.ts +68 -68
  61. package/lib/common/process/task-protocol.js +33 -33
  62. package/lib/common/task-common-module.d.ts +7 -7
  63. package/lib/common/task-common-module.js +33 -33
  64. package/lib/common/task-protocol.d.ts +192 -192
  65. package/lib/common/task-protocol.js +137 -137
  66. package/lib/common/task-util.d.ts +22 -22
  67. package/lib/common/task-util.js +46 -46
  68. package/lib/common/task-watcher.d.ts +17 -17
  69. package/lib/common/task-watcher.js +86 -86
  70. package/lib/node/custom/custom-task-runner-backend-module.d.ts +2 -2
  71. package/lib/node/custom/custom-task-runner-backend-module.js +36 -36
  72. package/lib/node/custom/custom-task-runner-contribution.d.ts +6 -6
  73. package/lib/node/custom/custom-task-runner-contribution.js +42 -42
  74. package/lib/node/custom/custom-task-runner.d.ts +15 -15
  75. package/lib/node/custom/custom-task-runner.js +69 -69
  76. package/lib/node/custom/custom-task.d.ts +20 -20
  77. package/lib/node/custom/custom-task.js +78 -78
  78. package/lib/node/index.d.ts +3 -3
  79. package/lib/node/index.js +30 -30
  80. package/lib/node/process/process-task-runner-backend-module.d.ts +2 -2
  81. package/lib/node/process/process-task-runner-backend-module.js +36 -36
  82. package/lib/node/process/process-task-runner-contribution.d.ts +6 -6
  83. package/lib/node/process/process-task-runner-contribution.js +43 -43
  84. package/lib/node/process/process-task-runner.d.ts +60 -60
  85. package/lib/node/process/process-task-runner.js +355 -355
  86. package/lib/node/process/process-task.d.ts +26 -26
  87. package/lib/node/process/process-task.js +135 -135
  88. package/lib/node/process/process-task.spec.d.ts +1 -1
  89. package/lib/node/process/process-task.spec.js +29 -29
  90. package/lib/node/task-abstract-line-matcher.d.ts +49 -49
  91. package/lib/node/task-abstract-line-matcher.js +273 -273
  92. package/lib/node/task-backend-application-contribution.d.ts +8 -8
  93. package/lib/node/task-backend-application-contribution.js +48 -48
  94. package/lib/node/task-backend-module.d.ts +3 -3
  95. package/lib/node/task-backend-module.js +50 -50
  96. package/lib/node/task-line-matchers.d.ts +27 -27
  97. package/lib/node/task-line-matchers.js +121 -121
  98. package/lib/node/task-manager.d.ts +55 -55
  99. package/lib/node/task-manager.js +135 -135
  100. package/lib/node/task-problem-collector.d.ts +10 -10
  101. package/lib/node/task-problem-collector.js +57 -57
  102. package/lib/node/task-problem-collector.spec.d.ts +1 -1
  103. package/lib/node/task-problem-collector.spec.js +310 -310
  104. package/lib/node/task-runner-protocol.d.ts +16 -16
  105. package/lib/node/task-runner-protocol.js +19 -19
  106. package/lib/node/task-runner.d.ts +50 -50
  107. package/lib/node/task-runner.js +97 -97
  108. package/lib/node/task-server.d.ts +39 -39
  109. package/lib/node/task-server.js +237 -237
  110. package/lib/node/task-server.slow-spec.d.ts +1 -1
  111. package/lib/node/task-server.slow-spec.js +395 -395
  112. package/lib/node/task.d.ts +50 -50
  113. package/lib/node/task.js +77 -77
  114. package/lib/node/test/task-test-container.d.ts +2 -2
  115. package/lib/node/test/task-test-container.js +58 -58
  116. package/package.json +14 -14
  117. package/src/browser/index.ts +22 -22
  118. package/src/browser/process/process-task-contribution.ts +31 -31
  119. package/src/browser/process/process-task-frontend-module.ts +27 -27
  120. package/src/browser/process/process-task-resolver.ts +89 -89
  121. package/src/browser/provided-task-configurations.spec.ts +46 -46
  122. package/src/browser/provided-task-configurations.ts +213 -213
  123. package/src/browser/quick-open-task.ts +831 -827
  124. package/src/browser/style/index.css +19 -19
  125. package/src/browser/task-configuration-manager.ts +256 -256
  126. package/src/browser/task-configuration-model.ts +101 -101
  127. package/src/browser/task-configurations.ts +508 -508
  128. package/src/browser/task-contribution.ts +266 -266
  129. package/src/browser/task-definition-registry.spec.ts +203 -203
  130. package/src/browser/task-definition-registry.ts +131 -131
  131. package/src/browser/task-frontend-contribution.ts +402 -402
  132. package/src/browser/task-frontend-module.ts +86 -86
  133. package/src/browser/task-name-resolver.ts +55 -55
  134. package/src/browser/task-node.ts +37 -37
  135. package/src/browser/task-preferences.ts +40 -40
  136. package/src/browser/task-problem-matcher-registry.ts +308 -308
  137. package/src/browser/task-problem-pattern-registry.ts +196 -196
  138. package/src/browser/task-schema-updater.ts +701 -701
  139. package/src/browser/task-service.ts +1164 -1164
  140. package/src/browser/task-source-resolver.ts +36 -36
  141. package/src/browser/task-templates.ts +168 -168
  142. package/src/browser/task-terminal-widget-manager.ts +224 -224
  143. package/src/browser/tasks-monaco-contribution.ts +27 -27
  144. package/src/common/index.ts +20 -20
  145. package/src/common/problem-matcher-protocol.ts +234 -234
  146. package/src/common/process/task-protocol.ts +97 -97
  147. package/src/common/task-common-module.ts +34 -34
  148. package/src/common/task-protocol.ts +317 -317
  149. package/src/common/task-util.ts +43 -43
  150. package/src/common/task-watcher.ts +78 -78
  151. package/src/node/custom/custom-task-runner-backend-module.ts +37 -37
  152. package/src/node/custom/custom-task-runner-contribution.ts +30 -30
  153. package/src/node/custom/custom-task-runner.ts +60 -60
  154. package/src/node/custom/custom-task.ts +73 -73
  155. package/src/node/index.ts +19 -19
  156. package/src/node/process/process-task-runner-backend-module.ts +37 -37
  157. package/src/node/process/process-task-runner-contribution.ts +31 -31
  158. package/src/node/process/process-task-runner.ts +371 -371
  159. package/src/node/process/process-task.spec.ts +30 -30
  160. package/src/node/process/process-task.ts +144 -144
  161. package/src/node/task-abstract-line-matcher.ts +312 -312
  162. package/src/node/task-backend-application-contribution.ts +36 -36
  163. package/src/node/task-backend-module.ts +57 -57
  164. package/src/node/task-line-matchers.ts +127 -127
  165. package/src/node/task-manager.ts +129 -129
  166. package/src/node/task-problem-collector.spec.ts +338 -338
  167. package/src/node/task-problem-collector.ts +62 -62
  168. package/src/node/task-runner-protocol.ts +33 -33
  169. package/src/node/task-runner.ts +96 -96
  170. package/src/node/task-server.slow-spec.ts +444 -444
  171. package/src/node/task-server.ts +263 -263
  172. package/src/node/task.ts +103 -103
  173. package/src/node/test/task-test-container.ts +63 -63
@@ -1,1120 +1,1120 @@
1
- "use strict";
2
- // *****************************************************************************
3
- // Copyright (C) 2017 Ericsson and others.
4
- //
5
- // This program and the accompanying materials are made available under the
6
- // terms of the Eclipse Public License v. 2.0 which is available at
7
- // http://www.eclipse.org/legal/epl-2.0.
8
- //
9
- // This Source Code may also be made available under the following Secondary
10
- // Licenses when the conditions for such availability set forth in the Eclipse
11
- // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
- // with the GNU Classpath Exception which is available at
13
- // https://www.gnu.org/software/classpath/license.html.
14
- //
15
- // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
- // *****************************************************************************
17
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
18
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21
- return c > 3 && r && Object.defineProperty(target, key, r), r;
22
- };
23
- var __metadata = (this && this.__metadata) || function (k, v) {
24
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
25
- };
26
- Object.defineProperty(exports, "__esModule", { value: true });
27
- exports.TaskService = exports.TaskEndedTypes = void 0;
28
- const browser_1 = require("@theia/core/lib/browser");
29
- const opener_service_1 = require("@theia/core/lib/browser/opener-service");
30
- const common_1 = require("@theia/core/lib/common");
31
- const message_service_1 = require("@theia/core/lib/common/message-service");
32
- const promise_util_1 = require("@theia/core/lib/common/promise-util");
33
- const quick_pick_service_1 = require("@theia/core/lib/common/quick-pick-service");
34
- const label_provider_1 = require("@theia/core/lib/browser/label-provider");
35
- const uri_1 = require("@theia/core/lib/common/uri");
36
- const browser_2 = require("@theia/editor/lib/browser");
37
- const problem_manager_1 = require("@theia/markers/lib/browser/problem/problem-manager");
38
- const terminal_service_1 = require("@theia/terminal/lib/browser/base/terminal-service");
39
- const browser_3 = require("@theia/variable-resolver/lib/browser");
40
- const workspace_service_1 = require("@theia/workspace/lib/browser/workspace-service");
41
- const inversify_1 = require("@theia/core/shared/inversify");
42
- const vscode_languageserver_protocol_1 = require("@theia/core/shared/vscode-languageserver-protocol");
43
- const common_2 = require("../common");
44
- const task_watcher_1 = require("../common/task-watcher");
45
- const provided_task_configurations_1 = require("./provided-task-configurations");
46
- const task_configurations_1 = require("./task-configurations");
47
- const task_contribution_1 = require("./task-contribution");
48
- const task_definition_registry_1 = require("./task-definition-registry");
49
- const task_name_resolver_1 = require("./task-name-resolver");
50
- const task_source_resolver_1 = require("./task-source-resolver");
51
- const task_problem_matcher_registry_1 = require("./task-problem-matcher-registry");
52
- const task_schema_updater_1 = require("./task-schema-updater");
53
- const task_configuration_manager_1 = require("./task-configuration-manager");
54
- const problem_widget_1 = require("@theia/markers/lib/browser/problem/problem-widget");
55
- const task_node_1 = require("./task-node");
56
- const monaco_workspace_1 = require("@theia/monaco/lib/browser/monaco-workspace");
57
- const task_terminal_widget_manager_1 = require("./task-terminal-widget-manager");
58
- const shell_terminal_protocol_1 = require("@theia/terminal/lib/common/shell-terminal-protocol");
59
- const async_mutex_1 = require("async-mutex");
60
- var TaskEndedTypes;
61
- (function (TaskEndedTypes) {
62
- TaskEndedTypes[TaskEndedTypes["TaskExited"] = 0] = "TaskExited";
63
- TaskEndedTypes[TaskEndedTypes["BackgroundTaskEnded"] = 1] = "BackgroundTaskEnded";
64
- })(TaskEndedTypes = exports.TaskEndedTypes || (exports.TaskEndedTypes = {}));
65
- let TaskService = class TaskService {
66
- constructor() {
67
- /**
68
- * The last executed task.
69
- */
70
- this.lastTask = { resolvedTask: undefined, option: undefined };
71
- this.cachedRecentTasks = [];
72
- this.runningTasks = new Map();
73
- this.taskStartingLock = new async_mutex_1.Mutex();
74
- }
75
- init() {
76
- this.getRunningTasks().then(tasks => tasks.forEach(task => {
77
- if (!this.runningTasks.has(task.taskId)) {
78
- this.runningTasks.set(task.taskId, {
79
- exitCode: new promise_util_1.Deferred(), terminateSignal: new promise_util_1.Deferred(),
80
- isBackgroundTaskEnded: new promise_util_1.Deferred()
81
- });
82
- }
83
- }));
84
- // notify user that task has started
85
- this.taskWatcher.onTaskCreated((event) => {
86
- if (!this.isEventForThisClient(event.ctx)) {
87
- return;
88
- }
89
- this.runningTasks.set(event.taskId, {
90
- exitCode: new promise_util_1.Deferred(),
91
- terminateSignal: new promise_util_1.Deferred(),
92
- isBackgroundTaskEnded: new promise_util_1.Deferred()
93
- });
94
- });
95
- this.taskWatcher.onOutputProcessed(async (event) => {
96
- if (!this.isEventForThisClient(event.ctx)) {
97
- return;
98
- }
99
- if (event.problems) {
100
- const runningTasksInfo = await this.getRunningTasks();
101
- // check if the task is active
102
- const matchedRunningTaskInfo = runningTasksInfo.find(taskInfo => {
103
- const taskConfig = taskInfo.config;
104
- return this.taskDefinitionRegistry.compareTasks(taskConfig, event.config);
105
- });
106
- const isTaskActiveAndOutputSilent = matchedRunningTaskInfo &&
107
- matchedRunningTaskInfo.config.presentation && matchedRunningTaskInfo.config.presentation.reveal === common_2.RevealKind.Silent;
108
- event.problems.forEach(problem => {
109
- const existingMarkers = this.problemManager.findMarkers({ owner: problem.description.owner });
110
- const uris = new Set();
111
- existingMarkers.forEach(marker => uris.add(marker.uri));
112
- if (common_2.ProblemMatchData.is(problem) && problem.resource) {
113
- // When task.presentation.reveal === RevealKind.Silent, put focus on the terminal only if it is an error
114
- if (isTaskActiveAndOutputSilent && problem.marker.severity === vscode_languageserver_protocol_1.DiagnosticSeverity.Error) {
115
- const terminalId = matchedRunningTaskInfo.terminalId;
116
- if (terminalId) {
117
- const terminal = this.terminalService.getByTerminalId(terminalId);
118
- if (terminal) {
119
- const focus = !!matchedRunningTaskInfo.config.presentation.focus;
120
- if (focus) { // assign focus to the terminal if presentation.focus is true
121
- this.terminalService.open(terminal, { mode: 'activate' });
122
- }
123
- else { // show the terminal but not assign focus
124
- this.terminalService.open(terminal, { mode: 'reveal' });
125
- }
126
- }
127
- }
128
- }
129
- const uri = problem.resource.withScheme(problem.resource.scheme);
130
- const document = this.monacoWorkspace.getTextDocument(uri.toString());
131
- if (problem.description.applyTo === common_2.ApplyToKind.openDocuments && !!document ||
132
- problem.description.applyTo === common_2.ApplyToKind.closedDocuments && !document ||
133
- problem.description.applyTo === common_2.ApplyToKind.allDocuments) {
134
- if (uris.has(uri.toString())) {
135
- const newData = [
136
- ...existingMarkers
137
- .filter(marker => marker.uri === uri.toString())
138
- .map(markerData => markerData.data),
139
- problem.marker
140
- ];
141
- this.problemManager.setMarkers(uri, problem.description.owner, newData);
142
- }
143
- else {
144
- this.problemManager.setMarkers(uri, problem.description.owner, [problem.marker]);
145
- }
146
- }
147
- }
148
- else { // should have received an event for finding the "background task begins" pattern
149
- uris.forEach(uriString => this.problemManager.setMarkers(new uri_1.default(uriString), problem.description.owner, []));
150
- }
151
- });
152
- }
153
- });
154
- this.taskWatcher.onBackgroundTaskEnded((event) => {
155
- if (!this.isEventForThisClient(event.ctx)) {
156
- return;
157
- }
158
- if (!this.runningTasks.has(event.taskId)) {
159
- this.runningTasks.set(event.taskId, {
160
- exitCode: new promise_util_1.Deferred(),
161
- terminateSignal: new promise_util_1.Deferred(),
162
- isBackgroundTaskEnded: new promise_util_1.Deferred()
163
- });
164
- }
165
- this.runningTasks.get(event.taskId).isBackgroundTaskEnded.resolve(true);
166
- });
167
- // notify user that task has finished
168
- this.taskWatcher.onTaskExit((event) => {
169
- if (!this.isEventForThisClient(event.ctx)) {
170
- return;
171
- }
172
- if (!this.runningTasks.has(event.taskId)) {
173
- this.runningTasks.set(event.taskId, {
174
- exitCode: new promise_util_1.Deferred(),
175
- terminateSignal: new promise_util_1.Deferred(),
176
- isBackgroundTaskEnded: new promise_util_1.Deferred()
177
- });
178
- }
179
- this.runningTasks.get(event.taskId).exitCode.resolve(event.code);
180
- this.runningTasks.get(event.taskId).terminateSignal.resolve(event.signal);
181
- setTimeout(() => this.runningTasks.delete(event.taskId), 60 * 1000);
182
- const taskConfig = event.config;
183
- const taskIdentifier = taskConfig ? this.getTaskIdentifier(taskConfig) : event.taskId.toString();
184
- if (event.code !== undefined) {
185
- if (event.code !== 0) {
186
- const eventTaskConfig = event.config;
187
- if (eventTaskConfig && eventTaskConfig.presentation && eventTaskConfig.presentation.reveal === common_2.RevealKind.Silent && event.terminalId) {
188
- const terminal = this.terminalService.getByTerminalId(event.terminalId);
189
- const focus = !!eventTaskConfig.presentation.focus;
190
- if (terminal) {
191
- if (focus) { // assign focus to the terminal if presentation.focus is true
192
- this.terminalService.open(terminal, { mode: 'activate' });
193
- }
194
- else { // show the terminal but not assign focus
195
- this.terminalService.open(terminal, { mode: 'reveal' });
196
- }
197
- }
198
- }
199
- this.messageService.error(`Task '${taskIdentifier}' has exited with code ${event.code}.`);
200
- }
201
- }
202
- else if (event.signal !== undefined) {
203
- this.messageService.info(`Task '${taskIdentifier}' was terminated by signal ${event.signal}.`);
204
- }
205
- else {
206
- console.error('Invalid TaskExitedEvent received, neither code nor signal is set.');
207
- }
208
- });
209
- }
210
- getTaskIdentifier(taskConfig) {
211
- const taskName = this.taskNameResolver.resolve(taskConfig);
212
- const sourceStrUri = this.taskSourceResolver.resolve(taskConfig);
213
- return `${taskName} (${this.labelProvider.getName(new uri_1.default(sourceStrUri))})`;
214
- }
215
- /**
216
- * Client should call this method to indicate that a new user-level action related to tasks has been started,
217
- * like invoking "Run Task..."
218
- * This method returns a token that can be used with various methods in this service.
219
- * As long as a client uses the same token, task providers will only asked once to contribute
220
- * tasks and the set of tasks will be cached. Each time the a new token is used, the cache of
221
- * contributed tasks is cleared.
222
- * @returns a token to be used for task-related actions
223
- */
224
- startUserAction() {
225
- return this.providedTaskConfigurations.startUserAction();
226
- }
227
- /**
228
- * Returns an array of the task configurations configured in tasks.json and provided by the extensions.
229
- * @param token The cache token for the user interaction in progress
230
- */
231
- async getTasks(token) {
232
- const configuredTasks = await this.getConfiguredTasks(token);
233
- const providedTasks = await this.getProvidedTasks(token);
234
- const notCustomizedProvidedTasks = providedTasks.filter(provided => !configuredTasks.some(configured => this.taskDefinitionRegistry.compareTasks(configured, provided)));
235
- return [...configuredTasks, ...notCustomizedProvidedTasks];
236
- }
237
- /**
238
- * Returns an array of the valid task configurations which are configured in tasks.json files
239
- * @param token The cache token for the user interaction in progress
240
- *
241
- */
242
- async getConfiguredTasks(token) {
243
- const invalidTaskConfig = this.taskConfigurations.getInvalidTaskConfigurations()[0];
244
- if (invalidTaskConfig) {
245
- const widget = await this.widgetManager.getOrCreateWidget(problem_widget_1.PROBLEMS_WIDGET_ID);
246
- const isProblemsWidgetVisible = widget && widget.isVisible;
247
- const currentEditorUri = this.editorManager.currentEditor && this.editorManager.currentEditor.editor.getResourceUri();
248
- let isInvalidTaskConfigFileOpen = false;
249
- if (currentEditorUri) {
250
- const folderUri = this.workspaceService.getWorkspaceRootUri(currentEditorUri);
251
- if (folderUri && folderUri.toString() === invalidTaskConfig._scope) {
252
- isInvalidTaskConfigFileOpen = true;
253
- }
254
- }
255
- const warningMessage = 'Invalid task configurations are found. Open tasks.json and find details in the Problems view.';
256
- if (!isProblemsWidgetVisible || !isInvalidTaskConfigFileOpen) {
257
- this.messageService.warn(warningMessage, 'Open').then(actionOpen => {
258
- if (actionOpen) {
259
- if (invalidTaskConfig && invalidTaskConfig._scope) {
260
- this.taskConfigurationManager.openConfiguration(invalidTaskConfig._scope);
261
- }
262
- if (!isProblemsWidgetVisible) {
263
- this.commands.executeCommand('problemsView:toggle');
264
- }
265
- }
266
- });
267
- }
268
- else {
269
- this.messageService.warn(warningMessage);
270
- }
271
- }
272
- const validTaskConfigs = await this.taskConfigurations.getTasks(token);
273
- return validTaskConfigs;
274
- }
275
- /**
276
- * Returns an array that contains the task configurations provided by the task providers for the specified task type.
277
- * @param token The cache token for the user interaction in progress
278
- * @param type The task type (filter) associated to the returning TaskConfigurations
279
- *
280
- * '*' indicates all tasks regardless of the type
281
- */
282
- getProvidedTasks(token, type) {
283
- return this.providedTaskConfigurations.getTasks(token, type);
284
- }
285
- addRecentTasks(tasks) {
286
- if (Array.isArray(tasks)) {
287
- tasks.forEach(task => this.addRecentTasks(task));
288
- }
289
- else {
290
- const ind = this.cachedRecentTasks.findIndex(recent => this.taskDefinitionRegistry.compareTasks(recent, tasks));
291
- if (ind >= 0) {
292
- this.cachedRecentTasks.splice(ind, 1);
293
- }
294
- this.cachedRecentTasks.unshift(tasks);
295
- }
296
- }
297
- get recentTasks() {
298
- return this.cachedRecentTasks;
299
- }
300
- set recentTasks(recent) {
301
- this.cachedRecentTasks = recent;
302
- }
303
- /**
304
- * Clears the list of recently used tasks.
305
- */
306
- clearRecentTasks() {
307
- this.cachedRecentTasks = [];
308
- }
309
- /**
310
- * Open user ser
311
- */
312
- openUserTasks() {
313
- return this.taskConfigurations.openUserTasks();
314
- }
315
- /**
316
- * Returns a task configuration provided by an extension by task source, scope and label.
317
- * If there are no task configuration, returns undefined.
318
- * @param token The cache token for the user interaction in progress
319
- * @param source The source for configured tasks
320
- * @param label The label of the task to find
321
- * @param scope The task scope to look in
322
- */
323
- async getProvidedTask(token, source, label, scope) {
324
- return this.providedTaskConfigurations.getTask(token, source, label, scope);
325
- }
326
- /** Returns an array of running tasks 'TaskInfo' objects */
327
- getRunningTasks() {
328
- return this.taskServer.getTasks(this.getContext());
329
- }
330
- async customExecutionComplete(id, exitCode) {
331
- return this.taskServer.customExecutionComplete(id, exitCode);
332
- }
333
- /** Returns an array of task types that are registered, including the default types */
334
- getRegisteredTaskTypes() {
335
- return this.taskSchemaUpdater.getRegisteredTaskTypes();
336
- }
337
- /**
338
- * Get the last executed task.
339
- *
340
- * @returns the last executed task or `undefined`.
341
- */
342
- getLastTask() {
343
- return this.lastTask;
344
- }
345
- /**
346
- * Runs a task, by task configuration label.
347
- * Note, it looks for a task configured in tasks.json only.
348
- * @param token The cache token for the user interaction in progress
349
- * @param scope The scope where to look for tasks
350
- * @param taskLabel the label to look for
351
- */
352
- async runConfiguredTask(token, scope, taskLabel) {
353
- const task = this.taskConfigurations.getTask(scope, taskLabel);
354
- if (!task) {
355
- this.logger.error(`Can't get task launch configuration for label: ${taskLabel}`);
356
- return;
357
- }
358
- this.run(token, task._source, taskLabel, scope);
359
- }
360
- /**
361
- * Run the last executed task.
362
- * @param token The cache token for the user interaction in progress
363
- */
364
- async runLastTask(token) {
365
- var _a, _b;
366
- if (!((_a = this.lastTask) === null || _a === void 0 ? void 0 : _a.resolvedTask)) {
367
- return;
368
- }
369
- if (!((_b = this.lastTask.resolvedTask.runOptions) === null || _b === void 0 ? void 0 : _b.reevaluateOnRerun)) {
370
- return this.runResolvedTask(this.lastTask.resolvedTask, this.lastTask.option);
371
- }
372
- const { _source, label, _scope } = this.lastTask.resolvedTask;
373
- return this.run(token, _source, label, _scope);
374
- }
375
- /**
376
- * Runs a task, by the source and label of the task configuration.
377
- * It looks for configured and detected tasks.
378
- * @param token The cache token for the user interaction in progress
379
- * @param source The source for configured tasks
380
- * @param taskLabel The label to look for
381
- * @param scope The scope where to look for tasks
382
- */
383
- async run(token, source, taskLabel, scope) {
384
- var _a, _b;
385
- let task;
386
- task = this.taskConfigurations.getTask(scope, taskLabel);
387
- if (!task) { // if a configured task cannot be found, search from detected tasks
388
- task = await this.getProvidedTask(token, source, taskLabel, scope);
389
- if (!task) { // find from the customized detected tasks
390
- task = await this.taskConfigurations.getCustomizedTask(token, scope, taskLabel);
391
- }
392
- if (!task) {
393
- this.logger.error(`Can't get task launch configuration for label: ${taskLabel}`);
394
- return;
395
- }
396
- }
397
- const customizationObject = await this.getTaskCustomization(task);
398
- if (!customizationObject.problemMatcher) {
399
- // ask the user what s/he wants to use to parse the task output
400
- const items = this.getCustomizeProblemMatcherItems();
401
- const selected = await this.quickPickService.show(items, {
402
- placeholder: 'Select for which kind of errors and warnings to scan the task output'
403
- });
404
- if (selected && ('value' in selected)) {
405
- if ((_a = selected.value) === null || _a === void 0 ? void 0 : _a.problemMatchers) {
406
- let matcherNames = [];
407
- if (selected.value.problemMatchers && selected.value.problemMatchers.length === 0) { // never parse output for this task
408
- matcherNames = [];
409
- }
410
- else if (selected.value.problemMatchers && selected.value.problemMatchers.length > 0) { // continue with user-selected parser
411
- matcherNames = selected.value.problemMatchers.map(matcher => matcher.name);
412
- }
413
- customizationObject.problemMatcher = matcherNames;
414
- // write the selected matcher (or the decision of "never parse") into the `tasks.json`
415
- this.updateTaskConfiguration(token, task, { problemMatcher: matcherNames });
416
- }
417
- else if ((_b = selected.value) === null || _b === void 0 ? void 0 : _b.learnMore) { // user wants to learn more about parsing task output
418
- (0, opener_service_1.open)(this.openerService, new uri_1.default('https://code.visualstudio.com/docs/editor/tasks#_processing-task-output-with-problem-matchers'));
419
- }
420
- // else, continue the task with no parser
421
- }
422
- else { // do not start the task in case that the user did not select any item from the list
423
- return;
424
- }
425
- }
426
- const resolvedMatchers = await this.resolveProblemMatchers(task, customizationObject);
427
- const runTaskOption = {
428
- customization: { ...customizationObject, ...{ problemMatcher: resolvedMatchers } }
429
- };
430
- if (task.dependsOn) {
431
- return this.runCompoundTask(token, task, runTaskOption);
432
- }
433
- else {
434
- return this.runTask(task, runTaskOption).catch(error => {
435
- console.error('Error at launching task', error);
436
- return undefined;
437
- });
438
- }
439
- }
440
- /**
441
- * Runs a compound task
442
- * @param token The cache token for the user interaction in progress
443
- * @param task The task to be executed
444
- * @param option options for executing the task
445
- */
446
- async runCompoundTask(token, task, option) {
447
- const tasks = await this.getWorkspaceTasks(token, task._scope);
448
- try {
449
- const rootNode = new task_node_1.TaskNode(task, [], []);
450
- this.detectDirectedAcyclicGraph(task, rootNode, tasks);
451
- }
452
- catch (error) {
453
- console.error(`Error at launching task '${task.label}'`, error);
454
- this.messageService.error(error.message);
455
- return undefined;
456
- }
457
- return this.runTasksGraph(task, tasks, option).catch(error => {
458
- console.error(`Error at launching task '${task.label}'`, error);
459
- return undefined;
460
- });
461
- }
462
- /**
463
- * A recursive function that runs a task and all its sub tasks that it depends on.
464
- * A task can be executed only when all of its dependencies have been executed, or when it doesn’t have any dependencies at all.
465
- */
466
- async runTasksGraph(task, tasks, option) {
467
- if (task && task.dependsOn) {
468
- // In case it is an array of task dependencies
469
- if (Array.isArray(task.dependsOn) && task.dependsOn.length > 0) {
470
- const dependentTasks = [];
471
- for (let i = 0; i < task.dependsOn.length; i++) {
472
- // It may be a string (a task label) or a JSON object which represents a TaskIdentifier (e.g. {"type":"npm", "script":"script1"})
473
- const taskIdentifier = task.dependsOn[i];
474
- const dependentTask = this.getDependentTask(taskIdentifier, tasks);
475
- const taskCustomization = await this.getTaskCustomization(dependentTask);
476
- const resolvedMatchers = await this.resolveProblemMatchers(dependentTask, taskCustomization);
477
- dependentTasks.push({ 'task': dependentTask, 'taskCustomization': taskCustomization, 'resolvedMatchers': resolvedMatchers });
478
- // In case the 'dependsOrder' is 'sequence'
479
- if (task.dependsOrder && task.dependsOrder === common_2.DependsOrder.Sequence) {
480
- await this.runTasksGraph(dependentTask, tasks, {
481
- customization: { ...taskCustomization, ...{ problemMatcher: resolvedMatchers } }
482
- });
483
- }
484
- }
485
- // In case the 'dependsOrder' is 'parallel'
486
- if (((!task.dependsOrder) || (task.dependsOrder && task.dependsOrder === common_2.DependsOrder.Parallel))) {
487
- const promises = dependentTasks.map(item => this.runTasksGraph(item.task, tasks, {
488
- customization: { ...item.taskCustomization, ...{ problemMatcher: item.resolvedMatchers } }
489
- }));
490
- await Promise.all(promises);
491
- }
492
- }
493
- else if (!Array.isArray(task.dependsOn)) {
494
- // In case it is a string (a task label) or a JSON object which represents a TaskIdentifier (e.g. {"type":"npm", "script":"script1"})
495
- const taskIdentifier = task.dependsOn;
496
- const dependentTask = this.getDependentTask(taskIdentifier, tasks);
497
- const taskCustomization = await this.getTaskCustomization(dependentTask);
498
- const resolvedMatchers = await this.resolveProblemMatchers(dependentTask, taskCustomization);
499
- await this.runTasksGraph(dependentTask, tasks, {
500
- customization: { ...taskCustomization, ...{ problemMatcher: resolvedMatchers } }
501
- });
502
- }
503
- }
504
- const taskInfo = await this.runTask(task, option);
505
- if (taskInfo) {
506
- const getExitCodePromise = this.getExitCode(taskInfo.taskId).then(result => ({ taskEndedType: TaskEndedTypes.TaskExited, value: result }));
507
- const isBackgroundTaskEndedPromise = this.isBackgroundTaskEnded(taskInfo.taskId).then(result => ({ taskEndedType: TaskEndedTypes.BackgroundTaskEnded, value: result }));
508
- // After start running the task, we wait for the task process to exit and if it is a background task, we also wait for a feedback
509
- // that a background task is active, as soon as one of the promises fulfills, we can continue and analyze the results.
510
- const taskEndedInfo = await Promise.race([getExitCodePromise, isBackgroundTaskEndedPromise]);
511
- if ((taskEndedInfo.taskEndedType === TaskEndedTypes.TaskExited && taskEndedInfo.value !== 0) ||
512
- (taskEndedInfo.taskEndedType === TaskEndedTypes.BackgroundTaskEnded && !taskEndedInfo.value)) {
513
- throw new Error('The task: ' + task.label + ' terminated with exit code ' + taskEndedInfo.value + '.');
514
- }
515
- }
516
- return taskInfo;
517
- }
518
- /**
519
- * Creates a graph of dependencies tasks from the root task and verify there is no DAG (Directed Acyclic Graph).
520
- * In case of detection of a circular dependency, an error is thrown with a message which describes the detected circular reference.
521
- */
522
- detectDirectedAcyclicGraph(task, taskNode, tasks) {
523
- if (task && task.dependsOn) {
524
- // In case the 'dependsOn' is an array
525
- if (Array.isArray(task.dependsOn) && task.dependsOn.length > 0) {
526
- for (let i = 0; i < task.dependsOn.length; i++) {
527
- const childNode = this.createChildTaskNode(task, taskNode, task.dependsOn[i], tasks);
528
- this.detectDirectedAcyclicGraph(childNode.taskConfiguration, childNode.node, tasks);
529
- }
530
- }
531
- else if (!Array.isArray(task.dependsOn)) {
532
- const childNode = this.createChildTaskNode(task, taskNode, task.dependsOn, tasks);
533
- this.detectDirectedAcyclicGraph(childNode.taskConfiguration, childNode.node, tasks);
534
- }
535
- }
536
- }
537
- // 'childTaskIdentifier' may be a string (a task label) or a JSON object which represents a TaskIdentifier (e.g. {"type":"npm", "script":"script1"})
538
- createChildTaskNode(task, taskNode, childTaskIdentifier, tasks) {
539
- const childTaskConfiguration = this.getDependentTask(childTaskIdentifier, tasks);
540
- // If current task and child task are identical or if
541
- // one of the child tasks is identical to one of the current task ancestors, then raise an error
542
- if (this.taskDefinitionRegistry.compareTasks(task, childTaskConfiguration) ||
543
- taskNode.parentsID.filter(t => this.taskDefinitionRegistry.compareTasks(childTaskConfiguration, t)).length > 0) {
544
- const fromNode = task.label;
545
- const toNode = childTaskConfiguration.label;
546
- throw new Error('Circular reference detected: ' + fromNode + ' --> ' + toNode);
547
- }
548
- const childNode = new task_node_1.TaskNode(childTaskConfiguration, [], Object.assign([], taskNode.parentsID));
549
- childNode.addParentDependency(taskNode.taskId);
550
- taskNode.addChildDependency(childNode);
551
- return { 'taskConfiguration': childTaskConfiguration, 'node': childNode };
552
- }
553
- /**
554
- * Gets task configuration by task label or by a JSON object which represents a task identifier
555
- *
556
- * @param taskIdentifier The task label (string) or a JSON object which represents a TaskIdentifier (e.g. {"type":"npm", "script":"script1"})
557
- * @param tasks an array of the task configurations
558
- * @returns the correct TaskConfiguration object which matches the taskIdentifier
559
- */
560
- getDependentTask(taskIdentifier, tasks) {
561
- const notEnoughDataError = 'The information provided in the "dependsOn" is not enough for matching the correct task !';
562
- let currentTaskChildConfiguration;
563
- if (typeof (taskIdentifier) !== 'string') {
564
- // TaskIdentifier object does not support tasks of type 'shell' (The same behavior as in VS Code).
565
- // So if we want the 'dependsOn' property to include tasks of type 'shell',
566
- // then we must mention their labels (in the 'dependsOn' property) and not to create a task identifier object for them.
567
- currentTaskChildConfiguration = this.getTaskByTaskIdentifier(taskIdentifier, tasks);
568
- if (!currentTaskChildConfiguration.type) {
569
- this.messageService.error(notEnoughDataError);
570
- throw new Error(notEnoughDataError);
571
- }
572
- return currentTaskChildConfiguration;
573
- }
574
- else {
575
- currentTaskChildConfiguration = tasks.filter(t => taskIdentifier === this.taskNameResolver.resolve(t))[0];
576
- return currentTaskChildConfiguration;
577
- }
578
- }
579
- /**
580
- * Gets the matched task from an array of task configurations by TaskIdentifier.
581
- * In case that more than one task configuration matches, we returns the first one.
582
- *
583
- * @param taskIdentifier The task label (string) or a JSON object which represents a TaskIdentifier (e.g. {"type":"npm", "script":"script1"})
584
- * @param tasks An array of task configurations.
585
- * @returns The correct TaskConfiguration object which matches the taskIdentifier.
586
- */
587
- getTaskByTaskIdentifier(taskIdentifier, tasks) {
588
- const requiredProperties = Object.keys(taskIdentifier);
589
- const taskWithAllProperties = tasks.find(task => requiredProperties.every(property => task.hasOwnProperty(property) && task[property] === taskIdentifier[property]));
590
- return taskWithAllProperties !== null && taskWithAllProperties !== void 0 ? taskWithAllProperties : { label: '', _scope: '', type: '' }; // Fall back to empty TaskConfiguration
591
- }
592
- async runTask(task, option) {
593
- console.debug('entering runTask');
594
- const releaseLock = await this.taskStartingLock.acquire();
595
- console.debug('got lock');
596
- try {
597
- // resolve problemMatchers
598
- if (!option && task.problemMatcher) {
599
- const customizationObject = { type: task.taskType, problemMatcher: task.problemMatcher, runOptions: task.runOptions };
600
- const resolvedMatchers = await this.resolveProblemMatchers(task, customizationObject);
601
- option = {
602
- customization: { ...customizationObject, ...{ problemMatcher: resolvedMatchers } }
603
- };
604
- }
605
- const runningTasksInfo = await this.getRunningTasks();
606
- // check if the task is active
607
- const matchedRunningTaskInfo = runningTasksInfo.find(taskInfo => {
608
- const taskConfig = taskInfo.config;
609
- return this.taskDefinitionRegistry.compareTasks(taskConfig, task);
610
- });
611
- console.debug(`running task ${JSON.stringify(task)}, already running = ${!!matchedRunningTaskInfo}`);
612
- if (matchedRunningTaskInfo) { // the task is active
613
- releaseLock();
614
- console.debug('released lock');
615
- const taskName = this.taskNameResolver.resolve(task);
616
- const terminalId = matchedRunningTaskInfo.terminalId;
617
- if (terminalId) {
618
- const terminal = this.terminalService.getByTerminalId(terminalId);
619
- if (terminal) {
620
- if (common_2.TaskOutputPresentation.shouldSetFocusToTerminal(task)) { // assign focus to the terminal if presentation.focus is true
621
- this.terminalService.open(terminal, { mode: 'activate' });
622
- }
623
- else if (common_2.TaskOutputPresentation.shouldAlwaysRevealTerminal(task)) { // show the terminal but not assign focus
624
- this.terminalService.open(terminal, { mode: 'reveal' });
625
- }
626
- }
627
- }
628
- const selectedAction = await this.messageService.info(`The task '${taskName}' is already active`, 'Terminate Task', 'Restart Task');
629
- if (selectedAction === 'Terminate Task') {
630
- await this.terminateTask(matchedRunningTaskInfo);
631
- }
632
- else if (selectedAction === 'Restart Task') {
633
- return this.restartTask(matchedRunningTaskInfo, option);
634
- }
635
- }
636
- else { // run task as the task is not active
637
- console.debug('task about to start');
638
- const taskInfo = await this.doRunTask(task, option);
639
- releaseLock();
640
- console.debug('release lock 2');
641
- return taskInfo;
642
- }
643
- }
644
- catch (e) {
645
- releaseLock();
646
- throw e;
647
- }
648
- }
649
- /**
650
- * Terminates a task that is actively running.
651
- * @param activeTaskInfo the TaskInfo of the task that is actively running
652
- */
653
- async terminateTask(activeTaskInfo) {
654
- const taskId = activeTaskInfo.taskId;
655
- return this.kill(taskId);
656
- }
657
- /**
658
- * Terminates a task that is actively running, and restarts it.
659
- * @param activeTaskInfo the TaskInfo of the task that is actively running
660
- */
661
- async restartTask(activeTaskInfo, option) {
662
- await this.terminateTask(activeTaskInfo);
663
- return this.doRunTask(activeTaskInfo.config, option);
664
- }
665
- async doRunTask(task, option) {
666
- let overridePropertiesFunction = () => { };
667
- if (option && option.customization) {
668
- const taskDefinition = this.taskDefinitionRegistry.getDefinition(task);
669
- if (taskDefinition) { // use the customization object to override the task config
670
- overridePropertiesFunction = tsk => {
671
- Object.keys(option.customization).forEach(customizedProperty => {
672
- // properties used to define the task cannot be customized
673
- if (customizedProperty !== 'type' && !taskDefinition.properties.all.some(pDefinition => pDefinition === customizedProperty)) {
674
- tsk[customizedProperty] = option.customization[customizedProperty];
675
- }
676
- });
677
- };
678
- }
679
- }
680
- overridePropertiesFunction(task);
681
- this.addRecentTasks(task);
682
- try {
683
- const resolver = await this.taskResolverRegistry.getTaskResolver(task.type);
684
- const resolvedTask = resolver ? await resolver.resolveTask(task) : task;
685
- const executionResolver = this.taskResolverRegistry.getExecutionResolver(resolvedTask.taskType || resolvedTask.type);
686
- overridePropertiesFunction(resolvedTask);
687
- const taskToRun = executionResolver ? await executionResolver.resolveTask(resolvedTask) : resolvedTask;
688
- await this.removeProblemMarkers(option);
689
- return this.runResolvedTask(taskToRun, option);
690
- }
691
- catch (error) {
692
- const errMessage = `Error resolving task '${task.label}': ${error}`;
693
- this.logger.error(errMessage);
694
- }
695
- return undefined;
696
- }
697
- /**
698
- * Runs the first task with the given label.
699
- *
700
- * @param token The cache token for the user interaction in progress
701
- * @param taskLabel The label of the task to be executed
702
- */
703
- async runTaskByLabel(token, taskLabel) {
704
- const tasks = await this.getTasks(token);
705
- for (const task of tasks) {
706
- if (task.label === taskLabel) {
707
- return this.runTask(task);
708
- }
709
- }
710
- return;
711
- }
712
- /**
713
- * Runs a task identified by the given identifier, but only if found in the given workspace folder
714
- *
715
- * @param token The cache token for the user interaction in progress
716
- * @param workspaceFolderUri The folder to restrict the search to
717
- * @param taskIdentifier The identifier to look for
718
- */
719
- async runWorkspaceTask(token, workspaceFolderUri, taskIdentifier) {
720
- const tasks = await this.getWorkspaceTasks(token, workspaceFolderUri);
721
- const task = this.getDependentTask(taskIdentifier, tasks);
722
- if (!task) {
723
- return undefined;
724
- }
725
- const taskCustomization = await this.getTaskCustomization(task);
726
- const resolvedMatchers = await this.resolveProblemMatchers(task, taskCustomization);
727
- try {
728
- const rootNode = new task_node_1.TaskNode(task, [], []);
729
- this.detectDirectedAcyclicGraph(task, rootNode, tasks);
730
- }
731
- catch (error) {
732
- this.logger.error(error.message);
733
- this.messageService.error(error.message);
734
- return undefined;
735
- }
736
- return this.runTasksGraph(task, tasks, {
737
- customization: { ...taskCustomization, ...{ problemMatcher: resolvedMatchers } }
738
- }).catch(error => {
739
- console.log(error.message);
740
- return undefined;
741
- });
742
- }
743
- /**
744
- * Updates the task configuration in the `tasks.json`.
745
- * The task config, together with updates, will be written into the `tasks.json` if it is not found in the file.
746
- *
747
- * @param token The cache token for the user interaction in progress
748
- * @param task task that the updates will be applied to
749
- * @param update the updates to be applied
750
- */
751
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
752
- async updateTaskConfiguration(token, task, update) {
753
- if (update.problemMatcher) {
754
- if (Array.isArray(update.problemMatcher)) {
755
- update.problemMatcher.forEach((_name, index) => update.problemMatcher[index] = (0, common_2.asVariableName)(update.problemMatcher[index]));
756
- }
757
- else {
758
- update.problemMatcher = (0, common_2.asVariableName)(update.problemMatcher);
759
- }
760
- }
761
- this.taskConfigurations.updateTaskConfig(token, task, update);
762
- }
763
- async getWorkspaceTasks(token, restrictToFolder) {
764
- const tasks = await this.getTasks(token);
765
- // if we pass undefined, return everything, otherwise only tasks with the same uri or workspace/global scope tasks
766
- return tasks.filter(t => typeof t._scope !== 'string' || t._scope === restrictToFolder);
767
- }
768
- async resolveProblemMatchers(task, customizationObject) {
769
- const notResolvedMatchers = customizationObject.problemMatcher ?
770
- (Array.isArray(customizationObject.problemMatcher) ? customizationObject.problemMatcher : [customizationObject.problemMatcher]) : undefined;
771
- let resolvedMatchers = [];
772
- if (notResolvedMatchers) {
773
- // resolve matchers before passing them to the server
774
- for (const matcher of notResolvedMatchers) {
775
- let resolvedMatcher;
776
- await this.problemMatcherRegistry.onReady();
777
- if (typeof matcher === 'string') {
778
- resolvedMatcher = this.problemMatcherRegistry.get(matcher);
779
- }
780
- else {
781
- resolvedMatcher = await this.problemMatcherRegistry.getProblemMatcherFromContribution(matcher);
782
- }
783
- if (resolvedMatcher) {
784
- const scope = task._scope || task._source;
785
- if (resolvedMatcher.filePrefix && scope) {
786
- const options = {
787
- context: new uri_1.default(scope).withScheme('file'),
788
- configurationSection: 'tasks'
789
- };
790
- const resolvedPrefix = await this.variableResolverService.resolve(resolvedMatcher.filePrefix, options);
791
- Object.assign(resolvedMatcher, { filePrefix: resolvedPrefix });
792
- }
793
- resolvedMatchers.push(resolvedMatcher);
794
- }
795
- }
796
- }
797
- else {
798
- resolvedMatchers = undefined;
799
- }
800
- return resolvedMatchers;
801
- }
802
- async getTaskCustomization(task) {
803
- const customizationObject = { type: '', _scope: task._scope, runOptions: task.runOptions };
804
- const customizationFound = this.taskConfigurations.getCustomizationForTask(task);
805
- if (customizationFound) {
806
- Object.assign(customizationObject, customizationFound);
807
- }
808
- else {
809
- Object.assign(customizationObject, {
810
- type: task.type,
811
- problemMatcher: task.problemMatcher
812
- });
813
- }
814
- return customizationObject;
815
- }
816
- async removeProblemMarkers(option) {
817
- if (option && option.customization) {
818
- const matchersFromOption = option.customization.problemMatcher || [];
819
- for (const matcher of matchersFromOption) {
820
- if (matcher && matcher.owner) {
821
- const existingMarkers = this.problemManager.findMarkers({ owner: matcher.owner });
822
- const uris = new Set();
823
- existingMarkers.forEach(marker => uris.add(marker.uri));
824
- uris.forEach(uriString => this.problemManager.setMarkers(new uri_1.default(uriString), matcher.owner, []));
825
- }
826
- }
827
- }
828
- }
829
- /**
830
- * Runs the resolved task and opens terminal widget if the task is based on a terminal process
831
- * @param resolvedTask the resolved task
832
- * @param option options to run the resolved task
833
- */
834
- async runResolvedTask(resolvedTask, option) {
835
- const taskLabel = resolvedTask.label;
836
- let taskInfo;
837
- try {
838
- taskInfo = await this.taskServer.run(resolvedTask, this.getContext(), option);
839
- this.lastTask = { resolvedTask, option };
840
- this.logger.debug(`Task created. Task id: ${taskInfo.taskId}`);
841
- /**
842
- * open terminal widget if the task is based on a terminal process (type: 'shell' or 'process')
843
- *
844
- * @todo Use a different mechanism to determine if the task should be attached?
845
- * Reason: Maybe a new task type wants to also be displayed in a terminal.
846
- */
847
- if (typeof taskInfo.terminalId === 'number') {
848
- await this.attach(taskInfo.terminalId, taskInfo);
849
- }
850
- return taskInfo;
851
- }
852
- catch (error) {
853
- const errorStr = `Error launching task '${taskLabel}': ${error.message}`;
854
- this.logger.error(errorStr);
855
- this.messageService.error(errorStr);
856
- if (taskInfo && typeof taskInfo.terminalId === 'number') {
857
- this.shellTerminalServer.onAttachAttempted(taskInfo.terminalId);
858
- }
859
- }
860
- }
861
- getCustomizeProblemMatcherItems() {
862
- const items = [];
863
- items.push({
864
- label: 'Continue without scanning the task output',
865
- value: { problemMatchers: undefined }
866
- });
867
- items.push({
868
- label: 'Never scan the task output',
869
- value: { problemMatchers: [] }
870
- });
871
- items.push({
872
- label: 'Learn more about scanning the task output',
873
- value: { problemMatchers: undefined, learnMore: true }
874
- });
875
- items.push({ type: 'separator', label: 'registered parsers' });
876
- const registeredProblemMatchers = this.problemMatcherRegistry.getAll();
877
- items.push(...registeredProblemMatchers.map(matcher => ({
878
- label: matcher.label,
879
- value: { problemMatchers: [matcher] },
880
- description: (0, common_2.asVariableName)(matcher.name)
881
- })));
882
- return items;
883
- }
884
- /**
885
- * Run selected text in the last active terminal.
886
- */
887
- async runSelectedText() {
888
- if (!this.editorManager.currentEditor) {
889
- return;
890
- }
891
- const startLine = this.editorManager.currentEditor.editor.selection.start.line;
892
- const startCharacter = this.editorManager.currentEditor.editor.selection.start.character;
893
- const endLine = this.editorManager.currentEditor.editor.selection.end.line;
894
- const endCharacter = this.editorManager.currentEditor.editor.selection.end.character;
895
- let selectedRange = vscode_languageserver_protocol_1.Range.create(startLine, startCharacter, endLine, endCharacter);
896
- // if no text is selected, default to selecting entire line
897
- if (startLine === endLine && startCharacter === endCharacter) {
898
- selectedRange = vscode_languageserver_protocol_1.Range.create(startLine, 0, endLine + 1, 0);
899
- }
900
- const selectedText = this.editorManager.currentEditor.editor.document.getText(selectedRange).trimRight() + '\n';
901
- let terminal = this.terminalService.lastUsedTerminal;
902
- if (!terminal || terminal.kind !== 'user' || (await terminal.hasChildProcesses())) {
903
- terminal = await this.terminalService.newTerminal({ created: new Date().toString() });
904
- await terminal.start();
905
- this.terminalService.open(terminal);
906
- }
907
- terminal.sendText(selectedText);
908
- }
909
- async attach(terminalId, taskInfo) {
910
- let widgetOpenMode = 'open';
911
- if (taskInfo) {
912
- const terminalWidget = this.terminalService.getByTerminalId(terminalId);
913
- if (terminalWidget) {
914
- this.messageService.error('Task is already running in terminal');
915
- return this.terminalService.open(terminalWidget, { mode: 'activate' });
916
- }
917
- if (common_2.TaskOutputPresentation.shouldAlwaysRevealTerminal(taskInfo.config)) {
918
- if (common_2.TaskOutputPresentation.shouldSetFocusToTerminal(taskInfo.config)) { // assign focus to the terminal if presentation.focus is true
919
- widgetOpenMode = 'activate';
920
- }
921
- else { // show the terminal but not assign focus
922
- widgetOpenMode = 'reveal';
923
- }
924
- }
925
- }
926
- const { taskId } = taskInfo;
927
- // Create / find a terminal widget to display an execution output of a task that was launched as a command inside a shell.
928
- const widget = await this.taskTerminalWidgetManager.open({
929
- created: new Date().toString(),
930
- id: this.getTerminalWidgetId(terminalId),
931
- title: taskInfo
932
- ? `Task: ${taskInfo.config.label}`
933
- : `Task: #${taskId}`,
934
- destroyTermOnClose: true,
935
- useServerTitle: false
936
- }, {
937
- widgetOptions: { area: 'bottom' },
938
- mode: widgetOpenMode,
939
- taskInfo
940
- });
941
- return widget.start(terminalId);
942
- }
943
- getTerminalWidgetId(terminalId) {
944
- const terminalWidget = this.terminalService.getByTerminalId(terminalId);
945
- if (terminalWidget) {
946
- return terminalWidget.id;
947
- }
948
- }
949
- /**
950
- * Opens an editor to configure the given task.
951
- *
952
- * @param token The cache token for the user interaction in progress
953
- * @param task The task to configure
954
- */
955
- async configure(token, task) {
956
- Object.assign(task, { label: this.taskNameResolver.resolve(task) });
957
- await this.taskConfigurations.configure(token, task);
958
- }
959
- isEventForThisClient(context) {
960
- if (context === this.getContext()) {
961
- return true;
962
- }
963
- return false;
964
- }
965
- taskConfigurationChanged(event) {
966
- // do nothing for now
967
- }
968
- getContext() {
969
- var _a;
970
- return (_a = this.workspaceService.workspace) === null || _a === void 0 ? void 0 : _a.resource.toString();
971
- }
972
- /** Kill task for a given id if task is found */
973
- async kill(id) {
974
- try {
975
- await this.taskServer.kill(id);
976
- }
977
- catch (error) {
978
- this.logger.error(`Error killing task '${id}': ${error}`);
979
- this.messageService.error(`Error killing task '${id}': ${error}`);
980
- return;
981
- }
982
- this.logger.debug(`Task killed. Task id: ${id}`);
983
- }
984
- async isBackgroundTaskEnded(id) {
985
- const completedTask = this.runningTasks.get(id);
986
- return completedTask && completedTask.isBackgroundTaskEnded.promise;
987
- }
988
- async getExitCode(id) {
989
- const completedTask = this.runningTasks.get(id);
990
- return completedTask && completedTask.exitCode.promise;
991
- }
992
- async getTerminateSignal(id) {
993
- const completedTask = this.runningTasks.get(id);
994
- return completedTask && completedTask.terminateSignal.promise;
995
- }
996
- };
997
- __decorate([
998
- (0, inversify_1.inject)(browser_1.FrontendApplication),
999
- __metadata("design:type", browser_1.FrontendApplication)
1000
- ], TaskService.prototype, "app", void 0);
1001
- __decorate([
1002
- (0, inversify_1.inject)(browser_1.ApplicationShell),
1003
- __metadata("design:type", browser_1.ApplicationShell)
1004
- ], TaskService.prototype, "shell", void 0);
1005
- __decorate([
1006
- (0, inversify_1.inject)(common_2.TaskServer),
1007
- __metadata("design:type", Object)
1008
- ], TaskService.prototype, "taskServer", void 0);
1009
- __decorate([
1010
- (0, inversify_1.inject)(common_1.ILogger),
1011
- (0, inversify_1.named)('task'),
1012
- __metadata("design:type", Object)
1013
- ], TaskService.prototype, "logger", void 0);
1014
- __decorate([
1015
- (0, inversify_1.inject)(browser_1.WidgetManager),
1016
- __metadata("design:type", browser_1.WidgetManager)
1017
- ], TaskService.prototype, "widgetManager", void 0);
1018
- __decorate([
1019
- (0, inversify_1.inject)(task_watcher_1.TaskWatcher),
1020
- __metadata("design:type", task_watcher_1.TaskWatcher)
1021
- ], TaskService.prototype, "taskWatcher", void 0);
1022
- __decorate([
1023
- (0, inversify_1.inject)(message_service_1.MessageService),
1024
- __metadata("design:type", message_service_1.MessageService)
1025
- ], TaskService.prototype, "messageService", void 0);
1026
- __decorate([
1027
- (0, inversify_1.inject)(workspace_service_1.WorkspaceService),
1028
- __metadata("design:type", workspace_service_1.WorkspaceService)
1029
- ], TaskService.prototype, "workspaceService", void 0);
1030
- __decorate([
1031
- (0, inversify_1.inject)(task_configurations_1.TaskConfigurations),
1032
- __metadata("design:type", task_configurations_1.TaskConfigurations)
1033
- ], TaskService.prototype, "taskConfigurations", void 0);
1034
- __decorate([
1035
- (0, inversify_1.inject)(provided_task_configurations_1.ProvidedTaskConfigurations),
1036
- __metadata("design:type", provided_task_configurations_1.ProvidedTaskConfigurations)
1037
- ], TaskService.prototype, "providedTaskConfigurations", void 0);
1038
- __decorate([
1039
- (0, inversify_1.inject)(browser_3.VariableResolverService),
1040
- __metadata("design:type", browser_3.VariableResolverService)
1041
- ], TaskService.prototype, "variableResolverService", void 0);
1042
- __decorate([
1043
- (0, inversify_1.inject)(task_contribution_1.TaskResolverRegistry),
1044
- __metadata("design:type", task_contribution_1.TaskResolverRegistry)
1045
- ], TaskService.prototype, "taskResolverRegistry", void 0);
1046
- __decorate([
1047
- (0, inversify_1.inject)(terminal_service_1.TerminalService),
1048
- __metadata("design:type", Object)
1049
- ], TaskService.prototype, "terminalService", void 0);
1050
- __decorate([
1051
- (0, inversify_1.inject)(browser_2.EditorManager),
1052
- __metadata("design:type", browser_2.EditorManager)
1053
- ], TaskService.prototype, "editorManager", void 0);
1054
- __decorate([
1055
- (0, inversify_1.inject)(problem_manager_1.ProblemManager),
1056
- __metadata("design:type", problem_manager_1.ProblemManager)
1057
- ], TaskService.prototype, "problemManager", void 0);
1058
- __decorate([
1059
- (0, inversify_1.inject)(task_definition_registry_1.TaskDefinitionRegistry),
1060
- __metadata("design:type", task_definition_registry_1.TaskDefinitionRegistry)
1061
- ], TaskService.prototype, "taskDefinitionRegistry", void 0);
1062
- __decorate([
1063
- (0, inversify_1.inject)(task_problem_matcher_registry_1.ProblemMatcherRegistry),
1064
- __metadata("design:type", task_problem_matcher_registry_1.ProblemMatcherRegistry)
1065
- ], TaskService.prototype, "problemMatcherRegistry", void 0);
1066
- __decorate([
1067
- (0, inversify_1.inject)(quick_pick_service_1.QuickPickService),
1068
- __metadata("design:type", Object)
1069
- ], TaskService.prototype, "quickPickService", void 0);
1070
- __decorate([
1071
- (0, inversify_1.inject)(opener_service_1.OpenerService),
1072
- __metadata("design:type", Object)
1073
- ], TaskService.prototype, "openerService", void 0);
1074
- __decorate([
1075
- (0, inversify_1.inject)(shell_terminal_protocol_1.ShellTerminalServerProxy),
1076
- __metadata("design:type", Object)
1077
- ], TaskService.prototype, "shellTerminalServer", void 0);
1078
- __decorate([
1079
- (0, inversify_1.inject)(task_name_resolver_1.TaskNameResolver),
1080
- __metadata("design:type", task_name_resolver_1.TaskNameResolver)
1081
- ], TaskService.prototype, "taskNameResolver", void 0);
1082
- __decorate([
1083
- (0, inversify_1.inject)(task_source_resolver_1.TaskSourceResolver),
1084
- __metadata("design:type", task_source_resolver_1.TaskSourceResolver)
1085
- ], TaskService.prototype, "taskSourceResolver", void 0);
1086
- __decorate([
1087
- (0, inversify_1.inject)(task_schema_updater_1.TaskSchemaUpdater),
1088
- __metadata("design:type", task_schema_updater_1.TaskSchemaUpdater)
1089
- ], TaskService.prototype, "taskSchemaUpdater", void 0);
1090
- __decorate([
1091
- (0, inversify_1.inject)(task_configuration_manager_1.TaskConfigurationManager),
1092
- __metadata("design:type", task_configuration_manager_1.TaskConfigurationManager)
1093
- ], TaskService.prototype, "taskConfigurationManager", void 0);
1094
- __decorate([
1095
- (0, inversify_1.inject)(common_1.CommandService),
1096
- __metadata("design:type", Object)
1097
- ], TaskService.prototype, "commands", void 0);
1098
- __decorate([
1099
- (0, inversify_1.inject)(label_provider_1.LabelProvider),
1100
- __metadata("design:type", label_provider_1.LabelProvider)
1101
- ], TaskService.prototype, "labelProvider", void 0);
1102
- __decorate([
1103
- (0, inversify_1.inject)(monaco_workspace_1.MonacoWorkspace),
1104
- __metadata("design:type", monaco_workspace_1.MonacoWorkspace)
1105
- ], TaskService.prototype, "monacoWorkspace", void 0);
1106
- __decorate([
1107
- (0, inversify_1.inject)(task_terminal_widget_manager_1.TaskTerminalWidgetManager),
1108
- __metadata("design:type", task_terminal_widget_manager_1.TaskTerminalWidgetManager)
1109
- ], TaskService.prototype, "taskTerminalWidgetManager", void 0);
1110
- __decorate([
1111
- (0, inversify_1.postConstruct)(),
1112
- __metadata("design:type", Function),
1113
- __metadata("design:paramtypes", []),
1114
- __metadata("design:returntype", void 0)
1115
- ], TaskService.prototype, "init", null);
1116
- TaskService = __decorate([
1117
- (0, inversify_1.injectable)()
1118
- ], TaskService);
1119
- exports.TaskService = TaskService;
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2017 Ericsson and others.
4
+ //
5
+ // This program and the accompanying materials are made available under the
6
+ // terms of the Eclipse Public License v. 2.0 which is available at
7
+ // http://www.eclipse.org/legal/epl-2.0.
8
+ //
9
+ // This Source Code may also be made available under the following Secondary
10
+ // Licenses when the conditions for such availability set forth in the Eclipse
11
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ // with the GNU Classpath Exception which is available at
13
+ // https://www.gnu.org/software/classpath/license.html.
14
+ //
15
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ // *****************************************************************************
17
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
18
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
22
+ };
23
+ var __metadata = (this && this.__metadata) || function (k, v) {
24
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
25
+ };
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ exports.TaskService = exports.TaskEndedTypes = void 0;
28
+ const browser_1 = require("@theia/core/lib/browser");
29
+ const opener_service_1 = require("@theia/core/lib/browser/opener-service");
30
+ const common_1 = require("@theia/core/lib/common");
31
+ const message_service_1 = require("@theia/core/lib/common/message-service");
32
+ const promise_util_1 = require("@theia/core/lib/common/promise-util");
33
+ const quick_pick_service_1 = require("@theia/core/lib/common/quick-pick-service");
34
+ const label_provider_1 = require("@theia/core/lib/browser/label-provider");
35
+ const uri_1 = require("@theia/core/lib/common/uri");
36
+ const browser_2 = require("@theia/editor/lib/browser");
37
+ const problem_manager_1 = require("@theia/markers/lib/browser/problem/problem-manager");
38
+ const terminal_service_1 = require("@theia/terminal/lib/browser/base/terminal-service");
39
+ const browser_3 = require("@theia/variable-resolver/lib/browser");
40
+ const workspace_service_1 = require("@theia/workspace/lib/browser/workspace-service");
41
+ const inversify_1 = require("@theia/core/shared/inversify");
42
+ const vscode_languageserver_protocol_1 = require("@theia/core/shared/vscode-languageserver-protocol");
43
+ const common_2 = require("../common");
44
+ const task_watcher_1 = require("../common/task-watcher");
45
+ const provided_task_configurations_1 = require("./provided-task-configurations");
46
+ const task_configurations_1 = require("./task-configurations");
47
+ const task_contribution_1 = require("./task-contribution");
48
+ const task_definition_registry_1 = require("./task-definition-registry");
49
+ const task_name_resolver_1 = require("./task-name-resolver");
50
+ const task_source_resolver_1 = require("./task-source-resolver");
51
+ const task_problem_matcher_registry_1 = require("./task-problem-matcher-registry");
52
+ const task_schema_updater_1 = require("./task-schema-updater");
53
+ const task_configuration_manager_1 = require("./task-configuration-manager");
54
+ const problem_widget_1 = require("@theia/markers/lib/browser/problem/problem-widget");
55
+ const task_node_1 = require("./task-node");
56
+ const monaco_workspace_1 = require("@theia/monaco/lib/browser/monaco-workspace");
57
+ const task_terminal_widget_manager_1 = require("./task-terminal-widget-manager");
58
+ const shell_terminal_protocol_1 = require("@theia/terminal/lib/common/shell-terminal-protocol");
59
+ const async_mutex_1 = require("async-mutex");
60
+ var TaskEndedTypes;
61
+ (function (TaskEndedTypes) {
62
+ TaskEndedTypes[TaskEndedTypes["TaskExited"] = 0] = "TaskExited";
63
+ TaskEndedTypes[TaskEndedTypes["BackgroundTaskEnded"] = 1] = "BackgroundTaskEnded";
64
+ })(TaskEndedTypes = exports.TaskEndedTypes || (exports.TaskEndedTypes = {}));
65
+ let TaskService = class TaskService {
66
+ constructor() {
67
+ /**
68
+ * The last executed task.
69
+ */
70
+ this.lastTask = { resolvedTask: undefined, option: undefined };
71
+ this.cachedRecentTasks = [];
72
+ this.runningTasks = new Map();
73
+ this.taskStartingLock = new async_mutex_1.Mutex();
74
+ }
75
+ init() {
76
+ this.getRunningTasks().then(tasks => tasks.forEach(task => {
77
+ if (!this.runningTasks.has(task.taskId)) {
78
+ this.runningTasks.set(task.taskId, {
79
+ exitCode: new promise_util_1.Deferred(), terminateSignal: new promise_util_1.Deferred(),
80
+ isBackgroundTaskEnded: new promise_util_1.Deferred()
81
+ });
82
+ }
83
+ }));
84
+ // notify user that task has started
85
+ this.taskWatcher.onTaskCreated((event) => {
86
+ if (!this.isEventForThisClient(event.ctx)) {
87
+ return;
88
+ }
89
+ this.runningTasks.set(event.taskId, {
90
+ exitCode: new promise_util_1.Deferred(),
91
+ terminateSignal: new promise_util_1.Deferred(),
92
+ isBackgroundTaskEnded: new promise_util_1.Deferred()
93
+ });
94
+ });
95
+ this.taskWatcher.onOutputProcessed(async (event) => {
96
+ if (!this.isEventForThisClient(event.ctx)) {
97
+ return;
98
+ }
99
+ if (event.problems) {
100
+ const runningTasksInfo = await this.getRunningTasks();
101
+ // check if the task is active
102
+ const matchedRunningTaskInfo = runningTasksInfo.find(taskInfo => {
103
+ const taskConfig = taskInfo.config;
104
+ return this.taskDefinitionRegistry.compareTasks(taskConfig, event.config);
105
+ });
106
+ const isTaskActiveAndOutputSilent = matchedRunningTaskInfo &&
107
+ matchedRunningTaskInfo.config.presentation && matchedRunningTaskInfo.config.presentation.reveal === common_2.RevealKind.Silent;
108
+ event.problems.forEach(problem => {
109
+ const existingMarkers = this.problemManager.findMarkers({ owner: problem.description.owner });
110
+ const uris = new Set();
111
+ existingMarkers.forEach(marker => uris.add(marker.uri));
112
+ if (common_2.ProblemMatchData.is(problem) && problem.resource) {
113
+ // When task.presentation.reveal === RevealKind.Silent, put focus on the terminal only if it is an error
114
+ if (isTaskActiveAndOutputSilent && problem.marker.severity === vscode_languageserver_protocol_1.DiagnosticSeverity.Error) {
115
+ const terminalId = matchedRunningTaskInfo.terminalId;
116
+ if (terminalId) {
117
+ const terminal = this.terminalService.getByTerminalId(terminalId);
118
+ if (terminal) {
119
+ const focus = !!matchedRunningTaskInfo.config.presentation.focus;
120
+ if (focus) { // assign focus to the terminal if presentation.focus is true
121
+ this.terminalService.open(terminal, { mode: 'activate' });
122
+ }
123
+ else { // show the terminal but not assign focus
124
+ this.terminalService.open(terminal, { mode: 'reveal' });
125
+ }
126
+ }
127
+ }
128
+ }
129
+ const uri = problem.resource.withScheme(problem.resource.scheme);
130
+ const document = this.monacoWorkspace.getTextDocument(uri.toString());
131
+ if (problem.description.applyTo === common_2.ApplyToKind.openDocuments && !!document ||
132
+ problem.description.applyTo === common_2.ApplyToKind.closedDocuments && !document ||
133
+ problem.description.applyTo === common_2.ApplyToKind.allDocuments) {
134
+ if (uris.has(uri.toString())) {
135
+ const newData = [
136
+ ...existingMarkers
137
+ .filter(marker => marker.uri === uri.toString())
138
+ .map(markerData => markerData.data),
139
+ problem.marker
140
+ ];
141
+ this.problemManager.setMarkers(uri, problem.description.owner, newData);
142
+ }
143
+ else {
144
+ this.problemManager.setMarkers(uri, problem.description.owner, [problem.marker]);
145
+ }
146
+ }
147
+ }
148
+ else { // should have received an event for finding the "background task begins" pattern
149
+ uris.forEach(uriString => this.problemManager.setMarkers(new uri_1.default(uriString), problem.description.owner, []));
150
+ }
151
+ });
152
+ }
153
+ });
154
+ this.taskWatcher.onBackgroundTaskEnded((event) => {
155
+ if (!this.isEventForThisClient(event.ctx)) {
156
+ return;
157
+ }
158
+ if (!this.runningTasks.has(event.taskId)) {
159
+ this.runningTasks.set(event.taskId, {
160
+ exitCode: new promise_util_1.Deferred(),
161
+ terminateSignal: new promise_util_1.Deferred(),
162
+ isBackgroundTaskEnded: new promise_util_1.Deferred()
163
+ });
164
+ }
165
+ this.runningTasks.get(event.taskId).isBackgroundTaskEnded.resolve(true);
166
+ });
167
+ // notify user that task has finished
168
+ this.taskWatcher.onTaskExit((event) => {
169
+ if (!this.isEventForThisClient(event.ctx)) {
170
+ return;
171
+ }
172
+ if (!this.runningTasks.has(event.taskId)) {
173
+ this.runningTasks.set(event.taskId, {
174
+ exitCode: new promise_util_1.Deferred(),
175
+ terminateSignal: new promise_util_1.Deferred(),
176
+ isBackgroundTaskEnded: new promise_util_1.Deferred()
177
+ });
178
+ }
179
+ this.runningTasks.get(event.taskId).exitCode.resolve(event.code);
180
+ this.runningTasks.get(event.taskId).terminateSignal.resolve(event.signal);
181
+ setTimeout(() => this.runningTasks.delete(event.taskId), 60 * 1000);
182
+ const taskConfig = event.config;
183
+ const taskIdentifier = taskConfig ? this.getTaskIdentifier(taskConfig) : event.taskId.toString();
184
+ if (event.code !== undefined) {
185
+ if (event.code !== 0) {
186
+ const eventTaskConfig = event.config;
187
+ if (eventTaskConfig && eventTaskConfig.presentation && eventTaskConfig.presentation.reveal === common_2.RevealKind.Silent && event.terminalId) {
188
+ const terminal = this.terminalService.getByTerminalId(event.terminalId);
189
+ const focus = !!eventTaskConfig.presentation.focus;
190
+ if (terminal) {
191
+ if (focus) { // assign focus to the terminal if presentation.focus is true
192
+ this.terminalService.open(terminal, { mode: 'activate' });
193
+ }
194
+ else { // show the terminal but not assign focus
195
+ this.terminalService.open(terminal, { mode: 'reveal' });
196
+ }
197
+ }
198
+ }
199
+ this.messageService.error(`Task '${taskIdentifier}' has exited with code ${event.code}.`);
200
+ }
201
+ }
202
+ else if (event.signal !== undefined) {
203
+ this.messageService.info(`Task '${taskIdentifier}' was terminated by signal ${event.signal}.`);
204
+ }
205
+ else {
206
+ console.error('Invalid TaskExitedEvent received, neither code nor signal is set.');
207
+ }
208
+ });
209
+ }
210
+ getTaskIdentifier(taskConfig) {
211
+ const taskName = this.taskNameResolver.resolve(taskConfig);
212
+ const sourceStrUri = this.taskSourceResolver.resolve(taskConfig);
213
+ return `${taskName} (${this.labelProvider.getName(new uri_1.default(sourceStrUri))})`;
214
+ }
215
+ /**
216
+ * Client should call this method to indicate that a new user-level action related to tasks has been started,
217
+ * like invoking "Run Task..."
218
+ * This method returns a token that can be used with various methods in this service.
219
+ * As long as a client uses the same token, task providers will only asked once to contribute
220
+ * tasks and the set of tasks will be cached. Each time the a new token is used, the cache of
221
+ * contributed tasks is cleared.
222
+ * @returns a token to be used for task-related actions
223
+ */
224
+ startUserAction() {
225
+ return this.providedTaskConfigurations.startUserAction();
226
+ }
227
+ /**
228
+ * Returns an array of the task configurations configured in tasks.json and provided by the extensions.
229
+ * @param token The cache token for the user interaction in progress
230
+ */
231
+ async getTasks(token) {
232
+ const configuredTasks = await this.getConfiguredTasks(token);
233
+ const providedTasks = await this.getProvidedTasks(token);
234
+ const notCustomizedProvidedTasks = providedTasks.filter(provided => !configuredTasks.some(configured => this.taskDefinitionRegistry.compareTasks(configured, provided)));
235
+ return [...configuredTasks, ...notCustomizedProvidedTasks];
236
+ }
237
+ /**
238
+ * Returns an array of the valid task configurations which are configured in tasks.json files
239
+ * @param token The cache token for the user interaction in progress
240
+ *
241
+ */
242
+ async getConfiguredTasks(token) {
243
+ const invalidTaskConfig = this.taskConfigurations.getInvalidTaskConfigurations()[0];
244
+ if (invalidTaskConfig) {
245
+ const widget = await this.widgetManager.getOrCreateWidget(problem_widget_1.PROBLEMS_WIDGET_ID);
246
+ const isProblemsWidgetVisible = widget && widget.isVisible;
247
+ const currentEditorUri = this.editorManager.currentEditor && this.editorManager.currentEditor.editor.getResourceUri();
248
+ let isInvalidTaskConfigFileOpen = false;
249
+ if (currentEditorUri) {
250
+ const folderUri = this.workspaceService.getWorkspaceRootUri(currentEditorUri);
251
+ if (folderUri && folderUri.toString() === invalidTaskConfig._scope) {
252
+ isInvalidTaskConfigFileOpen = true;
253
+ }
254
+ }
255
+ const warningMessage = 'Invalid task configurations are found. Open tasks.json and find details in the Problems view.';
256
+ if (!isProblemsWidgetVisible || !isInvalidTaskConfigFileOpen) {
257
+ this.messageService.warn(warningMessage, 'Open').then(actionOpen => {
258
+ if (actionOpen) {
259
+ if (invalidTaskConfig && invalidTaskConfig._scope) {
260
+ this.taskConfigurationManager.openConfiguration(invalidTaskConfig._scope);
261
+ }
262
+ if (!isProblemsWidgetVisible) {
263
+ this.commands.executeCommand('problemsView:toggle');
264
+ }
265
+ }
266
+ });
267
+ }
268
+ else {
269
+ this.messageService.warn(warningMessage);
270
+ }
271
+ }
272
+ const validTaskConfigs = await this.taskConfigurations.getTasks(token);
273
+ return validTaskConfigs;
274
+ }
275
+ /**
276
+ * Returns an array that contains the task configurations provided by the task providers for the specified task type.
277
+ * @param token The cache token for the user interaction in progress
278
+ * @param type The task type (filter) associated to the returning TaskConfigurations
279
+ *
280
+ * '*' indicates all tasks regardless of the type
281
+ */
282
+ getProvidedTasks(token, type) {
283
+ return this.providedTaskConfigurations.getTasks(token, type);
284
+ }
285
+ addRecentTasks(tasks) {
286
+ if (Array.isArray(tasks)) {
287
+ tasks.forEach(task => this.addRecentTasks(task));
288
+ }
289
+ else {
290
+ const ind = this.cachedRecentTasks.findIndex(recent => this.taskDefinitionRegistry.compareTasks(recent, tasks));
291
+ if (ind >= 0) {
292
+ this.cachedRecentTasks.splice(ind, 1);
293
+ }
294
+ this.cachedRecentTasks.unshift(tasks);
295
+ }
296
+ }
297
+ get recentTasks() {
298
+ return this.cachedRecentTasks;
299
+ }
300
+ set recentTasks(recent) {
301
+ this.cachedRecentTasks = recent;
302
+ }
303
+ /**
304
+ * Clears the list of recently used tasks.
305
+ */
306
+ clearRecentTasks() {
307
+ this.cachedRecentTasks = [];
308
+ }
309
+ /**
310
+ * Open user ser
311
+ */
312
+ openUserTasks() {
313
+ return this.taskConfigurations.openUserTasks();
314
+ }
315
+ /**
316
+ * Returns a task configuration provided by an extension by task source, scope and label.
317
+ * If there are no task configuration, returns undefined.
318
+ * @param token The cache token for the user interaction in progress
319
+ * @param source The source for configured tasks
320
+ * @param label The label of the task to find
321
+ * @param scope The task scope to look in
322
+ */
323
+ async getProvidedTask(token, source, label, scope) {
324
+ return this.providedTaskConfigurations.getTask(token, source, label, scope);
325
+ }
326
+ /** Returns an array of running tasks 'TaskInfo' objects */
327
+ getRunningTasks() {
328
+ return this.taskServer.getTasks(this.getContext());
329
+ }
330
+ async customExecutionComplete(id, exitCode) {
331
+ return this.taskServer.customExecutionComplete(id, exitCode);
332
+ }
333
+ /** Returns an array of task types that are registered, including the default types */
334
+ getRegisteredTaskTypes() {
335
+ return this.taskSchemaUpdater.getRegisteredTaskTypes();
336
+ }
337
+ /**
338
+ * Get the last executed task.
339
+ *
340
+ * @returns the last executed task or `undefined`.
341
+ */
342
+ getLastTask() {
343
+ return this.lastTask;
344
+ }
345
+ /**
346
+ * Runs a task, by task configuration label.
347
+ * Note, it looks for a task configured in tasks.json only.
348
+ * @param token The cache token for the user interaction in progress
349
+ * @param scope The scope where to look for tasks
350
+ * @param taskLabel the label to look for
351
+ */
352
+ async runConfiguredTask(token, scope, taskLabel) {
353
+ const task = this.taskConfigurations.getTask(scope, taskLabel);
354
+ if (!task) {
355
+ this.logger.error(`Can't get task launch configuration for label: ${taskLabel}`);
356
+ return;
357
+ }
358
+ this.run(token, task._source, taskLabel, scope);
359
+ }
360
+ /**
361
+ * Run the last executed task.
362
+ * @param token The cache token for the user interaction in progress
363
+ */
364
+ async runLastTask(token) {
365
+ var _a, _b;
366
+ if (!((_a = this.lastTask) === null || _a === void 0 ? void 0 : _a.resolvedTask)) {
367
+ return;
368
+ }
369
+ if (!((_b = this.lastTask.resolvedTask.runOptions) === null || _b === void 0 ? void 0 : _b.reevaluateOnRerun)) {
370
+ return this.runResolvedTask(this.lastTask.resolvedTask, this.lastTask.option);
371
+ }
372
+ const { _source, label, _scope } = this.lastTask.resolvedTask;
373
+ return this.run(token, _source, label, _scope);
374
+ }
375
+ /**
376
+ * Runs a task, by the source and label of the task configuration.
377
+ * It looks for configured and detected tasks.
378
+ * @param token The cache token for the user interaction in progress
379
+ * @param source The source for configured tasks
380
+ * @param taskLabel The label to look for
381
+ * @param scope The scope where to look for tasks
382
+ */
383
+ async run(token, source, taskLabel, scope) {
384
+ var _a, _b;
385
+ let task;
386
+ task = this.taskConfigurations.getTask(scope, taskLabel);
387
+ if (!task) { // if a configured task cannot be found, search from detected tasks
388
+ task = await this.getProvidedTask(token, source, taskLabel, scope);
389
+ if (!task) { // find from the customized detected tasks
390
+ task = await this.taskConfigurations.getCustomizedTask(token, scope, taskLabel);
391
+ }
392
+ if (!task) {
393
+ this.logger.error(`Can't get task launch configuration for label: ${taskLabel}`);
394
+ return;
395
+ }
396
+ }
397
+ const customizationObject = await this.getTaskCustomization(task);
398
+ if (!customizationObject.problemMatcher) {
399
+ // ask the user what s/he wants to use to parse the task output
400
+ const items = this.getCustomizeProblemMatcherItems();
401
+ const selected = await this.quickPickService.show(items, {
402
+ placeholder: 'Select for which kind of errors and warnings to scan the task output'
403
+ });
404
+ if (selected && ('value' in selected)) {
405
+ if ((_a = selected.value) === null || _a === void 0 ? void 0 : _a.problemMatchers) {
406
+ let matcherNames = [];
407
+ if (selected.value.problemMatchers && selected.value.problemMatchers.length === 0) { // never parse output for this task
408
+ matcherNames = [];
409
+ }
410
+ else if (selected.value.problemMatchers && selected.value.problemMatchers.length > 0) { // continue with user-selected parser
411
+ matcherNames = selected.value.problemMatchers.map(matcher => matcher.name);
412
+ }
413
+ customizationObject.problemMatcher = matcherNames;
414
+ // write the selected matcher (or the decision of "never parse") into the `tasks.json`
415
+ this.updateTaskConfiguration(token, task, { problemMatcher: matcherNames });
416
+ }
417
+ else if ((_b = selected.value) === null || _b === void 0 ? void 0 : _b.learnMore) { // user wants to learn more about parsing task output
418
+ (0, opener_service_1.open)(this.openerService, new uri_1.default('https://code.visualstudio.com/docs/editor/tasks#_processing-task-output-with-problem-matchers'));
419
+ }
420
+ // else, continue the task with no parser
421
+ }
422
+ else { // do not start the task in case that the user did not select any item from the list
423
+ return;
424
+ }
425
+ }
426
+ const resolvedMatchers = await this.resolveProblemMatchers(task, customizationObject);
427
+ const runTaskOption = {
428
+ customization: { ...customizationObject, ...{ problemMatcher: resolvedMatchers } }
429
+ };
430
+ if (task.dependsOn) {
431
+ return this.runCompoundTask(token, task, runTaskOption);
432
+ }
433
+ else {
434
+ return this.runTask(task, runTaskOption).catch(error => {
435
+ console.error('Error at launching task', error);
436
+ return undefined;
437
+ });
438
+ }
439
+ }
440
+ /**
441
+ * Runs a compound task
442
+ * @param token The cache token for the user interaction in progress
443
+ * @param task The task to be executed
444
+ * @param option options for executing the task
445
+ */
446
+ async runCompoundTask(token, task, option) {
447
+ const tasks = await this.getWorkspaceTasks(token, task._scope);
448
+ try {
449
+ const rootNode = new task_node_1.TaskNode(task, [], []);
450
+ this.detectDirectedAcyclicGraph(task, rootNode, tasks);
451
+ }
452
+ catch (error) {
453
+ console.error(`Error at launching task '${task.label}'`, error);
454
+ this.messageService.error(error.message);
455
+ return undefined;
456
+ }
457
+ return this.runTasksGraph(task, tasks, option).catch(error => {
458
+ console.error(`Error at launching task '${task.label}'`, error);
459
+ return undefined;
460
+ });
461
+ }
462
+ /**
463
+ * A recursive function that runs a task and all its sub tasks that it depends on.
464
+ * A task can be executed only when all of its dependencies have been executed, or when it doesn’t have any dependencies at all.
465
+ */
466
+ async runTasksGraph(task, tasks, option) {
467
+ if (task && task.dependsOn) {
468
+ // In case it is an array of task dependencies
469
+ if (Array.isArray(task.dependsOn) && task.dependsOn.length > 0) {
470
+ const dependentTasks = [];
471
+ for (let i = 0; i < task.dependsOn.length; i++) {
472
+ // It may be a string (a task label) or a JSON object which represents a TaskIdentifier (e.g. {"type":"npm", "script":"script1"})
473
+ const taskIdentifier = task.dependsOn[i];
474
+ const dependentTask = this.getDependentTask(taskIdentifier, tasks);
475
+ const taskCustomization = await this.getTaskCustomization(dependentTask);
476
+ const resolvedMatchers = await this.resolveProblemMatchers(dependentTask, taskCustomization);
477
+ dependentTasks.push({ 'task': dependentTask, 'taskCustomization': taskCustomization, 'resolvedMatchers': resolvedMatchers });
478
+ // In case the 'dependsOrder' is 'sequence'
479
+ if (task.dependsOrder && task.dependsOrder === common_2.DependsOrder.Sequence) {
480
+ await this.runTasksGraph(dependentTask, tasks, {
481
+ customization: { ...taskCustomization, ...{ problemMatcher: resolvedMatchers } }
482
+ });
483
+ }
484
+ }
485
+ // In case the 'dependsOrder' is 'parallel'
486
+ if (((!task.dependsOrder) || (task.dependsOrder && task.dependsOrder === common_2.DependsOrder.Parallel))) {
487
+ const promises = dependentTasks.map(item => this.runTasksGraph(item.task, tasks, {
488
+ customization: { ...item.taskCustomization, ...{ problemMatcher: item.resolvedMatchers } }
489
+ }));
490
+ await Promise.all(promises);
491
+ }
492
+ }
493
+ else if (!Array.isArray(task.dependsOn)) {
494
+ // In case it is a string (a task label) or a JSON object which represents a TaskIdentifier (e.g. {"type":"npm", "script":"script1"})
495
+ const taskIdentifier = task.dependsOn;
496
+ const dependentTask = this.getDependentTask(taskIdentifier, tasks);
497
+ const taskCustomization = await this.getTaskCustomization(dependentTask);
498
+ const resolvedMatchers = await this.resolveProblemMatchers(dependentTask, taskCustomization);
499
+ await this.runTasksGraph(dependentTask, tasks, {
500
+ customization: { ...taskCustomization, ...{ problemMatcher: resolvedMatchers } }
501
+ });
502
+ }
503
+ }
504
+ const taskInfo = await this.runTask(task, option);
505
+ if (taskInfo) {
506
+ const getExitCodePromise = this.getExitCode(taskInfo.taskId).then(result => ({ taskEndedType: TaskEndedTypes.TaskExited, value: result }));
507
+ const isBackgroundTaskEndedPromise = this.isBackgroundTaskEnded(taskInfo.taskId).then(result => ({ taskEndedType: TaskEndedTypes.BackgroundTaskEnded, value: result }));
508
+ // After start running the task, we wait for the task process to exit and if it is a background task, we also wait for a feedback
509
+ // that a background task is active, as soon as one of the promises fulfills, we can continue and analyze the results.
510
+ const taskEndedInfo = await Promise.race([getExitCodePromise, isBackgroundTaskEndedPromise]);
511
+ if ((taskEndedInfo.taskEndedType === TaskEndedTypes.TaskExited && taskEndedInfo.value !== 0) ||
512
+ (taskEndedInfo.taskEndedType === TaskEndedTypes.BackgroundTaskEnded && !taskEndedInfo.value)) {
513
+ throw new Error('The task: ' + task.label + ' terminated with exit code ' + taskEndedInfo.value + '.');
514
+ }
515
+ }
516
+ return taskInfo;
517
+ }
518
+ /**
519
+ * Creates a graph of dependencies tasks from the root task and verify there is no DAG (Directed Acyclic Graph).
520
+ * In case of detection of a circular dependency, an error is thrown with a message which describes the detected circular reference.
521
+ */
522
+ detectDirectedAcyclicGraph(task, taskNode, tasks) {
523
+ if (task && task.dependsOn) {
524
+ // In case the 'dependsOn' is an array
525
+ if (Array.isArray(task.dependsOn) && task.dependsOn.length > 0) {
526
+ for (let i = 0; i < task.dependsOn.length; i++) {
527
+ const childNode = this.createChildTaskNode(task, taskNode, task.dependsOn[i], tasks);
528
+ this.detectDirectedAcyclicGraph(childNode.taskConfiguration, childNode.node, tasks);
529
+ }
530
+ }
531
+ else if (!Array.isArray(task.dependsOn)) {
532
+ const childNode = this.createChildTaskNode(task, taskNode, task.dependsOn, tasks);
533
+ this.detectDirectedAcyclicGraph(childNode.taskConfiguration, childNode.node, tasks);
534
+ }
535
+ }
536
+ }
537
+ // 'childTaskIdentifier' may be a string (a task label) or a JSON object which represents a TaskIdentifier (e.g. {"type":"npm", "script":"script1"})
538
+ createChildTaskNode(task, taskNode, childTaskIdentifier, tasks) {
539
+ const childTaskConfiguration = this.getDependentTask(childTaskIdentifier, tasks);
540
+ // If current task and child task are identical or if
541
+ // one of the child tasks is identical to one of the current task ancestors, then raise an error
542
+ if (this.taskDefinitionRegistry.compareTasks(task, childTaskConfiguration) ||
543
+ taskNode.parentsID.filter(t => this.taskDefinitionRegistry.compareTasks(childTaskConfiguration, t)).length > 0) {
544
+ const fromNode = task.label;
545
+ const toNode = childTaskConfiguration.label;
546
+ throw new Error('Circular reference detected: ' + fromNode + ' --> ' + toNode);
547
+ }
548
+ const childNode = new task_node_1.TaskNode(childTaskConfiguration, [], Object.assign([], taskNode.parentsID));
549
+ childNode.addParentDependency(taskNode.taskId);
550
+ taskNode.addChildDependency(childNode);
551
+ return { 'taskConfiguration': childTaskConfiguration, 'node': childNode };
552
+ }
553
+ /**
554
+ * Gets task configuration by task label or by a JSON object which represents a task identifier
555
+ *
556
+ * @param taskIdentifier The task label (string) or a JSON object which represents a TaskIdentifier (e.g. {"type":"npm", "script":"script1"})
557
+ * @param tasks an array of the task configurations
558
+ * @returns the correct TaskConfiguration object which matches the taskIdentifier
559
+ */
560
+ getDependentTask(taskIdentifier, tasks) {
561
+ const notEnoughDataError = 'The information provided in the "dependsOn" is not enough for matching the correct task !';
562
+ let currentTaskChildConfiguration;
563
+ if (typeof (taskIdentifier) !== 'string') {
564
+ // TaskIdentifier object does not support tasks of type 'shell' (The same behavior as in VS Code).
565
+ // So if we want the 'dependsOn' property to include tasks of type 'shell',
566
+ // then we must mention their labels (in the 'dependsOn' property) and not to create a task identifier object for them.
567
+ currentTaskChildConfiguration = this.getTaskByTaskIdentifier(taskIdentifier, tasks);
568
+ if (!currentTaskChildConfiguration.type) {
569
+ this.messageService.error(notEnoughDataError);
570
+ throw new Error(notEnoughDataError);
571
+ }
572
+ return currentTaskChildConfiguration;
573
+ }
574
+ else {
575
+ currentTaskChildConfiguration = tasks.filter(t => taskIdentifier === this.taskNameResolver.resolve(t))[0];
576
+ return currentTaskChildConfiguration;
577
+ }
578
+ }
579
+ /**
580
+ * Gets the matched task from an array of task configurations by TaskIdentifier.
581
+ * In case that more than one task configuration matches, we returns the first one.
582
+ *
583
+ * @param taskIdentifier The task label (string) or a JSON object which represents a TaskIdentifier (e.g. {"type":"npm", "script":"script1"})
584
+ * @param tasks An array of task configurations.
585
+ * @returns The correct TaskConfiguration object which matches the taskIdentifier.
586
+ */
587
+ getTaskByTaskIdentifier(taskIdentifier, tasks) {
588
+ const requiredProperties = Object.keys(taskIdentifier);
589
+ const taskWithAllProperties = tasks.find(task => requiredProperties.every(property => task.hasOwnProperty(property) && task[property] === taskIdentifier[property]));
590
+ return taskWithAllProperties !== null && taskWithAllProperties !== void 0 ? taskWithAllProperties : { label: '', _scope: '', type: '' }; // Fall back to empty TaskConfiguration
591
+ }
592
+ async runTask(task, option) {
593
+ console.debug('entering runTask');
594
+ const releaseLock = await this.taskStartingLock.acquire();
595
+ console.debug('got lock');
596
+ try {
597
+ // resolve problemMatchers
598
+ if (!option && task.problemMatcher) {
599
+ const customizationObject = { type: task.taskType, problemMatcher: task.problemMatcher, runOptions: task.runOptions };
600
+ const resolvedMatchers = await this.resolveProblemMatchers(task, customizationObject);
601
+ option = {
602
+ customization: { ...customizationObject, ...{ problemMatcher: resolvedMatchers } }
603
+ };
604
+ }
605
+ const runningTasksInfo = await this.getRunningTasks();
606
+ // check if the task is active
607
+ const matchedRunningTaskInfo = runningTasksInfo.find(taskInfo => {
608
+ const taskConfig = taskInfo.config;
609
+ return this.taskDefinitionRegistry.compareTasks(taskConfig, task);
610
+ });
611
+ console.debug(`running task ${JSON.stringify(task)}, already running = ${!!matchedRunningTaskInfo}`);
612
+ if (matchedRunningTaskInfo) { // the task is active
613
+ releaseLock();
614
+ console.debug('released lock');
615
+ const taskName = this.taskNameResolver.resolve(task);
616
+ const terminalId = matchedRunningTaskInfo.terminalId;
617
+ if (terminalId) {
618
+ const terminal = this.terminalService.getByTerminalId(terminalId);
619
+ if (terminal) {
620
+ if (common_2.TaskOutputPresentation.shouldSetFocusToTerminal(task)) { // assign focus to the terminal if presentation.focus is true
621
+ this.terminalService.open(terminal, { mode: 'activate' });
622
+ }
623
+ else if (common_2.TaskOutputPresentation.shouldAlwaysRevealTerminal(task)) { // show the terminal but not assign focus
624
+ this.terminalService.open(terminal, { mode: 'reveal' });
625
+ }
626
+ }
627
+ }
628
+ const selectedAction = await this.messageService.info(`The task '${taskName}' is already active`, 'Terminate Task', 'Restart Task');
629
+ if (selectedAction === 'Terminate Task') {
630
+ await this.terminateTask(matchedRunningTaskInfo);
631
+ }
632
+ else if (selectedAction === 'Restart Task') {
633
+ return this.restartTask(matchedRunningTaskInfo, option);
634
+ }
635
+ }
636
+ else { // run task as the task is not active
637
+ console.debug('task about to start');
638
+ const taskInfo = await this.doRunTask(task, option);
639
+ releaseLock();
640
+ console.debug('release lock 2');
641
+ return taskInfo;
642
+ }
643
+ }
644
+ catch (e) {
645
+ releaseLock();
646
+ throw e;
647
+ }
648
+ }
649
+ /**
650
+ * Terminates a task that is actively running.
651
+ * @param activeTaskInfo the TaskInfo of the task that is actively running
652
+ */
653
+ async terminateTask(activeTaskInfo) {
654
+ const taskId = activeTaskInfo.taskId;
655
+ return this.kill(taskId);
656
+ }
657
+ /**
658
+ * Terminates a task that is actively running, and restarts it.
659
+ * @param activeTaskInfo the TaskInfo of the task that is actively running
660
+ */
661
+ async restartTask(activeTaskInfo, option) {
662
+ await this.terminateTask(activeTaskInfo);
663
+ return this.doRunTask(activeTaskInfo.config, option);
664
+ }
665
+ async doRunTask(task, option) {
666
+ let overridePropertiesFunction = () => { };
667
+ if (option && option.customization) {
668
+ const taskDefinition = this.taskDefinitionRegistry.getDefinition(task);
669
+ if (taskDefinition) { // use the customization object to override the task config
670
+ overridePropertiesFunction = tsk => {
671
+ Object.keys(option.customization).forEach(customizedProperty => {
672
+ // properties used to define the task cannot be customized
673
+ if (customizedProperty !== 'type' && !taskDefinition.properties.all.some(pDefinition => pDefinition === customizedProperty)) {
674
+ tsk[customizedProperty] = option.customization[customizedProperty];
675
+ }
676
+ });
677
+ };
678
+ }
679
+ }
680
+ overridePropertiesFunction(task);
681
+ this.addRecentTasks(task);
682
+ try {
683
+ const resolver = await this.taskResolverRegistry.getTaskResolver(task.type);
684
+ const resolvedTask = resolver ? await resolver.resolveTask(task) : task;
685
+ const executionResolver = this.taskResolverRegistry.getExecutionResolver(resolvedTask.taskType || resolvedTask.type);
686
+ overridePropertiesFunction(resolvedTask);
687
+ const taskToRun = executionResolver ? await executionResolver.resolveTask(resolvedTask) : resolvedTask;
688
+ await this.removeProblemMarkers(option);
689
+ return this.runResolvedTask(taskToRun, option);
690
+ }
691
+ catch (error) {
692
+ const errMessage = `Error resolving task '${task.label}': ${error}`;
693
+ this.logger.error(errMessage);
694
+ }
695
+ return undefined;
696
+ }
697
+ /**
698
+ * Runs the first task with the given label.
699
+ *
700
+ * @param token The cache token for the user interaction in progress
701
+ * @param taskLabel The label of the task to be executed
702
+ */
703
+ async runTaskByLabel(token, taskLabel) {
704
+ const tasks = await this.getTasks(token);
705
+ for (const task of tasks) {
706
+ if (task.label === taskLabel) {
707
+ return this.runTask(task);
708
+ }
709
+ }
710
+ return;
711
+ }
712
+ /**
713
+ * Runs a task identified by the given identifier, but only if found in the given workspace folder
714
+ *
715
+ * @param token The cache token for the user interaction in progress
716
+ * @param workspaceFolderUri The folder to restrict the search to
717
+ * @param taskIdentifier The identifier to look for
718
+ */
719
+ async runWorkspaceTask(token, workspaceFolderUri, taskIdentifier) {
720
+ const tasks = await this.getWorkspaceTasks(token, workspaceFolderUri);
721
+ const task = this.getDependentTask(taskIdentifier, tasks);
722
+ if (!task) {
723
+ return undefined;
724
+ }
725
+ const taskCustomization = await this.getTaskCustomization(task);
726
+ const resolvedMatchers = await this.resolveProblemMatchers(task, taskCustomization);
727
+ try {
728
+ const rootNode = new task_node_1.TaskNode(task, [], []);
729
+ this.detectDirectedAcyclicGraph(task, rootNode, tasks);
730
+ }
731
+ catch (error) {
732
+ this.logger.error(error.message);
733
+ this.messageService.error(error.message);
734
+ return undefined;
735
+ }
736
+ return this.runTasksGraph(task, tasks, {
737
+ customization: { ...taskCustomization, ...{ problemMatcher: resolvedMatchers } }
738
+ }).catch(error => {
739
+ console.log(error.message);
740
+ return undefined;
741
+ });
742
+ }
743
+ /**
744
+ * Updates the task configuration in the `tasks.json`.
745
+ * The task config, together with updates, will be written into the `tasks.json` if it is not found in the file.
746
+ *
747
+ * @param token The cache token for the user interaction in progress
748
+ * @param task task that the updates will be applied to
749
+ * @param update the updates to be applied
750
+ */
751
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
752
+ async updateTaskConfiguration(token, task, update) {
753
+ if (update.problemMatcher) {
754
+ if (Array.isArray(update.problemMatcher)) {
755
+ update.problemMatcher.forEach((_name, index) => update.problemMatcher[index] = (0, common_2.asVariableName)(update.problemMatcher[index]));
756
+ }
757
+ else {
758
+ update.problemMatcher = (0, common_2.asVariableName)(update.problemMatcher);
759
+ }
760
+ }
761
+ this.taskConfigurations.updateTaskConfig(token, task, update);
762
+ }
763
+ async getWorkspaceTasks(token, restrictToFolder) {
764
+ const tasks = await this.getTasks(token);
765
+ // if we pass undefined, return everything, otherwise only tasks with the same uri or workspace/global scope tasks
766
+ return tasks.filter(t => typeof t._scope !== 'string' || t._scope === restrictToFolder);
767
+ }
768
+ async resolveProblemMatchers(task, customizationObject) {
769
+ const notResolvedMatchers = customizationObject.problemMatcher ?
770
+ (Array.isArray(customizationObject.problemMatcher) ? customizationObject.problemMatcher : [customizationObject.problemMatcher]) : undefined;
771
+ let resolvedMatchers = [];
772
+ if (notResolvedMatchers) {
773
+ // resolve matchers before passing them to the server
774
+ for (const matcher of notResolvedMatchers) {
775
+ let resolvedMatcher;
776
+ await this.problemMatcherRegistry.onReady();
777
+ if (typeof matcher === 'string') {
778
+ resolvedMatcher = this.problemMatcherRegistry.get(matcher);
779
+ }
780
+ else {
781
+ resolvedMatcher = await this.problemMatcherRegistry.getProblemMatcherFromContribution(matcher);
782
+ }
783
+ if (resolvedMatcher) {
784
+ const scope = task._scope || task._source;
785
+ if (resolvedMatcher.filePrefix && scope) {
786
+ const options = {
787
+ context: new uri_1.default(scope).withScheme('file'),
788
+ configurationSection: 'tasks'
789
+ };
790
+ const resolvedPrefix = await this.variableResolverService.resolve(resolvedMatcher.filePrefix, options);
791
+ Object.assign(resolvedMatcher, { filePrefix: resolvedPrefix });
792
+ }
793
+ resolvedMatchers.push(resolvedMatcher);
794
+ }
795
+ }
796
+ }
797
+ else {
798
+ resolvedMatchers = undefined;
799
+ }
800
+ return resolvedMatchers;
801
+ }
802
+ async getTaskCustomization(task) {
803
+ const customizationObject = { type: '', _scope: task._scope, runOptions: task.runOptions };
804
+ const customizationFound = this.taskConfigurations.getCustomizationForTask(task);
805
+ if (customizationFound) {
806
+ Object.assign(customizationObject, customizationFound);
807
+ }
808
+ else {
809
+ Object.assign(customizationObject, {
810
+ type: task.type,
811
+ problemMatcher: task.problemMatcher
812
+ });
813
+ }
814
+ return customizationObject;
815
+ }
816
+ async removeProblemMarkers(option) {
817
+ if (option && option.customization) {
818
+ const matchersFromOption = option.customization.problemMatcher || [];
819
+ for (const matcher of matchersFromOption) {
820
+ if (matcher && matcher.owner) {
821
+ const existingMarkers = this.problemManager.findMarkers({ owner: matcher.owner });
822
+ const uris = new Set();
823
+ existingMarkers.forEach(marker => uris.add(marker.uri));
824
+ uris.forEach(uriString => this.problemManager.setMarkers(new uri_1.default(uriString), matcher.owner, []));
825
+ }
826
+ }
827
+ }
828
+ }
829
+ /**
830
+ * Runs the resolved task and opens terminal widget if the task is based on a terminal process
831
+ * @param resolvedTask the resolved task
832
+ * @param option options to run the resolved task
833
+ */
834
+ async runResolvedTask(resolvedTask, option) {
835
+ const taskLabel = resolvedTask.label;
836
+ let taskInfo;
837
+ try {
838
+ taskInfo = await this.taskServer.run(resolvedTask, this.getContext(), option);
839
+ this.lastTask = { resolvedTask, option };
840
+ this.logger.debug(`Task created. Task id: ${taskInfo.taskId}`);
841
+ /**
842
+ * open terminal widget if the task is based on a terminal process (type: 'shell' or 'process')
843
+ *
844
+ * @todo Use a different mechanism to determine if the task should be attached?
845
+ * Reason: Maybe a new task type wants to also be displayed in a terminal.
846
+ */
847
+ if (typeof taskInfo.terminalId === 'number') {
848
+ await this.attach(taskInfo.terminalId, taskInfo);
849
+ }
850
+ return taskInfo;
851
+ }
852
+ catch (error) {
853
+ const errorStr = `Error launching task '${taskLabel}': ${error.message}`;
854
+ this.logger.error(errorStr);
855
+ this.messageService.error(errorStr);
856
+ if (taskInfo && typeof taskInfo.terminalId === 'number') {
857
+ this.shellTerminalServer.onAttachAttempted(taskInfo.terminalId);
858
+ }
859
+ }
860
+ }
861
+ getCustomizeProblemMatcherItems() {
862
+ const items = [];
863
+ items.push({
864
+ label: 'Continue without scanning the task output',
865
+ value: { problemMatchers: undefined }
866
+ });
867
+ items.push({
868
+ label: 'Never scan the task output',
869
+ value: { problemMatchers: [] }
870
+ });
871
+ items.push({
872
+ label: 'Learn more about scanning the task output',
873
+ value: { problemMatchers: undefined, learnMore: true }
874
+ });
875
+ items.push({ type: 'separator', label: 'registered parsers' });
876
+ const registeredProblemMatchers = this.problemMatcherRegistry.getAll();
877
+ items.push(...registeredProblemMatchers.map(matcher => ({
878
+ label: matcher.label,
879
+ value: { problemMatchers: [matcher] },
880
+ description: (0, common_2.asVariableName)(matcher.name)
881
+ })));
882
+ return items;
883
+ }
884
+ /**
885
+ * Run selected text in the last active terminal.
886
+ */
887
+ async runSelectedText() {
888
+ if (!this.editorManager.currentEditor) {
889
+ return;
890
+ }
891
+ const startLine = this.editorManager.currentEditor.editor.selection.start.line;
892
+ const startCharacter = this.editorManager.currentEditor.editor.selection.start.character;
893
+ const endLine = this.editorManager.currentEditor.editor.selection.end.line;
894
+ const endCharacter = this.editorManager.currentEditor.editor.selection.end.character;
895
+ let selectedRange = vscode_languageserver_protocol_1.Range.create(startLine, startCharacter, endLine, endCharacter);
896
+ // if no text is selected, default to selecting entire line
897
+ if (startLine === endLine && startCharacter === endCharacter) {
898
+ selectedRange = vscode_languageserver_protocol_1.Range.create(startLine, 0, endLine + 1, 0);
899
+ }
900
+ const selectedText = this.editorManager.currentEditor.editor.document.getText(selectedRange).trimRight() + '\n';
901
+ let terminal = this.terminalService.lastUsedTerminal;
902
+ if (!terminal || terminal.kind !== 'user' || (await terminal.hasChildProcesses())) {
903
+ terminal = await this.terminalService.newTerminal({ created: new Date().toString() });
904
+ await terminal.start();
905
+ this.terminalService.open(terminal);
906
+ }
907
+ terminal.sendText(selectedText);
908
+ }
909
+ async attach(terminalId, taskInfo) {
910
+ let widgetOpenMode = 'open';
911
+ if (taskInfo) {
912
+ const terminalWidget = this.terminalService.getByTerminalId(terminalId);
913
+ if (terminalWidget) {
914
+ this.messageService.error('Task is already running in terminal');
915
+ return this.terminalService.open(terminalWidget, { mode: 'activate' });
916
+ }
917
+ if (common_2.TaskOutputPresentation.shouldAlwaysRevealTerminal(taskInfo.config)) {
918
+ if (common_2.TaskOutputPresentation.shouldSetFocusToTerminal(taskInfo.config)) { // assign focus to the terminal if presentation.focus is true
919
+ widgetOpenMode = 'activate';
920
+ }
921
+ else { // show the terminal but not assign focus
922
+ widgetOpenMode = 'reveal';
923
+ }
924
+ }
925
+ }
926
+ const { taskId } = taskInfo;
927
+ // Create / find a terminal widget to display an execution output of a task that was launched as a command inside a shell.
928
+ const widget = await this.taskTerminalWidgetManager.open({
929
+ created: new Date().toString(),
930
+ id: this.getTerminalWidgetId(terminalId),
931
+ title: taskInfo
932
+ ? `Task: ${taskInfo.config.label}`
933
+ : `Task: #${taskId}`,
934
+ destroyTermOnClose: true,
935
+ useServerTitle: false
936
+ }, {
937
+ widgetOptions: { area: 'bottom' },
938
+ mode: widgetOpenMode,
939
+ taskInfo
940
+ });
941
+ return widget.start(terminalId);
942
+ }
943
+ getTerminalWidgetId(terminalId) {
944
+ const terminalWidget = this.terminalService.getByTerminalId(terminalId);
945
+ if (terminalWidget) {
946
+ return terminalWidget.id;
947
+ }
948
+ }
949
+ /**
950
+ * Opens an editor to configure the given task.
951
+ *
952
+ * @param token The cache token for the user interaction in progress
953
+ * @param task The task to configure
954
+ */
955
+ async configure(token, task) {
956
+ Object.assign(task, { label: this.taskNameResolver.resolve(task) });
957
+ await this.taskConfigurations.configure(token, task);
958
+ }
959
+ isEventForThisClient(context) {
960
+ if (context === this.getContext()) {
961
+ return true;
962
+ }
963
+ return false;
964
+ }
965
+ taskConfigurationChanged(event) {
966
+ // do nothing for now
967
+ }
968
+ getContext() {
969
+ var _a;
970
+ return (_a = this.workspaceService.workspace) === null || _a === void 0 ? void 0 : _a.resource.toString();
971
+ }
972
+ /** Kill task for a given id if task is found */
973
+ async kill(id) {
974
+ try {
975
+ await this.taskServer.kill(id);
976
+ }
977
+ catch (error) {
978
+ this.logger.error(`Error killing task '${id}': ${error}`);
979
+ this.messageService.error(`Error killing task '${id}': ${error}`);
980
+ return;
981
+ }
982
+ this.logger.debug(`Task killed. Task id: ${id}`);
983
+ }
984
+ async isBackgroundTaskEnded(id) {
985
+ const completedTask = this.runningTasks.get(id);
986
+ return completedTask && completedTask.isBackgroundTaskEnded.promise;
987
+ }
988
+ async getExitCode(id) {
989
+ const completedTask = this.runningTasks.get(id);
990
+ return completedTask && completedTask.exitCode.promise;
991
+ }
992
+ async getTerminateSignal(id) {
993
+ const completedTask = this.runningTasks.get(id);
994
+ return completedTask && completedTask.terminateSignal.promise;
995
+ }
996
+ };
997
+ __decorate([
998
+ (0, inversify_1.inject)(browser_1.FrontendApplication),
999
+ __metadata("design:type", browser_1.FrontendApplication)
1000
+ ], TaskService.prototype, "app", void 0);
1001
+ __decorate([
1002
+ (0, inversify_1.inject)(browser_1.ApplicationShell),
1003
+ __metadata("design:type", browser_1.ApplicationShell)
1004
+ ], TaskService.prototype, "shell", void 0);
1005
+ __decorate([
1006
+ (0, inversify_1.inject)(common_2.TaskServer),
1007
+ __metadata("design:type", Object)
1008
+ ], TaskService.prototype, "taskServer", void 0);
1009
+ __decorate([
1010
+ (0, inversify_1.inject)(common_1.ILogger),
1011
+ (0, inversify_1.named)('task'),
1012
+ __metadata("design:type", Object)
1013
+ ], TaskService.prototype, "logger", void 0);
1014
+ __decorate([
1015
+ (0, inversify_1.inject)(browser_1.WidgetManager),
1016
+ __metadata("design:type", browser_1.WidgetManager)
1017
+ ], TaskService.prototype, "widgetManager", void 0);
1018
+ __decorate([
1019
+ (0, inversify_1.inject)(task_watcher_1.TaskWatcher),
1020
+ __metadata("design:type", task_watcher_1.TaskWatcher)
1021
+ ], TaskService.prototype, "taskWatcher", void 0);
1022
+ __decorate([
1023
+ (0, inversify_1.inject)(message_service_1.MessageService),
1024
+ __metadata("design:type", message_service_1.MessageService)
1025
+ ], TaskService.prototype, "messageService", void 0);
1026
+ __decorate([
1027
+ (0, inversify_1.inject)(workspace_service_1.WorkspaceService),
1028
+ __metadata("design:type", workspace_service_1.WorkspaceService)
1029
+ ], TaskService.prototype, "workspaceService", void 0);
1030
+ __decorate([
1031
+ (0, inversify_1.inject)(task_configurations_1.TaskConfigurations),
1032
+ __metadata("design:type", task_configurations_1.TaskConfigurations)
1033
+ ], TaskService.prototype, "taskConfigurations", void 0);
1034
+ __decorate([
1035
+ (0, inversify_1.inject)(provided_task_configurations_1.ProvidedTaskConfigurations),
1036
+ __metadata("design:type", provided_task_configurations_1.ProvidedTaskConfigurations)
1037
+ ], TaskService.prototype, "providedTaskConfigurations", void 0);
1038
+ __decorate([
1039
+ (0, inversify_1.inject)(browser_3.VariableResolverService),
1040
+ __metadata("design:type", browser_3.VariableResolverService)
1041
+ ], TaskService.prototype, "variableResolverService", void 0);
1042
+ __decorate([
1043
+ (0, inversify_1.inject)(task_contribution_1.TaskResolverRegistry),
1044
+ __metadata("design:type", task_contribution_1.TaskResolverRegistry)
1045
+ ], TaskService.prototype, "taskResolverRegistry", void 0);
1046
+ __decorate([
1047
+ (0, inversify_1.inject)(terminal_service_1.TerminalService),
1048
+ __metadata("design:type", Object)
1049
+ ], TaskService.prototype, "terminalService", void 0);
1050
+ __decorate([
1051
+ (0, inversify_1.inject)(browser_2.EditorManager),
1052
+ __metadata("design:type", browser_2.EditorManager)
1053
+ ], TaskService.prototype, "editorManager", void 0);
1054
+ __decorate([
1055
+ (0, inversify_1.inject)(problem_manager_1.ProblemManager),
1056
+ __metadata("design:type", problem_manager_1.ProblemManager)
1057
+ ], TaskService.prototype, "problemManager", void 0);
1058
+ __decorate([
1059
+ (0, inversify_1.inject)(task_definition_registry_1.TaskDefinitionRegistry),
1060
+ __metadata("design:type", task_definition_registry_1.TaskDefinitionRegistry)
1061
+ ], TaskService.prototype, "taskDefinitionRegistry", void 0);
1062
+ __decorate([
1063
+ (0, inversify_1.inject)(task_problem_matcher_registry_1.ProblemMatcherRegistry),
1064
+ __metadata("design:type", task_problem_matcher_registry_1.ProblemMatcherRegistry)
1065
+ ], TaskService.prototype, "problemMatcherRegistry", void 0);
1066
+ __decorate([
1067
+ (0, inversify_1.inject)(quick_pick_service_1.QuickPickService),
1068
+ __metadata("design:type", Object)
1069
+ ], TaskService.prototype, "quickPickService", void 0);
1070
+ __decorate([
1071
+ (0, inversify_1.inject)(opener_service_1.OpenerService),
1072
+ __metadata("design:type", Object)
1073
+ ], TaskService.prototype, "openerService", void 0);
1074
+ __decorate([
1075
+ (0, inversify_1.inject)(shell_terminal_protocol_1.ShellTerminalServerProxy),
1076
+ __metadata("design:type", Object)
1077
+ ], TaskService.prototype, "shellTerminalServer", void 0);
1078
+ __decorate([
1079
+ (0, inversify_1.inject)(task_name_resolver_1.TaskNameResolver),
1080
+ __metadata("design:type", task_name_resolver_1.TaskNameResolver)
1081
+ ], TaskService.prototype, "taskNameResolver", void 0);
1082
+ __decorate([
1083
+ (0, inversify_1.inject)(task_source_resolver_1.TaskSourceResolver),
1084
+ __metadata("design:type", task_source_resolver_1.TaskSourceResolver)
1085
+ ], TaskService.prototype, "taskSourceResolver", void 0);
1086
+ __decorate([
1087
+ (0, inversify_1.inject)(task_schema_updater_1.TaskSchemaUpdater),
1088
+ __metadata("design:type", task_schema_updater_1.TaskSchemaUpdater)
1089
+ ], TaskService.prototype, "taskSchemaUpdater", void 0);
1090
+ __decorate([
1091
+ (0, inversify_1.inject)(task_configuration_manager_1.TaskConfigurationManager),
1092
+ __metadata("design:type", task_configuration_manager_1.TaskConfigurationManager)
1093
+ ], TaskService.prototype, "taskConfigurationManager", void 0);
1094
+ __decorate([
1095
+ (0, inversify_1.inject)(common_1.CommandService),
1096
+ __metadata("design:type", Object)
1097
+ ], TaskService.prototype, "commands", void 0);
1098
+ __decorate([
1099
+ (0, inversify_1.inject)(label_provider_1.LabelProvider),
1100
+ __metadata("design:type", label_provider_1.LabelProvider)
1101
+ ], TaskService.prototype, "labelProvider", void 0);
1102
+ __decorate([
1103
+ (0, inversify_1.inject)(monaco_workspace_1.MonacoWorkspace),
1104
+ __metadata("design:type", monaco_workspace_1.MonacoWorkspace)
1105
+ ], TaskService.prototype, "monacoWorkspace", void 0);
1106
+ __decorate([
1107
+ (0, inversify_1.inject)(task_terminal_widget_manager_1.TaskTerminalWidgetManager),
1108
+ __metadata("design:type", task_terminal_widget_manager_1.TaskTerminalWidgetManager)
1109
+ ], TaskService.prototype, "taskTerminalWidgetManager", void 0);
1110
+ __decorate([
1111
+ (0, inversify_1.postConstruct)(),
1112
+ __metadata("design:type", Function),
1113
+ __metadata("design:paramtypes", []),
1114
+ __metadata("design:returntype", void 0)
1115
+ ], TaskService.prototype, "init", null);
1116
+ TaskService = __decorate([
1117
+ (0, inversify_1.injectable)()
1118
+ ], TaskService);
1119
+ exports.TaskService = TaskService;
1120
1120
  //# sourceMappingURL=task-service.js.map