UNPKG

@theia/task

Version:

Theia - Task extension. This extension adds support for executing raw or terminal processes in the backend.

232 lines • 10.2 kB
"use strict"; // ***************************************************************************** // Copyright (C) 2017 Ericsson and others. // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License v. 2.0 which is available at // http://www.eclipse.org/legal/epl-2.0. // // This Source Code may also be made available under the following Secondary // Licenses when the conditions for such availability set forth in the Eclipse // Public License v. 2.0 are satisfied: GNU General Public License, version 2 // with the GNU Classpath Exception which is available at // https://www.gnu.org/software/classpath/license.html. // // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** Object.defineProperty(exports, "__esModule", { value: true }); exports.TaskServerImpl = void 0; const tslib_1 = require("tslib"); const inversify_1 = require("@theia/core/shared/inversify"); const common_1 = require("@theia/core/lib/common/"); const task_manager_1 = require("./task-manager"); const task_runner_1 = require("./task-runner"); const process_task_1 = require("./process/process-task"); const task_problem_collector_1 = require("./task-problem-collector"); let TaskServerImpl = class TaskServerImpl { constructor() { /** Task clients, to send notifications-to. */ this.clients = []; /** Map of task id and task disposable */ this.toDispose = new Map(); /** Map of task id and task background status. */ // Currently there is only one property ('isActive'), but in the future we may want to store more properties this.backgroundTaskStatusMap = new Map(); /** task context - {task id - problem collector} */ this.problemCollectors = new Map(); } dispose() { for (const toDispose of this.toDispose.values()) { toDispose.dispose(); } this.toDispose.clear(); this.backgroundTaskStatusMap.clear(); } disposeByTaskId(taskId) { if (this.toDispose.has(taskId)) { this.toDispose.get(taskId).dispose(); this.toDispose.delete(taskId); } if (this.backgroundTaskStatusMap.has(taskId)) { this.backgroundTaskStatusMap.delete(taskId); } } async getTasks(context) { const taskInfo = []; const tasks = this.taskManager.getTasks(context); if (tasks !== undefined) { for (const task of tasks) { taskInfo.push(await task.getRuntimeInfo()); } } this.logger.debug(`getTasks(): about to return task information for ${taskInfo.length} tasks`); return Promise.resolve(taskInfo); } async run(taskConfiguration, ctx, option) { const runner = taskConfiguration.executionType ? this.runnerRegistry.getRunner(taskConfiguration.type, taskConfiguration.executionType) : this.runnerRegistry.getRunner(taskConfiguration.type); const task = await runner.run(taskConfiguration, ctx); if (!this.toDispose.has(task.id)) { this.toDispose.set(task.id, new common_1.DisposableCollection()); } if (taskConfiguration.isBackground && !this.backgroundTaskStatusMap.has(task.id)) { this.backgroundTaskStatusMap.set(task.id, { 'isActive': false }); } this.toDispose.get(task.id).push(task.onExit(event => { this.taskManager.delete(task); this.fireTaskExitedEvent(event, task); this.removedCachedProblemCollector(event.ctx || '', event.taskId); this.disposeByTaskId(event.taskId); })); const resolvedMatchers = option && option.customization ? option.customization.problemMatcher || [] : []; if (resolvedMatchers.length > 0) { this.toDispose.get(task.id).push(task.onOutput(event => { let collector = this.getCachedProblemCollector(event.ctx || '', event.taskId); if (!collector) { collector = new task_problem_collector_1.ProblemCollector(resolvedMatchers); this.cacheProblemCollector(event.ctx || '', event.taskId, collector); } const problems = collector.processLine(event.line); if (problems.length > 0) { this.fireTaskOutputProcessedEvent({ taskId: event.taskId, config: taskConfiguration, ctx: event.ctx, problems }); } if (taskConfiguration.isBackground) { const backgroundTaskStatus = this.backgroundTaskStatusMap.get(event.taskId); if (!backgroundTaskStatus.isActive) { // Get the 'activeOnStart' value of the problem matcher 'background' property const activeOnStart = collector.isTaskActiveOnStart(); if (activeOnStart) { backgroundTaskStatus.isActive = true; } else { const isBeginsPatternMatch = collector.matchBeginMatcher(event.line); if (isBeginsPatternMatch) { backgroundTaskStatus.isActive = true; } } } if (backgroundTaskStatus.isActive) { const isEndsPatternMatch = collector.matchEndMatcher(event.line); // Mark ends pattern as matches, only after begins pattern matches if (isEndsPatternMatch) { this.fireBackgroundTaskEndedEvent({ taskId: event.taskId, ctx: event.ctx }); } } } })); } this.toDispose.get(task.id).push(task); const taskInfo = await task.getRuntimeInfo(); this.fireTaskCreatedEvent(taskInfo); return taskInfo; } async getRegisteredTaskTypes() { return this.runnerRegistry.getRunnerTypes(); } async customExecutionComplete(id, exitCode) { const task = this.taskManager.get(id); await task.callbackTaskComplete(exitCode); } fireTaskExitedEvent(event, task) { this.logger.debug(log => log('task has exited:', event)); if (task instanceof process_task_1.ProcessTask) { this.clients.forEach(client => { client.onDidEndTaskProcess(event); }); } this.clients.forEach(client => { client.onTaskExit(event); }); } fireTaskCreatedEvent(event, task) { this.logger.debug(log => log('task created:', event)); this.clients.forEach(client => { client.onTaskCreated(event); }); if (task && task instanceof process_task_1.ProcessTask) { this.clients.forEach(client => { client.onDidStartTaskProcess(event); }); } } fireTaskOutputProcessedEvent(event) { this.clients.forEach(client => client.onDidProcessTaskOutput(event)); } fireBackgroundTaskEndedEvent(event) { this.clients.forEach(client => client.onBackgroundTaskEnded(event)); } /** Kill task for a given id. Rejects if task is not found */ async kill(id) { const taskToKill = this.taskManager.get(id); if (taskToKill !== undefined) { this.logger.info(`Killing task id ${id}`); return taskToKill.kill(); } else { this.logger.info(`Could not find task to kill, task id ${id}. Already terminated?`); return Promise.reject(new Error(`Could not find task to kill, task id ${id}. Already terminated?`)); } } /** Adds a client to this server */ setClient(client) { this.logger.debug('a client has connected - adding it to the list:'); this.clients.push(client); } /** Removes a client, from this server */ disconnectClient(client) { this.logger.debug('a client has disconnected - removed from list:'); const idx = this.clients.indexOf(client); if (idx > -1) { this.clients.splice(idx, 1); } } getCachedProblemCollector(ctx, taskId) { if (this.problemCollectors.has(ctx)) { return this.problemCollectors.get(ctx).get(taskId); } } cacheProblemCollector(ctx, taskId, problemCollector) { if (this.problemCollectors.has(ctx)) { if (!this.problemCollectors.get(ctx).has(taskId)) { this.problemCollectors.get(ctx).set(taskId, problemCollector); } } else { const forNewContext = new Map(); forNewContext.set(taskId, problemCollector); this.problemCollectors.set(ctx, forNewContext); } } removedCachedProblemCollector(ctx, taskId) { if (this.problemCollectors.has(ctx) && this.problemCollectors.get(ctx).has(taskId)) { this.problemCollectors.get(ctx).delete(taskId); } } }; exports.TaskServerImpl = TaskServerImpl; tslib_1.__decorate([ (0, inversify_1.inject)(common_1.ILogger), (0, inversify_1.named)('task'), tslib_1.__metadata("design:type", Object) ], TaskServerImpl.prototype, "logger", void 0); tslib_1.__decorate([ (0, inversify_1.inject)(task_manager_1.TaskManager), tslib_1.__metadata("design:type", task_manager_1.TaskManager) ], TaskServerImpl.prototype, "taskManager", void 0); tslib_1.__decorate([ (0, inversify_1.inject)(task_runner_1.TaskRunnerRegistry), tslib_1.__metadata("design:type", task_runner_1.TaskRunnerRegistry) ], TaskServerImpl.prototype, "runnerRegistry", void 0); exports.TaskServerImpl = TaskServerImpl = tslib_1.__decorate([ (0, inversify_1.injectable)() ], TaskServerImpl); //# sourceMappingURL=task-server.js.map