From 98e93489ebde483e84602eef32d85bc439b1730d Mon Sep 17 00:00:00 2001 From: Lewin Tan Date: Tue, 16 Mar 2021 21:17:17 +0800 Subject: [PATCH] Fixed some issues of Custom Task: 1. fixed custom task copyright 2. fixed TerminalWidgetImpl error log 3. fixed repeat task multiple callback close 4. fixed have no exit code Signed-off-by: Lewin Tan --- .../plugin-ext/src/common/plugin-api-rpc.ts | 2 +- .../plugin-ext/src/main/browser/tasks-main.ts | 12 +------- packages/plugin-ext/src/plugin/tasks/tasks.ts | 8 +++-- .../plugin-ext/src/plugin/terminal-ext.ts | 2 +- .../custom-task-runner-backend-module.ts | 2 +- .../custom/custom-task-runner-contribution.ts | 2 +- .../src/node/custom/custom-task-runner.ts | 29 ++++--------------- packages/task/src/node/custom/custom-task.ts | 11 ++----- packages/task/src/node/task-server.ts | 1 - .../src/browser/terminal-widget-impl.ts | 18 ++++++++---- 10 files changed, 32 insertions(+), 55 deletions(-) diff --git a/packages/plugin-ext/src/common/plugin-api-rpc.ts b/packages/plugin-ext/src/common/plugin-api-rpc.ts index 449ee060b012d..d0fa008ca05a4 100644 --- a/packages/plugin-ext/src/common/plugin-api-rpc.ts +++ b/packages/plugin-ext/src/common/plugin-api-rpc.ts @@ -1707,7 +1707,7 @@ export const MAIN_RPC_CONTEXT = { export interface TasksExt { $provideTasks(handle: number, token?: CancellationToken): Promise; $resolveTask(handle: number, task: TaskDto, token?: CancellationToken): Promise; - $onDidStartTask(execution: TaskExecutionDto, terminalId: number, resolvedDefinition: theia.TaskDefinition): void; + $onDidStartTask(execution: TaskExecutionDto, terminalId: number): void; $onDidEndTask(id: number): void; $onDidStartTaskProcess(processId: number | undefined, execution: TaskExecutionDto): void; $onDidEndTaskProcess(exitCode: number | undefined, taskId: number): void; diff --git a/packages/plugin-ext/src/main/browser/tasks-main.ts b/packages/plugin-ext/src/main/browser/tasks-main.ts index 57ba90a9a195a..7f195eb89ee35 100644 --- a/packages/plugin-ext/src/main/browser/tasks-main.ts +++ b/packages/plugin-ext/src/main/browser/tasks-main.ts @@ -29,7 +29,6 @@ import { TaskInfo, TaskExitedEvent, TaskConfiguration, TaskCustomization } from import { TaskWatcher } from '@theia/task/lib/common/task-watcher'; import { TaskService } from '@theia/task/lib/browser/task-service'; import { TaskDefinitionRegistry } from '@theia/task/lib/browser'; -import * as theia from '@theia/plugin'; export class TasksMainImpl implements TasksMain, Disposable { private readonly proxy: TasksExt; @@ -51,19 +50,10 @@ export class TasksMainImpl implements TasksMain, Disposable { this.taskDefinitionRegistry = container.get(TaskDefinitionRegistry); this.toDispose.push(this.taskWatcher.onTaskCreated((event: TaskInfo) => { - const taskDefinition = { - type: event.config.type - } as theia.TaskDefinition; - const { type, ...properties } = event.config; - for (const key in properties) { - if (properties.hasOwnProperty(key)) { - taskDefinition[key] = properties[key]; - } - } this.proxy.$onDidStartTask({ id: event.taskId, task: this.fromTaskConfiguration(event.config) - }, event.terminalId!!, taskDefinition); + }, event.terminalId!); })); this.toDispose.push(this.taskWatcher.onTaskExit((event: TaskExitedEvent) => { diff --git a/packages/plugin-ext/src/plugin/tasks/tasks.ts b/packages/plugin-ext/src/plugin/tasks/tasks.ts index 2494915b2c911..e49454fcbed1e 100644 --- a/packages/plugin-ext/src/plugin/tasks/tasks.ts +++ b/packages/plugin-ext/src/plugin/tasks/tasks.ts @@ -64,7 +64,7 @@ export class TasksExtImpl implements TasksExt { return this.onDidExecuteTask.event; } - async $onDidStartTask(execution: TaskExecutionDto, terminalId: number, resolvedDefinition: theia.TaskDefinition): Promise { + async $onDidStartTask(execution: TaskExecutionDto, terminalId: number): Promise { const customExecution: CustomExecution | undefined = this.providedCustomExecutions.get(execution.task.id); if (customExecution) { if (this.activeCustomExecutions.get(execution.id) !== undefined) { @@ -73,10 +73,12 @@ export class TasksExtImpl implements TasksExt { // Clone the custom execution to keep the original untouched. This is important for multiple runs of the same task. this.activeCustomExecutions.set(execution.id, customExecution); - const pty = await customExecution.callback(resolvedDefinition); + const taskDefinition = converter.toTask(execution.task).definition; + const pty = await customExecution.callback(taskDefinition); this.terminalExt.attachPtyToTerminal(terminalId, pty); if (pty.onDidClose) { - pty.onDidClose((e: number | void = undefined) => { + const disposable = pty.onDidClose((e: number | void = undefined) => { + disposable.dispose(); // eslint-disable-next-line no-void this.proxy.$customExecutionComplete(execution.id, e === void 0 ? undefined : e); }); diff --git a/packages/plugin-ext/src/plugin/terminal-ext.ts b/packages/plugin-ext/src/plugin/terminal-ext.ts index 4d0a14b31238e..92d26127befcb 100644 --- a/packages/plugin-ext/src/plugin/terminal-ext.ts +++ b/packages/plugin-ext/src/plugin/terminal-ext.ts @@ -79,7 +79,7 @@ export class TerminalServiceExtImpl implements TerminalServiceExt { return this.obtainTerminal(id, options.name || 'Terminal'); } - public attachPtyToTerminal(terminalId: number, pty: theia.Pseudoterminal): void { + attachPtyToTerminal(terminalId: number, pty: theia.Pseudoterminal): void { this._pseudoTerminals.set(terminalId.toString(), new PseudoTerminal(terminalId, this.proxy, pty, true)); } diff --git a/packages/task/src/node/custom/custom-task-runner-backend-module.ts b/packages/task/src/node/custom/custom-task-runner-backend-module.ts index 63dc426a30426..1e688a5fc80bf 100644 --- a/packages/task/src/node/custom/custom-task-runner-backend-module.ts +++ b/packages/task/src/node/custom/custom-task-runner-backend-module.ts @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (C) 2018 Red Hat, Inc. and others. + * Copyright (C) 2021 ByteDance 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 diff --git a/packages/task/src/node/custom/custom-task-runner-contribution.ts b/packages/task/src/node/custom/custom-task-runner-contribution.ts index a15e76772d20e..563dc97c08a30 100644 --- a/packages/task/src/node/custom/custom-task-runner-contribution.ts +++ b/packages/task/src/node/custom/custom-task-runner-contribution.ts @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (C) 2018 Red Hat, Inc. and others. + * Copyright (C) 2021 ByteDance 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 diff --git a/packages/task/src/node/custom/custom-task-runner.ts b/packages/task/src/node/custom/custom-task-runner.ts index 427adee154e2c..deb2503a1fe7c 100644 --- a/packages/task/src/node/custom/custom-task-runner.ts +++ b/packages/task/src/node/custom/custom-task-runner.ts @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (C) 2017-2019 Ericsson and others. + * Copyright (C) 2021 ByteDance 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 @@ -14,11 +14,6 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - import { TaskConfiguration } from '../../common'; import { Task } from '../task'; import { TaskRunner } from '../task-runner'; @@ -26,7 +21,6 @@ import { injectable, inject, named } from 'inversify'; import { ILogger } from '@theia/core'; import { TaskFactory } from './custom-task'; import { - RawProcessFactory, TerminalProcessFactory, Process, TerminalProcessOptions, @@ -41,34 +35,23 @@ export class CustomTaskRunner implements TaskRunner { @inject(ILogger) @named('task') protected readonly logger: ILogger; - @inject(RawProcessFactory) - protected readonly rawProcessFactory: RawProcessFactory; - @inject(TerminalProcessFactory) protected readonly terminalProcessFactory: TerminalProcessFactory; @inject(TaskFactory) protected readonly taskFactory: TaskFactory; - async run(tskConfig: TaskConfiguration, ctx?: string): Promise { + async run(taskConfig: TaskConfiguration, ctx?: string): Promise { try { const terminalProcessOptions = { isPseudo: true } as TerminalProcessOptions; const terminal: Process = this.terminalProcessFactory(terminalProcessOptions); - // Wait for the confirmation that the process is successfully started, or has failed to start. - // await new Promise((resolve, reject) => { - // terminal.onStart(resolve); - // terminal.onError((error: ProcessErrorEvent) => { - // reject(ProcessTaskError.CouldNotRun(error.code)); - // }); - // }); - - return Promise.resolve(this.taskFactory({ + return this.taskFactory({ context: ctx, - config: tskConfig, - label: tskConfig.label, + config: taskConfig, + label: taskConfig.label, process: terminal, - })); + }); } catch (error) { this.logger.error(`Error occurred while creating task: ${error}`); throw error; diff --git a/packages/task/src/node/custom/custom-task.ts b/packages/task/src/node/custom/custom-task.ts index d1453a8f0fc77..5aa032bb60bb6 100644 --- a/packages/task/src/node/custom/custom-task.ts +++ b/packages/task/src/node/custom/custom-task.ts @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (C) 2017 Ericsson and others. + * Copyright (C) 2021 ByteDance 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 @@ -14,11 +14,6 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ - import { injectable, inject, named } from 'inversify'; import { ILogger, MaybePromise } from '@theia/core/lib/common/'; import { Task, TaskOptions } from '../task'; @@ -57,7 +52,7 @@ export class CustomTask extends Task { ctx: this.context, config: this.options.config, terminalId: this.process.id, - processId: this.process.id, + processId: this.process.id }; } @@ -68,7 +63,7 @@ export class CustomTask extends Task { config: this.options.config, terminalId: this.process.id, processId: this.process.id, - code: exitCode, + code: exitCode || 0 }); } diff --git a/packages/task/src/node/task-server.ts b/packages/task/src/node/task-server.ts index c95dde51a1f7f..ba3cd872d2837 100644 --- a/packages/task/src/node/task-server.ts +++ b/packages/task/src/node/task-server.ts @@ -172,7 +172,6 @@ export class TaskServerImpl implements TaskServer, Disposable { async customExecutionComplete(id: number, exitCode: number | undefined): Promise { const task = this.taskManager.get(id) as CustomTask; await task.callbackTaskComplete(exitCode); - return; } protected fireTaskExitedEvent(event: TaskExitedEvent, task?: Task): void { diff --git a/packages/terminal/src/browser/terminal-widget-impl.ts b/packages/terminal/src/browser/terminal-widget-impl.ts index 50b7d357b4268..de84bdbcf3fc1 100644 --- a/packages/terminal/src/browser/terminal-widget-impl.ts +++ b/packages/terminal/src/browser/terminal-widget-impl.ts @@ -37,6 +37,7 @@ import { TerminalCopyOnSelectionHandler } from './terminal-copy-on-selection-han import { TerminalThemeService } from './terminal-theme-service'; import { CommandLineOptions, ShellCommandBuilder } from '@theia/process/lib/common/shell-command-builder'; import { Key } from '@theia/core/lib/browser/keys'; + export const TERMINAL_WIDGET_FACTORY_ID = 'terminal'; export interface TerminalWidgetFactoryOptions extends Partial { @@ -59,6 +60,7 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget protected waitForConnection: Deferred | undefined; protected hoverMessage: HTMLDivElement; protected lastTouchEnd: TouchEvent | undefined; + protected isAttachedCloseListener: boolean = false; @inject(WorkspaceService) protected readonly workspaceService: WorkspaceService; @inject(WebSocketConnectionProvider) protected readonly webSocketConnectionProvider: WebSocketConnectionProvider; @@ -487,7 +489,7 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget // Excludes the device status code emitted by Xterm.js const sendData = (data?: string) => { - if (data && !this.deviceStatusCodes.has(data)) { + if (data && !this.deviceStatusCodes.has(data) && !this.disableEnterWhenAttachCloseListener()) { return connection.sendRequest('write', data); } }; @@ -615,7 +617,7 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget return; } if (!IBaseTerminalServer.validateId(this.terminalId) - && !this.terminalService.getById(this.id)) { + || !this.terminalService.getById(this.id)) { return; } const { cols, rows } = this.term; @@ -683,17 +685,23 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget this.shellTerminalServer.close(this.terminalId); this.onTermDidClose.fire(this); } - this.attachPressAnyKeyToCloseListener(this.term); + this.attachPressEnterKeyToCloseListener(this.term); return; } - return this.dispose(); + this.dispose(); } - private attachPressAnyKeyToCloseListener(term: Terminal): void { + private attachPressEnterKeyToCloseListener(term: Terminal): void { if (term.textarea) { + this.isAttachedCloseListener = true; this.addKeyListener(term.textarea, Key.ENTER, (event: KeyboardEvent) => { this.dispose(); + this.isAttachedCloseListener = false; }); } } + + private disableEnterWhenAttachCloseListener(): boolean { + return this.isAttachedCloseListener; + } }