提交 c956b4a7 编写于 作者: D Dirk Baeumer

Fixes #19267: Terminate task dialog doesn't terminate

上级 0e519843
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import nls = require('vs/nls');
import Filters = require('vs/base/common/filters');
import { TPromise } from 'vs/base/common/winjs.base';
import Quickopen = require('vs/workbench/browser/quickopen');
import QuickOpen = require('vs/base/parts/quickopen/common/quickOpen');
import Model = require('vs/base/parts/quickopen/browser/quickOpenModel');
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { Task } from 'vs/workbench/parts/tasks/common/tasks';
import { ITaskService } from 'vs/workbench/parts/tasks/common/taskService';
class TaskEntry extends Model.QuickOpenEntry {
private taskService: ITaskService;
private task: Task;
constructor(taskService: ITaskService, task: Task, highlights: Model.IHighlight[] = []) {
super(highlights);
this.taskService = taskService;
this.task = task;
}
public getLabel(): string {
return this.task.name;
}
public getAriaLabel(): string {
return nls.localize('entryAriaLabel', "{0}, tasks", this.getLabel());
}
public run(mode: QuickOpen.Mode, context: Model.IContext): boolean {
if (mode === QuickOpen.Mode.PREVIEW) {
return false;
}
this.taskService.terminate(this.task._id);
return true;
}
}
export class QuickOpenHandler extends Quickopen.QuickOpenHandler {
private quickOpenService: IQuickOpenService;
private taskService: ITaskService;
constructor(
@IQuickOpenService quickOpenService: IQuickOpenService,
@ITaskService taskService: ITaskService
) {
super();
this.quickOpenService = quickOpenService;
this.taskService = taskService;
}
public getAriaLabel(): string {
return nls.localize('tasksAriaLabel', "Type the name of a task to terminate");
}
public getResults(input: string): TPromise<Model.QuickOpenModel> {
return this.taskService.getActiveTasks().then(tasks => tasks
.sort((a, b) => a.name.localeCompare(b.name))
.map(task => ({ task: task, highlights: Filters.matchesContiguousSubString(input, task.name) }))
.filter(({ highlights }) => !!highlights)
.map(({ task, highlights }) => new TaskEntry(this.taskService, task, highlights))
, _ => []).then(e => new Model.QuickOpenModel(e));
}
public getClass(): string {
return null;
}
public canRun(): boolean {
return true;
}
public getAutoFocus(input: string): QuickOpen.IAutoFocus {
return {
autoFocusFirstEntry: !!input
};
}
public onClose(canceled: boolean): void {
return;
}
public getGroupLabel(): string {
return null;
}
public getEmptyLabel(searchString: string): string {
if (searchString.length > 0) {
return nls.localize('noTasksMatching', "No tasks matching");
}
return nls.localize('noTasksFound', "No tasks to terminate found");
}
}
......@@ -37,7 +37,9 @@ export interface ITaskService extends IEventEmitter {
run(task: string | Task): TPromise<ITaskSummary>;
inTerminal(): boolean;
isActive(): TPromise<boolean>;
terminate(): TPromise<TerminateResponse>;
getActiveTasks(): TPromise<Task[]>;
terminate(id: string): TPromise<TerminateResponse>;
terminateAll(): TPromise<TerminateResponse>;
tasks(): TPromise<Task[]>;
registerTaskProvider(handle: number, taskProvider: ITaskProvider): void;
......
......@@ -100,6 +100,8 @@ export interface ITaskSystem extends IEventEmitter {
run(task: Task, resolver: ITaskResolver): ITaskExecuteResult;
isActive(): TPromise<boolean>;
isActiveSync(): boolean;
getActiveTasks(): Task[];
canAutoTerminate(): boolean;
terminate(): TPromise<TerminateResponse>;
terminate(id: string): TPromise<TerminateResponse>;
terminateAll(): TPromise<TerminateResponse>;
}
\ No newline at end of file
......@@ -7,6 +7,7 @@
import 'vs/css!./media/task.contribution';
import 'vs/workbench/parts/tasks/browser/taskQuickOpen';
import 'vs/workbench/parts/tasks/browser/terminateQuickOpen';
import * as nls from 'vs/nls';
......@@ -413,10 +414,16 @@ class NullTaskSystem extends EventEmitter implements ITaskSystem {
public isActiveSync(): boolean {
return false;
}
public getActiveTasks(): Task[] {
return [];
}
public canAutoTerminate(): boolean {
return true;
}
public terminate(): TPromise<TerminateResponse> {
public terminate(task: string | Task): TPromise<TerminateResponse> {
return TPromise.as<TerminateResponse>({ success: true });
}
public terminateAll(): TPromise<TerminateResponse> {
return TPromise.as<TerminateResponse>({ success: true });
}
}
......@@ -495,7 +502,6 @@ class TaskService extends EventEmitter implements ITaskService {
private clearTaskSystemPromise: boolean;
private outputChannel: IOutputChannel;
private fileChangesListener: IDisposable;
private providers: Map<number, ITaskProvider>;
constructor( @IModeService modeService: IModeService, @IConfigurationService configurationService: IConfigurationService,
......@@ -597,13 +603,6 @@ class TaskService extends EventEmitter implements ITaskService {
this.taskSystemListeners = dispose(this.taskSystemListeners);
}
private disposeFileChangesListener(): void {
if (this.fileChangesListener) {
this.fileChangesListener.dispose();
this.fileChangesListener = null;
}
}
public registerTaskProvider(handle: number, provider: ITaskProvider): void {
if (!provider) {
return;
......@@ -632,6 +631,14 @@ class TaskService extends EventEmitter implements ITaskService {
return this._taskSystem.isActive();
}
public getActiveTasks(): TPromise<Task[]> {
if (!this._taskSystem) {
return TPromise.as([]);
}
return TPromise.as(this._taskSystem.getActiveTasks());
}
public build(): TPromise<ITaskSummary> {
return this.getTaskSets().then((values) => {
let runnable = this.createRunnableTask(values, (set) => set.buildTasks);
......@@ -768,13 +775,23 @@ class TaskService extends EventEmitter implements ITaskService {
});
}
public terminate(): TPromise<TerminateResponse> {
public terminate(task: string | Task): TPromise<TerminateResponse> {
if (!this._taskSystem) {
return TPromise.as({ success: true });
}
return this._taskSystem.terminate().then((response) => {
const id: string = Types.isString(task) ? task : task._id;
return this._taskSystem.terminate(id).then((response) => {
this.emit(TaskServiceEvents.Terminated, {});
return response;
});
}
public terminateAll(): TPromise<TerminateResponse> {
if (!this._taskSystem) {
return TPromise.as({ success: true });
}
return this._taskSystem.terminateAll().then((response) => {
this.emit(TaskServiceEvents.Terminated, {});
this.disposeFileChangesListener();
return response;
});
}
......@@ -985,11 +1002,10 @@ class TaskService extends EventEmitter implements ITaskService {
message: nls.localize('TaskSystem.runningTask', 'There is a task running. Do you want to terminate it?'),
primaryButton: nls.localize({ key: 'TaskSystem.terminateTask', comment: ['&& denotes a mnemonic'] }, "&&Terminate Task")
})) {
return this._taskSystem.terminate().then((response) => {
return this._taskSystem.terminateAll().then((response) => {
if (response.success) {
this.emit(TaskServiceEvents.Terminated, {});
this._taskSystem = null;
this.disposeFileChangesListener();
this.disposeTaskSystemListeners();
return false; // no veto
} else if (response.code && response.code === TerminateResponseCode.ProcessNotFound) {
......@@ -1079,14 +1095,22 @@ class TaskService extends EventEmitter implements ITaskService {
return;
}
if (this.inTerminal()) {
this.messageService.show(Severity.Info, {
message: nls.localize('TerminateAction.terminalSystem', 'The tasks are executed in the integrated terminal. Use the terminal to manage the tasks.'),
actions: [new ViewTerminalAction(this.terminalService), new CloseMessageAction()]
});
if (!this._taskSystem) {
return;
}
let activeTasks = this._taskSystem.getActiveTasks();
if (activeTasks.length === 0) {
return;
}
if (activeTasks.length === 1) {
this._taskSystem.terminate(activeTasks[0]._id);
} else {
this.quickOpenService.show('terminate task ');
}
} else {
this.isActive().then((active) => {
if (active) {
this.terminate().then((response) => {
this.terminateAll().then((response) => {
if (response.success) {
return undefined;
} else if (response.code && response.code === TerminateResponseCode.ProcessNotFound) {
......@@ -1118,12 +1142,23 @@ MenuRegistry.addCommand({ id: 'workbench.action.tasks.test', title: nls.localize
registerSingleton(ITaskService, TaskService);
// Register Quick Open
(<IQuickOpenRegistry>Registry.as(QuickOpenExtensions.Quickopen)).registerQuickOpenHandler(
const quickOpenRegistry = (<IQuickOpenRegistry>Registry.as(QuickOpenExtensions.Quickopen));
quickOpenRegistry.registerQuickOpenHandler(
new QuickOpenHandlerDescriptor(
'vs/workbench/parts/tasks/browser/taskQuickOpen',
'QuickOpenHandler',
'task ',
nls.localize('taskCommands', "Run Task")
nls.localize('quickOpen.task', "Run Task")
)
);
quickOpenRegistry.registerQuickOpenHandler(
new QuickOpenHandlerDescriptor(
'vs/workbench/parts/tasks/browser/terminateQuickOpen',
'QuickOpenHandler',
'terminate task ',
nls.localize('quickOpen.terminateTask', "Terminate Task")
)
);
......
......@@ -166,7 +166,20 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem {
return Object.keys(this.activeTasks).every(key => !this.activeTasks[key].task.promptOnClose);
}
public terminate(): TPromise<TerminateResponse> {
public getActiveTasks(): Task[] {
return Object.keys(this.activeTasks).map(key => this.activeTasks[key].task);
}
public terminate(id: string): TPromise<TerminateResponse> {
let terminalData = this.activeTasks[id];
if (!terminalData) {
return TPromise.as<TerminateResponse>({ success: false });
};
terminalData.terminal.dispose();
return TPromise.as<TerminateResponse>({ success: true });
}
public terminateAll(): TPromise<TerminateResponse> {
Object.keys(this.activeTasks).forEach((key) => {
let data = this.activeTasks[key];
data.terminal.dispose();
......
......@@ -74,6 +74,14 @@ export class ProcessTaskSystem extends EventEmitter implements ITaskSystem {
return !!this.childProcess;
}
public getActiveTasks(): Task[] {
let result: Task[] = [];
if (this.activeTask) {
result.push(this.activeTask);
}
return result;
}
public run(task: Task): ITaskExecuteResult {
if (this.activeTask) {
return { kind: TaskExecuteKind.Active, active: { same: this.activeTask._id === task._id, background: this.activeTask.isBackground }, promise: this.activeTaskPromise };
......@@ -95,7 +103,14 @@ export class ProcessTaskSystem extends EventEmitter implements ITaskSystem {
return true;
}
public terminate(): TPromise<TerminateResponse> {
public terminate(_id: string): TPromise<TerminateResponse> {
if (!this.activeTask || this.activeTask._id !== _id) {
return TPromise.as<TerminateResponse>({ success: false });
}
return this.terminateAll();
}
public terminateAll(): TPromise<TerminateResponse> {
if (this.childProcess) {
return this.childProcess.terminate();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册