diff --git a/packages/task/src/node/process/process-task.ts b/packages/task/src/node/process/process-task.ts index ee0a1ac0b97a8..c843330dabf3f 100644 --- a/packages/task/src/node/process/process-task.ts +++ b/packages/task/src/node/process/process-task.ts @@ -64,10 +64,11 @@ export class ProcessTask extends Task { ) { super(taskManager, logger, options); - const toDispose = this.process.onExit(async event => { - toDispose.dispose(); - this.fireTaskExited(await this.getTaskExitedEvent(event)); - }); + this.toDispose.push( + this.process.onExit(async event => { + this.fireTaskExited(await this.getTaskExitedEvent(event)); + }) + ); // Buffer to accumulate incoming output. let databuf: string = ''; diff --git a/packages/task/src/node/task-server.ts b/packages/task/src/node/task-server.ts index 8def86f7fc53f..3a8e7f35dddb0 100644 --- a/packages/task/src/node/task-server.ts +++ b/packages/task/src/node/task-server.ts @@ -15,7 +15,7 @@ ********************************************************************************/ import { inject, injectable, named } from 'inversify'; -import { ILogger } from '@theia/core/lib/common/'; +import { Disposable, DisposableCollection, ILogger } from '@theia/core/lib/common/'; import { TaskClient, TaskExitedEvent, @@ -32,10 +32,11 @@ import { ProcessTask } from './process/process-task'; import { ProblemCollector } from './task-problem-collector'; @injectable() -export class TaskServerImpl implements TaskServer { +export class TaskServerImpl implements TaskServer, Disposable { /** Task clients, to send notifications-to. */ protected clients: TaskClient[] = []; + protected toDispose = new DisposableCollection(); @inject(ILogger) @named('task') protected readonly logger: ILogger; @@ -50,7 +51,7 @@ export class TaskServerImpl implements TaskServer { private problemCollectors: Map> = new Map(); dispose() { - // do nothing + this.toDispose.dispose(); } async getTasks(context?: string): Promise { @@ -70,31 +71,37 @@ export class TaskServerImpl implements TaskServer { async run(taskConfiguration: TaskConfiguration, ctx?: string, option?: RunTaskOption): Promise { const runner = this.runnerRegistry.getRunner(taskConfiguration.type); const task = await runner.run(taskConfiguration, ctx); + this.toDispose.push(task); - task.onExit(event => { - this.taskManager.delete(task); - this.fireTaskExitedEvent(event); - this.removedCachedProblemCollector(event.ctx || '', event.taskId); - }); + this.toDispose.push( + task.onExit(event => { + this.taskManager.delete(task); + this.fireTaskExitedEvent(event); + this.removedCachedProblemCollector(event.ctx || '', event.taskId); + this.toDispose.dispose(); + }) + ); const resolvedMatchers = option && option.customization ? option.customization.problemMatcher || [] : []; if (resolvedMatchers.length > 0) { - task.onOutput(event => { - let collector: ProblemCollector | undefined = this.getCachedProblemCollector(event.ctx || '', event.taskId); - if (!collector) { - collector = new ProblemCollector(resolvedMatchers); - this.cacheProblemCollector(event.ctx || '', event.taskId, collector); - } - - const problems = collector.processLine(event.line); - if (problems.length > 0) { - this.fireTaskOutputProcessedEvent({ - taskId: event.taskId, - ctx: event.ctx, - problems - }); - } - }); + this.toDispose.push( + task.onOutput(event => { + let collector: ProblemCollector | undefined = this.getCachedProblemCollector(event.ctx || '', event.taskId); + if (!collector) { + collector = new ProblemCollector(resolvedMatchers); + this.cacheProblemCollector(event.ctx || '', event.taskId, collector); + } + + const problems = collector.processLine(event.line); + if (problems.length > 0) { + this.fireTaskOutputProcessedEvent({ + taskId: event.taskId, + ctx: event.ctx, + problems + }); + } + }) + ); } const taskInfo = await task.getRuntimeInfo(); diff --git a/packages/task/src/node/task.ts b/packages/task/src/node/task.ts index 3cbca191820b0..0d516a7ed1511 100644 --- a/packages/task/src/node/task.ts +++ b/packages/task/src/node/task.ts @@ -15,7 +15,7 @@ ********************************************************************************/ import { injectable } from 'inversify'; -import { ILogger, Emitter, Event, MaybePromise } from '@theia/core/lib/common/'; +import { ILogger, Disposable, DisposableCollection, Emitter, Event, MaybePromise } from '@theia/core/lib/common/'; import { TaskManager } from './task-manager'; import { TaskInfo, TaskExitedEvent, TaskConfiguration, TaskOutputEvent, TaskOutputProcessedEvent } from '../common/task-protocol'; @@ -26,9 +26,10 @@ export interface TaskOptions { } @injectable() -export abstract class Task { +export abstract class Task implements Disposable { protected taskId: number; + protected toDispose: DisposableCollection = new DisposableCollection(); readonly exitEmitter: Emitter; readonly outputEmitter: Emitter; readonly outputProcessedEmitter: Emitter; @@ -41,6 +42,8 @@ export abstract class Task { this.taskId = this.taskManager.register(this, this.options.context); this.exitEmitter = new Emitter(); this.outputEmitter = new Emitter(); + this.toDispose.push(this.exitEmitter); + this.toDispose.push(this.outputEmitter); } /** Terminates the task. */ @@ -77,4 +80,8 @@ export abstract class Task { get label() { return this.options.label; } + + dispose() { + this.toDispose.dispose(); + } }