mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 09:08:48 +01:00
Implements #45664: Add API to query and execute tasks
This commit is contained in:
Vendored
+46
-13
@@ -781,32 +781,65 @@ declare module 'vscode' {
|
||||
//#region Tasks
|
||||
|
||||
/**
|
||||
* A task item represents a task in the system. It can be used to
|
||||
* present task information in the user interface or to execute the
|
||||
* underlying task.
|
||||
* An object representing an executed Task. It can be used
|
||||
* to terminate a task.
|
||||
*/
|
||||
export interface TaskItem {
|
||||
export interface TaskExecution {
|
||||
}
|
||||
|
||||
/**
|
||||
* An event signaling the start of a task execution.
|
||||
*/
|
||||
interface TaskStartEvent {
|
||||
/**
|
||||
* The task item representing the task that got started.
|
||||
*/
|
||||
execution: TaskExecution;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event signaling the end of an executed task.
|
||||
*/
|
||||
interface TaskEndEvent {
|
||||
/**
|
||||
* The task item representing the task that finished.
|
||||
*/
|
||||
execution: TaskExecution;
|
||||
}
|
||||
|
||||
export namespace workspace {
|
||||
|
||||
/**
|
||||
* A unique ID representing the underlying task.
|
||||
* Fetches all task available in the systems. This includes tasks
|
||||
* from `tasks.json` files as well as tasks from task providers
|
||||
* contributed through extensions.
|
||||
*/
|
||||
readonly id: string;
|
||||
export function fetchTasks(): Thenable<Task[]>;
|
||||
|
||||
/**
|
||||
* A human readable label of the task.
|
||||
* Executes a task that is managed by VS Code. The returned
|
||||
* task execution can be used to terminate the task.
|
||||
*
|
||||
* @param task the task to execute
|
||||
*/
|
||||
readonly label: string;
|
||||
export function executeTask(task: Task): Thenable<TaskExecution>;
|
||||
|
||||
/**
|
||||
* The task definition.
|
||||
* Fires when a task starts.
|
||||
*/
|
||||
readonly definition: TaskDefinition;
|
||||
export const onDidStartTask: Event<TaskStartEvent>;
|
||||
|
||||
/**
|
||||
* The workspace folder the task belongs to. Is undefined
|
||||
* to tasks that aren't scoped to a workspace folder.
|
||||
* Terminates a task that was previously started using `executeTask`
|
||||
*
|
||||
* @param task the task to terminate
|
||||
*/
|
||||
readonly workspaceFolder: WorkspaceFolder | undefined;
|
||||
export function terminateTask(task: TaskExecution): void;
|
||||
|
||||
/**
|
||||
* Fires when a task ends.
|
||||
*/
|
||||
export const onDidEndTask: Event<TaskEndEvent>;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -4,16 +4,327 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as crypto from 'crypto';
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
import * as Objects from 'vs/base/common/objects';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as Types from 'vs/base/common/types';
|
||||
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
|
||||
import { ContributedTask, ExtensionTaskSourceTransfer } from 'vs/workbench/parts/tasks/common/tasks';
|
||||
import {
|
||||
ContributedTask, ExtensionTaskSourceTransfer, TaskIdentifier, TaskExecution, Task, TaskEvent, TaskEventKind,
|
||||
PresentationOptions, CommandOptions, CommandConfiguration, RuntimeType, CustomTask, TaskScope, TaskSource, TaskSourceKind, ExtensionTaskSource
|
||||
} from 'vs/workbench/parts/tasks/common/tasks';
|
||||
import { ITaskService } from 'vs/workbench/parts/tasks/common/taskService';
|
||||
|
||||
import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape, MainContext, IExtHostContext } from '../node/extHost.protocol';
|
||||
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape, MainContext, IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import {
|
||||
TaskDefinitionDTO, TaskExecutionDTO, ProcessExecutionOptionsDTO, TaskPresentationOptionsDTO,
|
||||
ProcessExecutionDTO, ShellExecutionDTO, ShellExecutionOptionsDTO, TaskDTO, TaskSourceDTO, TaskHandleDTO
|
||||
} from 'vs/workbench/api/shared/tasks';
|
||||
|
||||
export { TaskDTO, TaskHandleDTO, TaskExecutionDTO };
|
||||
|
||||
namespace TaskExecutionDTO {
|
||||
export function from(value: TaskExecution): TaskExecutionDTO {
|
||||
return {
|
||||
id: value.id,
|
||||
};
|
||||
}
|
||||
export function to(value: TaskExecutionDTO, workspace: IWorkspaceContextService): TaskExecution {
|
||||
return {
|
||||
id: value.id,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskDefinitionDTO {
|
||||
export function from(value: TaskIdentifier): TaskDefinitionDTO {
|
||||
let result = Objects.assign(Object.create(null), value);
|
||||
delete result._key;
|
||||
return result;
|
||||
}
|
||||
export function to(value: TaskDefinitionDTO): TaskIdentifier {
|
||||
const hash = crypto.createHash('md5');
|
||||
hash.update(JSON.stringify(value));
|
||||
let result = Objects.assign(Object.create(null), value);
|
||||
result._key = hash.digest('hex');
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskPresentationOptionsDTO {
|
||||
export function from(value: PresentationOptions): TaskPresentationOptionsDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return Objects.assign(Object.create(null), value);
|
||||
}
|
||||
export function to(value: TaskPresentationOptionsDTO): PresentationOptions {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return Objects.assign(Object.create(null), value);
|
||||
}
|
||||
}
|
||||
|
||||
namespace ProcessExecutionOptionsDTO {
|
||||
export function from(value: CommandOptions): ProcessExecutionOptionsDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
cwd: value.cwd,
|
||||
env: value.env
|
||||
};
|
||||
}
|
||||
export function to(value: ProcessExecutionOptionsDTO): CommandOptions {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
cwd: value.cwd,
|
||||
env: value.env
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace ProcessExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ProcessExecutionDTO {
|
||||
let candidate = value as ProcessExecutionDTO;
|
||||
return candidate && !!candidate.process;
|
||||
}
|
||||
export function from(value: CommandConfiguration): ProcessExecutionDTO {
|
||||
let process: string = Types.isString(value.name) ? value.name : value.name.value;
|
||||
let args: string[] = value.args ? value.args.map(value => Types.isString(value) ? value : value.value) : [];
|
||||
let result: ProcessExecutionDTO = {
|
||||
process: process,
|
||||
args: args
|
||||
};
|
||||
if (value.options) {
|
||||
result.options = ProcessExecutionOptionsDTO.from(value.options);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export function to(value: ProcessExecutionDTO): CommandConfiguration {
|
||||
let result: CommandConfiguration = {
|
||||
runtime: RuntimeType.Process,
|
||||
name: value.process,
|
||||
args: value.args,
|
||||
presentation: undefined
|
||||
};
|
||||
if (value.options) {
|
||||
result.options = ProcessExecutionOptionsDTO.to(value.options);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ShellExecutionOptionsDTO {
|
||||
export function from(value: CommandOptions): ShellExecutionOptionsDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
let result: ShellExecutionOptionsDTO = {
|
||||
cwd: value.cwd,
|
||||
env: value.env
|
||||
};
|
||||
if (value.shell) {
|
||||
result.executable = value.shell.executable;
|
||||
result.shellArgs = value.shell.args;
|
||||
result.shellQuoting = value.shell.quoting;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export function to(value: ShellExecutionOptionsDTO): CommandOptions {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
let result: CommandOptions = {
|
||||
cwd: value.cwd,
|
||||
env: value.env
|
||||
};
|
||||
if (value.executable) {
|
||||
result.shell = {
|
||||
executable: value.executable
|
||||
};
|
||||
if (value.shellArgs) {
|
||||
result.shell.args = value.shellArgs;
|
||||
}
|
||||
if (value.shellQuoting) {
|
||||
result.shell.quoting = value.shellQuoting;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ShellExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ShellExecutionDTO {
|
||||
let candidate = value as ShellExecutionDTO;
|
||||
return candidate && (!!candidate.commandLine || !!candidate.command);
|
||||
}
|
||||
export function from(value: CommandConfiguration): ShellExecutionDTO {
|
||||
let result: ShellExecutionDTO = {};
|
||||
if (value.name && Types.isString(value.name) && (value.args === void 0 || value.args === null || value.args.length === 0)) {
|
||||
result.commandLine = value.name;
|
||||
} else {
|
||||
result.command = value.name;
|
||||
result.args = value.args;
|
||||
}
|
||||
if (value.options) {
|
||||
result.options = ShellExecutionOptionsDTO.from(value.options);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export function to(value: ShellExecutionDTO): CommandConfiguration {
|
||||
let result: CommandConfiguration = {
|
||||
runtime: RuntimeType.Shell,
|
||||
name: value.commandLine ? value.commandLine : value.command,
|
||||
args: value.args,
|
||||
presentation: undefined
|
||||
};
|
||||
if (value.options) {
|
||||
result.options = ShellExecutionOptionsDTO.to(value.options);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskSourceDTO {
|
||||
export function from(value: TaskSource): TaskSourceDTO {
|
||||
let result: TaskSourceDTO = {
|
||||
label: value.label
|
||||
};
|
||||
if (value.kind === TaskSourceKind.Extension) {
|
||||
result.extensionId = value.extension;
|
||||
if (value.workspaceFolder) {
|
||||
result.scope = value.workspaceFolder.uri;
|
||||
} else {
|
||||
result.scope = value.scope;
|
||||
}
|
||||
} else if (value.kind === TaskSourceKind.Workspace) {
|
||||
result.extensionId = '$core';
|
||||
result.scope = value.config.workspaceFolder.uri;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export function to(value: TaskSourceDTO, workspace: IWorkspaceContextService): ExtensionTaskSource {
|
||||
let scope: TaskScope;
|
||||
let workspaceFolder: IWorkspaceFolder;
|
||||
if (value.scope === void 0) {
|
||||
if (workspace.getWorkspace().folders.length === 0) {
|
||||
scope = TaskScope.Global;
|
||||
workspaceFolder = undefined;
|
||||
} else {
|
||||
scope = TaskScope.Folder;
|
||||
workspaceFolder = workspace.getWorkspace().folders[0];
|
||||
}
|
||||
} else if (typeof value.scope === 'number') {
|
||||
scope = value.scope;
|
||||
} else {
|
||||
scope = TaskScope.Folder;
|
||||
workspaceFolder = workspace.getWorkspaceFolder(URI.revive(value.scope));
|
||||
}
|
||||
let result: ExtensionTaskSource = {
|
||||
kind: TaskSourceKind.Extension,
|
||||
label: value.label,
|
||||
extension: value.extensionId,
|
||||
scope,
|
||||
workspaceFolder
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskHandleDTO {
|
||||
export function is(value: any): value is TaskHandleDTO {
|
||||
let candidate: TaskHandleDTO = value;
|
||||
return candidate && Types.isString(candidate.id) && !!candidate.workspaceFolder;
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskDTO {
|
||||
export function from(task: Task): TaskDTO {
|
||||
if (task === void 0 || task === null || (!CustomTask.is(task) && !ContributedTask.is(task))) {
|
||||
return undefined;
|
||||
}
|
||||
let result: TaskDTO = {
|
||||
_id: task._id,
|
||||
name: task.name,
|
||||
definition: TaskDefinitionDTO.from(Task.getTaskDefinition(task)),
|
||||
source: TaskSourceDTO.from(task._source),
|
||||
execution: undefined,
|
||||
presentationOptions: task.command ? TaskPresentationOptionsDTO.from(task.command.presentation) : undefined,
|
||||
isBackground: task.isBackground,
|
||||
problemMatchers: [],
|
||||
hasDefinedMatchers: ContributedTask.is(task) ? task.hasDefinedMatchers : false
|
||||
};
|
||||
if (task.group) {
|
||||
result.group = task.group;
|
||||
}
|
||||
if (task.command) {
|
||||
if (task.command.runtime === RuntimeType.Process) {
|
||||
result.execution = ProcessExecutionDTO.from(task.command);
|
||||
} else if (task.command.runtime === RuntimeType.Shell) {
|
||||
result.execution = ShellExecutionDTO.from(task.command);
|
||||
}
|
||||
}
|
||||
if (task.problemMatchers) {
|
||||
for (let matcher of task.problemMatchers) {
|
||||
if (Types.isString(matcher)) {
|
||||
result.problemMatchers.push(matcher);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!result.execution) {
|
||||
return undefined;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function to(task: TaskDTO, workspace: IWorkspaceContextService): Task {
|
||||
if (typeof task.name !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
let command: CommandConfiguration;
|
||||
if (ShellExecutionDTO.is(task.execution)) {
|
||||
command = ShellExecutionDTO.to(task.execution);
|
||||
} else if (ProcessExecutionDTO.is(task.execution)) {
|
||||
command = ProcessExecutionDTO.to(task.execution);
|
||||
}
|
||||
if (!command) {
|
||||
return undefined;
|
||||
}
|
||||
command.presentation = TaskPresentationOptionsDTO.to(task.presentationOptions);
|
||||
let source = TaskSourceDTO.to(task.source, workspace);
|
||||
|
||||
let label = nls.localize('task.label', '{0}: {1}', source.label, task.name);
|
||||
let definition = TaskDefinitionDTO.to(task.definition);
|
||||
let id = `${task.source.extensionId}.${definition._key}`;
|
||||
let result: ContributedTask = {
|
||||
_id: id, // uuidMap.getUUID(identifier),
|
||||
_source: source,
|
||||
_label: label,
|
||||
type: definition.type,
|
||||
defines: definition,
|
||||
name: task.name,
|
||||
identifier: label,
|
||||
group: task.group,
|
||||
command: command,
|
||||
isBackground: !!task.isBackground,
|
||||
problemMatchers: task.problemMatchers.slice(),
|
||||
hasDefinedMatchers: task.hasDefinedMatchers
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadTask)
|
||||
export class MainThreadTask implements MainThreadTaskShape {
|
||||
@@ -28,6 +339,14 @@ export class MainThreadTask implements MainThreadTaskShape {
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTask);
|
||||
this._activeHandles = Object.create(null);
|
||||
this._taskService.onDidStateChange((event: TaskEvent) => {
|
||||
let task = event.__task;
|
||||
if (event.kind === TaskEventKind.Start) {
|
||||
this._proxy.$taskStarted(TaskExecutionDTO.from(Task.getTaskExecution(task)));
|
||||
} else if (event.kind === TaskEventKind.End) {
|
||||
this._proxy.$taskEnded(TaskExecutionDTO.from(Task.getTaskExecution(task)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
@@ -63,4 +382,60 @@ export class MainThreadTask implements MainThreadTaskShape {
|
||||
delete this._activeHandles[handle];
|
||||
return TPromise.wrap<void>(undefined);
|
||||
}
|
||||
|
||||
public $executeTaskProvider(): TPromise<TaskDTO[]> {
|
||||
return this._taskService.tasks().then((tasks) => {
|
||||
let result: TaskDTO[] = [];
|
||||
for (let task of tasks) {
|
||||
let item = TaskDTO.from(task);
|
||||
if (item) {
|
||||
result.push(item);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
public $executeTask(value: TaskHandleDTO | TaskDTO): TPromise<TaskExecutionDTO> {
|
||||
return new TPromise<TaskExecutionDTO>((resolve, reject) => {
|
||||
if (TaskHandleDTO.is(value)) {
|
||||
let workspaceFolder = this._workspaceContextServer.getWorkspaceFolder(URI.revive(value.workspaceFolder));
|
||||
this._taskService.getTask(workspaceFolder, value.id, true).then((task: Task) => {
|
||||
this._taskService.run(task);
|
||||
let result: TaskExecutionDTO = {
|
||||
id: value.id
|
||||
};
|
||||
resolve(result);
|
||||
}, (error) => {
|
||||
reject(new Error('Task not found'));
|
||||
});
|
||||
} else {
|
||||
let task = TaskDTO.to(value, this._workspaceContextServer);
|
||||
this._taskService.run(task);
|
||||
let result: TaskExecutionDTO = {
|
||||
id: task._id
|
||||
};
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public $terminateTask(value: TaskExecutionDTO): TPromise<void> {
|
||||
let execution: TaskExecution = TaskExecutionDTO.to(value, this._workspaceContextServer);
|
||||
return new TPromise<void>((resolve, reject) => {
|
||||
this._taskService.getActiveTasks().then((tasks) => {
|
||||
for (let task of tasks) {
|
||||
if (execution.id === task._id) {
|
||||
this._taskService.terminate(task).then((value) => {
|
||||
resolve(undefined);
|
||||
}, (error) => {
|
||||
reject(undefined);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
reject(new Error('Task to terminate not found'));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ export function createApiFactory(
|
||||
const extHostLanguages = new ExtHostLanguages(rpcProtocol);
|
||||
|
||||
// Register API-ish commands
|
||||
ExtHostApiCommands.register(extHostCommands, extHostWorkspace);
|
||||
ExtHostApiCommands.register(extHostCommands, extHostTask);
|
||||
|
||||
return function (extension: IExtensionDescription): typeof vscode {
|
||||
|
||||
@@ -517,6 +517,21 @@ export function createApiFactory(
|
||||
registerTaskProvider: (type: string, provider: vscode.TaskProvider) => {
|
||||
return extHostTask.registerTaskProvider(extension, provider);
|
||||
},
|
||||
fetchTasks: proposedApiFunction(extension, (): Thenable<vscode.Task[]> => {
|
||||
return extHostTask.executeTaskProvider();
|
||||
}),
|
||||
executeTask: proposedApiFunction(extension, (task: vscode.Task): Thenable<vscode.TaskExecution> => {
|
||||
return extHostTask.executeTask(extension, task);
|
||||
}),
|
||||
onDidStartTask: (listeners, thisArgs?, disposables?) => {
|
||||
return extHostTask.onDidStartTask(listeners, thisArgs, disposables);
|
||||
},
|
||||
terminateTask: proposedApiFunction(extension, (task: vscode.TaskExecution): void => {
|
||||
extHostTask.terminateTask(task);
|
||||
}),
|
||||
onDidEndTask: (listeners, thisArgs?, disposables?) => {
|
||||
return extHostTask.onDidEndTask(listeners, thisArgs, disposables);
|
||||
},
|
||||
registerFileSystemProvider: proposedApiFunction(extension, (scheme, provider) => {
|
||||
return extHostFileSystem.registerFileSystemProvider(scheme, provider);
|
||||
}),
|
||||
|
||||
@@ -48,6 +48,7 @@ import { CommentRule, CharacterPair, EnterAction } from 'vs/editor/common/modes/
|
||||
import { ISingleEditOperation } from 'vs/editor/common/model';
|
||||
import { ILineMatch, IPatternInfo } from 'vs/platform/search/common/search';
|
||||
import { LogLevel } from 'vs/platform/log/common/log';
|
||||
import { TaskExecutionDTO, TaskDTO, TaskHandleDTO } from 'vs/workbench/api/shared/tasks';
|
||||
|
||||
export interface IEnvironment {
|
||||
isExtensionDevelopmentDebug: boolean;
|
||||
@@ -388,6 +389,9 @@ export interface MainThreadFileSystemShape extends IDisposable {
|
||||
|
||||
export interface MainThreadTaskShape extends IDisposable {
|
||||
$registerTaskProvider(handle: number): TPromise<void>;
|
||||
$executeTaskProvider(): TPromise<TaskDTO[]>;
|
||||
$executeTask(task: TaskHandleDTO | TaskDTO): TPromise<TaskExecutionDTO>;
|
||||
$terminateTask(task: TaskExecutionDTO): TPromise<void>;
|
||||
$unregisterTaskProvider(handle: number): TPromise<void>;
|
||||
}
|
||||
|
||||
@@ -727,6 +731,8 @@ export interface ExtHostSCMShape {
|
||||
|
||||
export interface ExtHostTaskShape {
|
||||
$provideTasks(handle: number): TPromise<TaskSet>;
|
||||
$taskStarted(execution: TaskExecutionDTO): void;
|
||||
$taskEnded(execution: TaskExecutionDTO): void;
|
||||
}
|
||||
|
||||
export interface IBreakpointDto {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as Objects from 'vs/base/common/objects';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import * as vscode from 'vscode';
|
||||
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
@@ -18,22 +17,21 @@ import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
|
||||
import { Position as EditorPosition, ITextEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { CustomCodeAction } from 'vs/workbench/api/node/extHostLanguageFeatures';
|
||||
import * as TaskSystem from 'vs/workbench/parts/tasks/common/tasks';
|
||||
import { ExtHostWorkspace } from './extHostWorkspace';
|
||||
import { ExtHostTask } from './extHostTask';
|
||||
|
||||
export class ExtHostApiCommands {
|
||||
|
||||
static register(commands: ExtHostCommands, workspace: ExtHostWorkspace) {
|
||||
static register(commands: ExtHostCommands, workspace: ExtHostTask) {
|
||||
return new ExtHostApiCommands(commands, workspace).registerCommands();
|
||||
}
|
||||
|
||||
private _commands: ExtHostCommands;
|
||||
private _workspace: ExtHostWorkspace;
|
||||
private _tasks: ExtHostTask;
|
||||
private _disposables: IDisposable[] = [];
|
||||
|
||||
private constructor(commands: ExtHostCommands, workspace: ExtHostWorkspace) {
|
||||
private constructor(commands: ExtHostCommands, task: ExtHostTask) {
|
||||
this._commands = commands;
|
||||
this._workspace = workspace;
|
||||
this._tasks = task;
|
||||
}
|
||||
|
||||
registerCommands() {
|
||||
@@ -476,29 +474,8 @@ export class ExtHostApiCommands {
|
||||
.then(tryMapWith(typeConverters.DocumentLink.to));
|
||||
}
|
||||
|
||||
private _executeTaskProvider(): Thenable<vscode.TaskItem[]> {
|
||||
return this._commands.executeCommand<TaskSystem.TaskItemTransfer[]>('_executeTaskProvider').then<vscode.TaskItem[]>((values) => {
|
||||
let workspace = this._workspace;
|
||||
return values.map(handle => {
|
||||
let definition: vscode.TaskDefinition = Objects.assign(Object.create(null), handle.definition);
|
||||
delete definition._key;
|
||||
let uri = URI.revive(handle.workspaceFolderUri);
|
||||
return new class {
|
||||
get id(): string {
|
||||
return handle.id;
|
||||
}
|
||||
get label(): string {
|
||||
return handle.label;
|
||||
}
|
||||
get definition(): vscode.TaskDefinition {
|
||||
return definition;
|
||||
}
|
||||
get workspaceFolder(): vscode.WorkspaceFolder {
|
||||
return uri ? workspace.resolveWorkspaceFolder(uri) : undefined;
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
private _executeTaskProvider(): Thenable<vscode.Task[]> {
|
||||
return this._tasks.executeTaskProvider();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
import URI, { UriComponents } from 'vs/base/common/uri';
|
||||
import * as nls from 'vs/nls';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as Objects from 'vs/base/common/objects';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import * as TaskSystem from 'vs/workbench/parts/tasks/common/tasks';
|
||||
@@ -18,7 +19,12 @@ import { MainContext, MainThreadTaskShape, ExtHostTaskShape, IMainContext } from
|
||||
import * as types from 'vs/workbench/api/node/extHostTypes';
|
||||
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
|
||||
import * as vscode from 'vscode';
|
||||
import {
|
||||
TaskDefinitionDTO, TaskExecutionDTO, TaskPresentationOptionsDTO, ProcessExecutionOptionsDTO, ProcessExecutionDTO,
|
||||
ShellExecutionOptionsDTO, ShellExecutionDTO, TaskDTO, TaskHandleDTO
|
||||
} from '../shared/tasks';
|
||||
|
||||
export { TaskExecutionDTO };
|
||||
|
||||
/*
|
||||
namespace ProblemPattern {
|
||||
@@ -450,6 +456,240 @@ namespace Tasks {
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskDefinitionDTO {
|
||||
export function from(value: vscode.TaskDefinition): TaskDefinitionDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
export function to(value: TaskDefinitionDTO): vscode.TaskDefinition {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskPresentationOptionsDTO {
|
||||
export function from(value: vscode.TaskPresentationOptions): TaskPresentationOptionsDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
export function to(value: TaskPresentationOptionsDTO): vscode.TaskPresentationOptions {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ProcessExecutionOptionsDTO {
|
||||
export function from(value: vscode.ProcessExecutionOptions): ProcessExecutionOptionsDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
export function to(value: ProcessExecutionOptionsDTO): vscode.ProcessExecutionOptions {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ProcessExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ProcessExecutionDTO {
|
||||
let candidate = value as ProcessExecutionDTO;
|
||||
return candidate && !!candidate.process;
|
||||
}
|
||||
export function from(value: vscode.ProcessExecution): ProcessExecutionDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
let result: ProcessExecutionDTO = {
|
||||
process: value.process,
|
||||
args: value.args
|
||||
};
|
||||
if (value.options) {
|
||||
result.options = ProcessExecutionOptionsDTO.from(value.options);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export function to(value: ProcessExecutionDTO): types.ProcessExecution {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return new types.ProcessExecution(value.process, value.args, value.options);
|
||||
}
|
||||
}
|
||||
|
||||
namespace ShellExecutionOptionsDTO {
|
||||
export function from(value: vscode.ShellExecutionOptions): ShellExecutionOptionsDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
export function to(value: ShellExecutionOptionsDTO): vscode.ShellExecutionOptions {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ShellExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ShellExecutionDTO {
|
||||
let candidate = value as ShellExecutionDTO;
|
||||
return candidate && (!!candidate.commandLine || !!candidate.command);
|
||||
}
|
||||
export function from(value: vscode.ShellExecution): ShellExecutionDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
let result: ShellExecutionDTO = {
|
||||
};
|
||||
if (value.commandLine !== void 0) {
|
||||
result.commandLine = value.commandLine;
|
||||
} else {
|
||||
result.command = value.command;
|
||||
result.args = value.args;
|
||||
}
|
||||
if (value.options) {
|
||||
result.options = ShellExecutionOptionsDTO.from(value.options);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export function to(value: ShellExecutionDTO): types.ShellExecution {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
if (value.commandLine) {
|
||||
return new types.ShellExecution(value.commandLine, value.options);
|
||||
} else {
|
||||
return new types.ShellExecution(value.command, value.args ? value.args : [], value.options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskHandleDTO {
|
||||
export function from(value: types.Task): TaskHandleDTO {
|
||||
let folder: UriComponents;
|
||||
if (value.scope !== void 0 && typeof value.scope !== 'number') {
|
||||
folder = value.scope.uri;
|
||||
}
|
||||
return {
|
||||
id: value._id,
|
||||
workspaceFolder: folder
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskDTO {
|
||||
|
||||
export function from(value: vscode.Task, extension: IExtensionDescription): TaskDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
let execution: ShellExecutionDTO | ProcessExecutionDTO;
|
||||
if (value.execution instanceof types.ProcessExecution) {
|
||||
execution = ProcessExecutionDTO.from(value.execution);
|
||||
} else if (value.execution instanceof types.ShellExecution) {
|
||||
execution = ShellExecutionDTO.from(value.execution);
|
||||
}
|
||||
let definition: TaskDefinitionDTO = TaskDefinitionDTO.from(value.definition);
|
||||
let scope: number | UriComponents;
|
||||
if (value.scope) {
|
||||
if (typeof value.scope === 'number') {
|
||||
scope = value.scope;
|
||||
} else {
|
||||
scope = value.scope.uri.toJSON();
|
||||
}
|
||||
}
|
||||
if (!execution || !definition || !scope) {
|
||||
return undefined;
|
||||
}
|
||||
let result: TaskDTO = {
|
||||
_id: (value as types.Task)._id,
|
||||
definition,
|
||||
name: value.name,
|
||||
source: {
|
||||
extensionId: extension.id,
|
||||
label: value.source,
|
||||
scope: scope
|
||||
},
|
||||
execution,
|
||||
isBackground: value.isBackground,
|
||||
group: (value.group as types.TaskGroup).id,
|
||||
presentationOptions: TaskPresentationOptionsDTO.from(value.presentationOptions),
|
||||
problemMatchers: value.problemMatchers,
|
||||
hasDefinedMatchers: (value as types.Task).hasDefinedMatchers
|
||||
};
|
||||
return result;
|
||||
}
|
||||
export function to(value: TaskDTO, workspace: ExtHostWorkspace): types.Task {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
let execution: types.ShellExecution | types.ProcessExecution;
|
||||
if (ProcessExecutionDTO.is(value.execution)) {
|
||||
execution = ProcessExecutionDTO.to(value.execution);
|
||||
} else if (ShellExecutionDTO.is(value.execution)) {
|
||||
execution = ShellExecutionDTO.to(value.execution);
|
||||
}
|
||||
let definition: vscode.TaskDefinition = TaskDefinitionDTO.to(value.definition);
|
||||
let scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder;
|
||||
if (value.source) {
|
||||
if (value.source.scope !== void 0) {
|
||||
if (typeof value.source.scope === 'number') {
|
||||
scope = value.source.scope;
|
||||
} else {
|
||||
scope = workspace.resolveWorkspaceFolder(URI.revive(value.source.scope));
|
||||
}
|
||||
} else {
|
||||
scope = types.TaskScope.Workspace;
|
||||
}
|
||||
}
|
||||
if (!execution || !definition || !scope) {
|
||||
return undefined;
|
||||
}
|
||||
let result = new types.Task(definition, scope, value.name, value.source.label, execution, value.problemMatchers);
|
||||
if (value.isBackground !== void 0) {
|
||||
result.isBackground = value.isBackground;
|
||||
}
|
||||
if (value.group !== void 0) {
|
||||
result.group = types.TaskGroup.from(value.group);
|
||||
}
|
||||
if (value.presentationOptions) {
|
||||
result.presentationOptions = TaskPresentationOptionsDTO.to(value.presentationOptions);
|
||||
}
|
||||
if (value._id) {
|
||||
result._id = value._id;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
class TaskExecutionImpl implements vscode.TaskExecution {
|
||||
constructor(readonly _id: string) {
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskExecutionDTO {
|
||||
export function to(value: TaskExecutionDTO): vscode.TaskExecution {
|
||||
return new TaskExecutionImpl(value.id);
|
||||
}
|
||||
export function from(value: vscode.TaskExecution): TaskExecutionDTO {
|
||||
return {
|
||||
id: (value as TaskExecutionImpl)._id
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
interface HandlerData {
|
||||
provider: vscode.TaskProvider;
|
||||
extension: IExtensionDescription;
|
||||
@@ -462,6 +702,9 @@ export class ExtHostTask implements ExtHostTaskShape {
|
||||
private _handleCounter: number;
|
||||
private _handlers: Map<number, HandlerData>;
|
||||
|
||||
private readonly _onDidExecuteTask: Emitter<vscode.TaskStartEvent> = new Emitter<vscode.TaskStartEvent>();
|
||||
private readonly _onDidTerminateTask: Emitter<vscode.TaskEndEvent> = new Emitter<vscode.TaskEndEvent>();
|
||||
|
||||
constructor(mainContext: IMainContext, extHostWorkspace: ExtHostWorkspace) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadTask);
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
@@ -482,6 +725,56 @@ export class ExtHostTask implements ExtHostTaskShape {
|
||||
});
|
||||
}
|
||||
|
||||
public executeTaskProvider(): Thenable<vscode.Task[]> {
|
||||
return this._proxy.$executeTaskProvider().then((values) => {
|
||||
let result: vscode.Task[] = [];
|
||||
for (let value of values) {
|
||||
let task = TaskDTO.to(value, this._extHostWorkspace);
|
||||
if (task) {
|
||||
result.push(task);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
public executeTask(extension: IExtensionDescription, task: vscode.Task): Thenable<vscode.TaskExecution> {
|
||||
let tTask = (task as types.Task);
|
||||
// We have a preserved ID. So the task didn't change.
|
||||
if (tTask._id !== void 0) {
|
||||
return this._proxy.$executeTask(TaskHandleDTO.from(tTask)).then(value => TaskExecutionDTO.to(value));
|
||||
} else {
|
||||
return this._proxy.$executeTask(TaskDTO.from(task, extension)).then(value => TaskExecutionDTO.to(value));
|
||||
}
|
||||
}
|
||||
|
||||
public $taskStarted(execution: TaskExecutionDTO): void {
|
||||
this._onDidExecuteTask.fire({
|
||||
execution: TaskExecutionDTO.to(execution)
|
||||
});
|
||||
}
|
||||
|
||||
get onDidStartTask(): Event<vscode.TaskStartEvent> {
|
||||
return this._onDidExecuteTask.event;
|
||||
}
|
||||
|
||||
public terminateTask(execution: vscode.TaskExecution): TPromise<void> {
|
||||
if (!(execution instanceof TaskExecutionImpl)) {
|
||||
throw new Error('No valid task execution provided');
|
||||
}
|
||||
return this._proxy.$terminateTask(TaskExecutionDTO.from(execution));
|
||||
}
|
||||
|
||||
public $taskEnded(execution: TaskExecutionDTO): void {
|
||||
this._onDidTerminateTask.fire({
|
||||
execution: TaskExecutionDTO.to(execution)
|
||||
});
|
||||
}
|
||||
|
||||
get onDidEndTask(): Event<vscode.TaskEndEvent> {
|
||||
return this._onDidTerminateTask.event;
|
||||
}
|
||||
|
||||
public $provideTasks(handle: number): TPromise<TaskSystem.TaskSet> {
|
||||
let handler = this._handlers.get(handle);
|
||||
if (!handler) {
|
||||
|
||||
@@ -1257,6 +1257,21 @@ export class TaskGroup implements vscode.TaskGroup {
|
||||
|
||||
public static Test: TaskGroup = new TaskGroup('test', 'Test');
|
||||
|
||||
public static from(value: string) {
|
||||
switch (value) {
|
||||
case 'clean':
|
||||
return TaskGroup.Clean;
|
||||
case 'build':
|
||||
return TaskGroup.Build;
|
||||
case 'rebuild':
|
||||
return TaskGroup.Rebuild;
|
||||
case 'test':
|
||||
return TaskGroup.Test;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
constructor(id: string, _label: string) {
|
||||
if (typeof id !== 'string') {
|
||||
throw illegalArgument('name');
|
||||
@@ -1411,6 +1426,8 @@ export enum TaskScope {
|
||||
|
||||
export class Task implements vscode.Task {
|
||||
|
||||
private __id: string;
|
||||
|
||||
private _definition: vscode.TaskDefinition;
|
||||
private _definitionKey: string;
|
||||
private _scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder;
|
||||
@@ -1459,6 +1476,18 @@ export class Task implements vscode.Task {
|
||||
this._isBackground = false;
|
||||
}
|
||||
|
||||
get _id(): string {
|
||||
return this.__id;
|
||||
}
|
||||
|
||||
set _id(value: string) {
|
||||
this.__id = value;
|
||||
}
|
||||
|
||||
private clear(): void {
|
||||
this.__id = undefined;
|
||||
}
|
||||
|
||||
get definition(): vscode.TaskDefinition {
|
||||
return this._definition;
|
||||
}
|
||||
@@ -1467,6 +1496,7 @@ export class Task implements vscode.Task {
|
||||
if (value === void 0 || value === null) {
|
||||
throw illegalArgument('Kind can\'t be undefined or null');
|
||||
}
|
||||
this.clear();
|
||||
this._definitionKey = undefined;
|
||||
this._definition = value;
|
||||
}
|
||||
@@ -1485,6 +1515,7 @@ export class Task implements vscode.Task {
|
||||
}
|
||||
|
||||
set target(value: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder) {
|
||||
this.clear();
|
||||
this._scope = value;
|
||||
}
|
||||
|
||||
@@ -1496,6 +1527,7 @@ export class Task implements vscode.Task {
|
||||
if (typeof value !== 'string') {
|
||||
throw illegalArgument('name');
|
||||
}
|
||||
this.clear();
|
||||
this._name = value;
|
||||
}
|
||||
|
||||
@@ -1507,6 +1539,7 @@ export class Task implements vscode.Task {
|
||||
if (value === null) {
|
||||
value = undefined;
|
||||
}
|
||||
this.clear();
|
||||
this._execution = value;
|
||||
}
|
||||
|
||||
@@ -1520,6 +1553,7 @@ export class Task implements vscode.Task {
|
||||
this._hasDefinedMatchers = false;
|
||||
return;
|
||||
}
|
||||
this.clear();
|
||||
this._problemMatchers = value;
|
||||
this._hasDefinedMatchers = true;
|
||||
}
|
||||
@@ -1536,6 +1570,7 @@ export class Task implements vscode.Task {
|
||||
if (value !== true && value !== false) {
|
||||
value = false;
|
||||
}
|
||||
this.clear();
|
||||
this._isBackground = value;
|
||||
}
|
||||
|
||||
@@ -1547,6 +1582,7 @@ export class Task implements vscode.Task {
|
||||
if (typeof value !== 'string' || value.length === 0) {
|
||||
throw illegalArgument('source must be a string of length > 0');
|
||||
}
|
||||
this.clear();
|
||||
this._source = value;
|
||||
}
|
||||
|
||||
@@ -1559,6 +1595,7 @@ export class Task implements vscode.Task {
|
||||
this._group = undefined;
|
||||
return;
|
||||
}
|
||||
this.clear();
|
||||
this._group = value;
|
||||
}
|
||||
|
||||
@@ -1570,6 +1607,7 @@ export class Task implements vscode.Task {
|
||||
if (value === null) {
|
||||
value = undefined;
|
||||
}
|
||||
this.clear();
|
||||
this._presentationOptions = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 { UriComponents } from 'vs/base/common/uri';
|
||||
|
||||
export interface TaskDefinitionDTO {
|
||||
type: string;
|
||||
[name: string]: any;
|
||||
}
|
||||
|
||||
export interface TaskExecutionDTO {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface TaskPresentationOptionsDTO {
|
||||
reveal?: number;
|
||||
echo?: boolean;
|
||||
focus?: boolean;
|
||||
panel?: number;
|
||||
}
|
||||
|
||||
export interface ExecutionOptionsDTO {
|
||||
cwd?: string;
|
||||
env?: { [key: string]: string };
|
||||
}
|
||||
|
||||
export interface ProcessExecutionOptionsDTO extends ExecutionOptionsDTO {
|
||||
}
|
||||
|
||||
export interface ProcessExecutionDTO {
|
||||
process: string;
|
||||
args: string[];
|
||||
options?: ProcessExecutionOptionsDTO;
|
||||
}
|
||||
|
||||
export interface ShellQuotingOptionsDTO {
|
||||
escape?: string | {
|
||||
escapeChar: string;
|
||||
charsToEscape: string;
|
||||
};
|
||||
strong?: string;
|
||||
weak?: string;
|
||||
}
|
||||
|
||||
export interface ShellExecutionOptionsDTO extends ExecutionOptionsDTO {
|
||||
executable?: string;
|
||||
shellArgs?: string[];
|
||||
shellQuoting?: ShellQuotingOptionsDTO;
|
||||
}
|
||||
|
||||
export interface ShellQuotedStringDTO {
|
||||
value: string;
|
||||
quoting: number;
|
||||
}
|
||||
|
||||
export interface ShellExecutionDTO {
|
||||
commandLine?: string;
|
||||
command?: string | ShellQuotedStringDTO;
|
||||
args?: (string | ShellQuotedStringDTO)[];
|
||||
options?: ShellExecutionOptionsDTO;
|
||||
}
|
||||
|
||||
export interface TaskSourceDTO {
|
||||
label: string;
|
||||
extensionId?: string;
|
||||
scope?: number | UriComponents;
|
||||
}
|
||||
|
||||
export interface TaskHandleDTO {
|
||||
id: string;
|
||||
workspaceFolder: UriComponents;
|
||||
}
|
||||
|
||||
export interface TaskDTO {
|
||||
_id: string;
|
||||
name: string;
|
||||
execution: ProcessExecutionDTO | ShellExecutionDTO;
|
||||
definition: TaskDefinitionDTO;
|
||||
isBackground: boolean;
|
||||
source: TaskSourceDTO;
|
||||
group?: string;
|
||||
presentationOptions: TaskPresentationOptionsDTO;
|
||||
problemMatchers: string[];
|
||||
hasDefinedMatchers: boolean;
|
||||
}
|
||||
@@ -47,9 +47,9 @@ export interface ITaskService {
|
||||
terminateAll(): TPromise<TaskTerminateResponse[]>;
|
||||
tasks(): TPromise<Task[]>;
|
||||
/**
|
||||
* @param identifier The task's name, label or defined identifier.
|
||||
* @param alias The task's name, label or defined identifier.
|
||||
*/
|
||||
getTask(workspaceFolder: IWorkspaceFolder | string, identifier: string): TPromise<Task>;
|
||||
getTask(workspaceFolder: IWorkspaceFolder | string, alias: string, compareId?: boolean): TPromise<Task>;
|
||||
getTasksForGroup(group: string): TPromise<Task[]>;
|
||||
getRecentlyUsedTasks(): LinkedMap<string, string>;
|
||||
createSorter(): TaskSorter;
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import URI, { UriComponents } from 'vs/base/common/uri';
|
||||
import * as Types from 'vs/base/common/types';
|
||||
import { IJSONSchemaMap } from 'vs/base/common/jsonSchema';
|
||||
import * as Objects from 'vs/base/common/objects';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { UriComponents } from 'vs/base/common/uri';
|
||||
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ProblemMatcher } from 'vs/workbench/parts/tasks/common/problemMatcher';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { generateUuid } from '../../../../base/common/uuid';
|
||||
|
||||
|
||||
export enum ShellQuoting {
|
||||
@@ -598,8 +598,8 @@ export namespace Task {
|
||||
}
|
||||
}
|
||||
|
||||
export function matches(task: Task, alias: string): boolean {
|
||||
return alias === task._label || alias === task.identifier;
|
||||
export function matches(task: Task, alias: string, compareId: boolean = false): boolean {
|
||||
return alias === task._label || alias === task.identifier || (compareId && alias === task._id);
|
||||
}
|
||||
|
||||
export function getQualifiedLabel(task: Task): string {
|
||||
@@ -610,13 +610,53 @@ export namespace Task {
|
||||
return task._label;
|
||||
}
|
||||
}
|
||||
|
||||
export function getTaskItem(task: Task): TaskItem {
|
||||
let folder: IWorkspaceFolder = Task.getWorkspaceFolder(task);
|
||||
let definition: TaskIdentifier;
|
||||
if (ContributedTask.is(task)) {
|
||||
definition = task.defines;
|
||||
} else if (CustomTask.is(task) && task.command !== void 0) {
|
||||
definition = CustomTask.getDefinition(task);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
let result: TaskItem = {
|
||||
id: task._id,
|
||||
label: task._label,
|
||||
definition: definition,
|
||||
workspaceFolder: folder
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getTaskDefinition(task: Task): TaskIdentifier {
|
||||
if (ContributedTask.is(task)) {
|
||||
return task.defines;
|
||||
} else if (CustomTask.is(task) && task.command !== void 0) {
|
||||
return CustomTask.getDefinition(task);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function getTaskExecution(task: Task): TaskExecution {
|
||||
let result: TaskExecution = {
|
||||
id: task._id
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export interface TaskItemTransfer {
|
||||
export interface TaskItem {
|
||||
id: string;
|
||||
label: string;
|
||||
definition: TaskIdentifier;
|
||||
workspaceFolderUri: URI;
|
||||
workspaceFolder: IWorkspaceFolder;
|
||||
}
|
||||
|
||||
export interface TaskExecution {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export enum ExecutionEngine {
|
||||
@@ -679,10 +719,12 @@ export class TaskSorter {
|
||||
}
|
||||
|
||||
export enum TaskEventKind {
|
||||
Start = 'start',
|
||||
Active = 'active',
|
||||
Inactive = 'inactive',
|
||||
Terminated = 'terminated',
|
||||
Changed = 'changed',
|
||||
Terminated = 'terminated',
|
||||
End = 'end'
|
||||
}
|
||||
|
||||
|
||||
@@ -701,7 +743,7 @@ export interface TaskEvent {
|
||||
}
|
||||
|
||||
export namespace TaskEvent {
|
||||
export function create(kind: TaskEventKind.Active | TaskEventKind.Inactive | TaskEventKind.Terminated, task: Task);
|
||||
export function create(kind: TaskEventKind.Active | TaskEventKind.Inactive | TaskEventKind.Terminated | TaskEventKind.Start | TaskEventKind.End, task: Task);
|
||||
export function create(kind: TaskEventKind.Changed);
|
||||
export function create(kind: TaskEventKind, task?: Task): TaskEvent {
|
||||
if (task) {
|
||||
|
||||
@@ -74,7 +74,7 @@ import { ITaskSystem, ITaskResolver, ITaskSummary, TaskExecuteKind, TaskError, T
|
||||
import {
|
||||
Task, CustomTask, ConfiguringTask, ContributedTask, InMemoryTask, TaskEvent,
|
||||
TaskEventKind, TaskSet, TaskGroup, GroupType, ExecutionEngine, JsonSchemaVersion, TaskSourceKind,
|
||||
TaskIdentifier, TaskSorter, TaskItemTransfer
|
||||
TaskIdentifier, TaskSorter, TaskItem
|
||||
} from 'vs/workbench/parts/tasks/common/tasks';
|
||||
import { ITaskService, ITaskProvider, RunOptions, CustomizationProperties } from 'vs/workbench/parts/tasks/common/taskService';
|
||||
import { getTemplates as getTaskTemplates } from 'vs/workbench/parts/tasks/common/taskTemplates';
|
||||
@@ -582,23 +582,12 @@ class TaskService implements ITaskService {
|
||||
|
||||
CommandsRegistry.registerCommand('_executeTaskProvider', (accessor, args) => {
|
||||
return this.tasks().then((tasks) => {
|
||||
let result: TaskItemTransfer[] = [];
|
||||
let result: TaskItem[] = [];
|
||||
for (let task of tasks) {
|
||||
let folder: IWorkspaceFolder = Task.getWorkspaceFolder(task);
|
||||
let folderUri = folder ? folder.uri : undefined;
|
||||
let definition: TaskIdentifier;
|
||||
if (ContributedTask.is(task)) {
|
||||
definition = task.defines;
|
||||
} else if (CustomTask.is(task) && task.command !== void 0) {
|
||||
definition = CustomTask.getDefinition(task);
|
||||
let item = Task.getTaskItem(task);
|
||||
if (item) {
|
||||
result.push(item);
|
||||
}
|
||||
let handle: TaskItemTransfer = {
|
||||
id: task._id,
|
||||
label: task._label,
|
||||
definition: definition,
|
||||
workspaceFolderUri: folderUri
|
||||
};
|
||||
result.push(handle);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
@@ -685,7 +674,7 @@ class TaskService implements ITaskService {
|
||||
return this._providers.delete(handle);
|
||||
}
|
||||
|
||||
public getTask(folder: IWorkspaceFolder | string, alias: string): TPromise<Task> {
|
||||
public getTask(folder: IWorkspaceFolder | string, alias: string, compareId: boolean = false): TPromise<Task> {
|
||||
let name = Types.isString(folder) ? folder : folder.name;
|
||||
if (this.ignoredWorkspaceFolders.some(ignored => ignored.name === name)) {
|
||||
return TPromise.wrapError(new Error(nls.localize('TaskServer.folderIgnored', 'The folder {0} is ignored since it uses task version 0.1.0', name)));
|
||||
@@ -696,7 +685,7 @@ class TaskService implements ITaskService {
|
||||
return undefined;
|
||||
}
|
||||
for (let task of values) {
|
||||
if (Task.matches(task, alias)) {
|
||||
if (Task.matches(task, alias, compareId)) {
|
||||
return task;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,6 +288,7 @@ export class TerminalTaskSystem implements ITaskSystem {
|
||||
watchingProblemMatcher.aboutToStart();
|
||||
let delayer: Async.Delayer<any> = undefined;
|
||||
[terminal, executedCommand] = this.createTerminal(task);
|
||||
this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Start, task));
|
||||
const registeredLinkMatchers = this.registerLinkMatchers(terminal, problemMatchers);
|
||||
const onData = terminal.onLineData((line) => {
|
||||
watchingProblemMatcher.processLine(line);
|
||||
@@ -328,12 +329,14 @@ export class TerminalTaskSystem implements ITaskSystem {
|
||||
this.terminalService.setActiveInstance(terminal);
|
||||
this.terminalService.showPanel(false);
|
||||
}
|
||||
this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.End, task));
|
||||
resolve({ exitCode });
|
||||
});
|
||||
});
|
||||
} else {
|
||||
promise = new TPromise<ITaskSummary>((resolve, reject) => {
|
||||
[terminal, executedCommand] = this.createTerminal(task);
|
||||
this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Start, task));
|
||||
this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Active, task));
|
||||
let problemMatchers = this.resolveMatchers(task, task.problemMatchers);
|
||||
let startStopProblemMatcher = new StartStopProblemCollector(problemMatchers, this.markerService, this.modelService);
|
||||
@@ -359,6 +362,7 @@ export class TerminalTaskSystem implements ITaskSystem {
|
||||
startStopProblemMatcher.dispose();
|
||||
registeredLinkMatchers.forEach(handle => terminal.deregisterLinkMatcher(handle));
|
||||
this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Inactive, task));
|
||||
this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.End, task));
|
||||
// See https://github.com/Microsoft/vscode/issues/31965
|
||||
if (exitCode === 0 && startStopProblemMatcher.numberOfMatches > 0) {
|
||||
exitCode = 1;
|
||||
|
||||
@@ -35,6 +35,7 @@ import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
|
||||
|
||||
const defaultSelector = { scheme: 'far' };
|
||||
const model: ITextModel = EditorModel.createFromString(
|
||||
@@ -51,6 +52,7 @@ let rpcProtocol: TestRPCProtocol;
|
||||
let extHost: ExtHostLanguageFeatures;
|
||||
let mainThread: MainThreadLanguageFeatures;
|
||||
let commands: ExtHostCommands;
|
||||
let task: ExtHostTask;
|
||||
let workspace: ExtHostWorkspace;
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
let originalErrorHandler: (e: any) => any;
|
||||
@@ -119,9 +121,10 @@ suite('ExtHostLanguageFeatureCommands', function () {
|
||||
|
||||
commands = new ExtHostCommands(rpcProtocol, heapService, new NullLogService());
|
||||
workspace = new ExtHostWorkspace(rpcProtocol, { id: generateUuid(), name: 'Test', folders: [] }, new NullLogService());
|
||||
task = new ExtHostTask(rpcProtocol, workspace);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostCommands, commands);
|
||||
rpcProtocol.set(MainContext.MainThreadCommands, inst.createInstance(MainThreadCommands, rpcProtocol));
|
||||
ExtHostApiCommands.register(commands, workspace);
|
||||
ExtHostApiCommands.register(commands, task);
|
||||
|
||||
const diagnostics = new ExtHostDiagnostics(rpcProtocol);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, diagnostics);
|
||||
|
||||
Reference in New Issue
Block a user