From 1acfd00cc283d9af7c29faed7963dac9671d5fce Mon Sep 17 00:00:00 2001 From: elaihau Date: Wed, 3 Jul 2019 08:45:16 -0400 Subject: [PATCH] dispose task listeners and emitters when needed Signed-off-by: elaihau --- packages/task/src/node/task-server.ts | 55 +++++++++++++++------------ packages/task/src/node/task.ts | 11 +++++- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/packages/task/src/node/task-server.ts b/packages/task/src/node/task-server.ts index 8def86f7fc53f..4caf37a9a0ef2 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 readonly 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 b73cd7fe1a992..3ee22209479e7 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 } 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 readonly toDispose: DisposableCollection = new DisposableCollection(); readonly exitEmitter: Emitter; readonly outputEmitter: Emitter; @@ -40,6 +41,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. */ @@ -76,4 +79,8 @@ export abstract class Task { get label() { return this.options.label; } + + dispose() { + this.toDispose.dispose(); + } }