Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-add task default API with fixes #129397

Merged
merged 3 commits into from Jul 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import * as assert from 'assert';
import { window, tasks, Disposable, TaskDefinition, Task, EventEmitter, CustomExecution, Pseudoterminal, TaskScope, commands, env, UIKind, ShellExecution, TaskExecution, Terminal, Event, workspace, ConfigurationTarget, TaskProcessStartEvent } from 'vscode';
import { window, tasks, Disposable, TaskDefinition, Task, Task2, EventEmitter, CustomExecution, Pseudoterminal, TaskScope, commands, env, UIKind, ShellExecution, TaskExecution, Terminal, Event, workspace, ConfigurationTarget, TaskProcessStartEvent } from 'vscode';
import { assertNoRpc } from '../utils';

// Disable tasks tests:
Expand Down Expand Up @@ -331,6 +331,38 @@ import { assertNoRpc } from '../utils';
}
});
});

test('A task can be fetched with default task group information', () => {
return new Promise<void>(async (resolve, reject) => {
// Add default to tasks.json since this is not possible using an API yet.
const tasksConfig = workspace.getConfiguration('tasks');
await tasksConfig.update('version', '2.0.0', ConfigurationTarget.Workspace);
await tasksConfig.update('tasks', [
{
label: 'Run this task',
type: 'shell',
command: 'sleep 1',
problemMatcher: [],
group: {
kind: 'build',
isDefault: 'true'
}
}
], ConfigurationTarget.Workspace);

const task = <Task2[]>(await tasks.fetchTasks());

if (task && task.length > 0) {
const grp = task[0].group;
assert.strictEqual(grp?.isDefault, true);
resolve();
} else {
reject('fetched task can\'t be undefined');
}
// Reset tasks.json
await tasksConfig.update('tasks', []);
});
});
});
});
});
14 changes: 14 additions & 0 deletions src/vs/vscode.proposed.d.ts
Expand Up @@ -1001,6 +1001,20 @@ declare module 'vscode' {
}
//#endregion

export class TaskGroup2 {
static Clean: TaskGroup2;
static Build: TaskGroup2;
static Rebuild: TaskGroup2;
static Test: TaskGroup2;
readonly isDefault?: boolean;
readonly id: string;
private constructor(id: string, label: string);
}

export class Task2 extends Task {
group?: TaskGroup2;
}

//#region Custom editor move https://github.com/microsoft/vscode/issues/86146

// TODO: Also for custom editor
Expand Down
7 changes: 3 additions & 4 deletions src/vs/workbench/api/browser/mainThreadTask.ts
Expand Up @@ -17,7 +17,7 @@ import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder } from 'vs/platf
import {
ContributedTask, ConfiguringTask, KeyedTaskIdentifier, TaskExecution, Task, TaskEvent, TaskEventKind,
PresentationOptions, CommandOptions, CommandConfiguration, RuntimeType, CustomTask, TaskScope, TaskSource,
TaskSourceKind, ExtensionTaskSource, RunOptions, TaskSet, TaskDefinition
TaskSourceKind, ExtensionTaskSource, RunOptions, TaskSet, TaskDefinition, TaskGroup
} from 'vs/workbench/contrib/tasks/common/tasks';


Expand Down Expand Up @@ -320,9 +320,8 @@ namespace TaskDTO {
hasDefinedMatchers: ContributedTask.is(task) ? task.hasDefinedMatchers : false,
runOptions: RunOptionsDTO.from(task.runOptions),
};
if (task.configurationProperties.group) {
result.group = task.configurationProperties.group;
}
result.group = TaskGroup.from(task.configurationProperties.group);

if (task.configurationProperties.detail) {
result.detail = task.configurationProperties.detail;
}
Expand Down
2 changes: 2 additions & 0 deletions src/vs/workbench/api/common/extHost.api.impl.ts
Expand Up @@ -1227,7 +1227,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
SymbolKind: extHostTypes.SymbolKind,
SymbolTag: extHostTypes.SymbolTag,
Task: extHostTypes.Task,
Task2: extHostTypes.Task,
TaskGroup: extHostTypes.TaskGroup,
TaskGroup2: extHostTypes.TaskGroup,
TaskPanelKind: extHostTypes.TaskPanelKind,
TaskRevealKind: extHostTypes.TaskRevealKind,
TaskScope: extHostTypes.TaskScope,
Expand Down
21 changes: 17 additions & 4 deletions src/vs/workbench/api/common/extHostTask.ts
Expand Up @@ -8,7 +8,7 @@ import { asPromise } from 'vs/base/common/async';
import { Event, Emitter } from 'vs/base/common/event';

import { MainContext, MainThreadTaskShape, ExtHostTaskShape } from 'vs/workbench/api/common/extHost.protocol';

import * as Objects from 'vs/base/common/objects';
import * as types from 'vs/workbench/api/common/extHostTypes';
import { IExtHostWorkspaceProvider, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import type * as vscode from 'vscode';
Expand Down Expand Up @@ -213,6 +213,14 @@ export namespace TaskHandleDTO {
};
}
}
export namespace TaskGroupDTO {
export function from(value: vscode.TaskGroup2): tasks.TaskGroupDTO | undefined {
if (value === undefined || value === null) {
return undefined;
}
return { _id: value.id, isDefault: value.isDefault };
}
}

export namespace TaskDTO {
export function fromMany(tasks: vscode.Task[], extension: IExtensionDescription): tasks.TaskDTO[] {
Expand Down Expand Up @@ -257,7 +265,6 @@ export namespace TaskDTO {
if (!definition || !scope) {
return undefined;
}
const group = (value.group as types.TaskGroup) ? (value.group as types.TaskGroup).id : undefined;
const result: tasks.TaskDTO = {
_id: (value as types.Task)._id!,
definition,
Expand All @@ -269,7 +276,7 @@ export namespace TaskDTO {
},
execution: execution!,
isBackground: value.isBackground,
group: group,
group: TaskGroupDTO.from(value.group as vscode.TaskGroup2),
presentationOptions: TaskPresentationOptionsDTO.from(value.presentationOptions),
problemMatchers: value.problemMatchers,
hasDefinedMatchers: (value as types.Task).hasDefinedMatchers,
Expand Down Expand Up @@ -311,7 +318,13 @@ export namespace TaskDTO {
result.isBackground = value.isBackground;
}
if (value.group !== undefined) {
result.group = types.TaskGroup.from(value.group);
result.group = types.TaskGroup.from(value.group._id);
if (result.group) {
result.group = Objects.deepClone(result.group);
if (value.group.isDefault) {
result.group.isDefault = value.group.isDefault;
}
}
}
if (value.presentationOptions) {
result.presentationOptions = TaskPresentationOptionsDTO.to(value.presentationOptions)!;
Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/api/common/extHostTypes.ts
Expand Up @@ -1762,8 +1762,9 @@ export enum TaskPanelKind {
}

@es5ClassCompat
export class TaskGroup implements vscode.TaskGroup {
export class TaskGroup implements vscode.TaskGroup2 {

isDefault?: boolean;
private _id: string;

public static Clean: TaskGroup = new TaskGroup('clean', 'Clean');
Expand Down
7 changes: 6 additions & 1 deletion src/vs/workbench/api/common/shared/tasks.ts
Expand Up @@ -82,14 +82,19 @@ export interface TaskHandleDTO {
workspaceFolder: UriComponents | string;
}

export interface TaskGroupDTO {
isDefault?: boolean;
_id: string;
}

export interface TaskDTO {
_id: string;
name?: string;
execution: ProcessExecutionDTO | ShellExecutionDTO | CustomExecutionDTO | undefined;
definition: TaskDefinitionDTO;
isBackground?: boolean;
source: TaskSourceDTO;
group?: string;
group?: TaskGroupDTO;
detail?: string;
presentationOptions?: TaskPresentationOptionsDTO;
problemMatchers: string[];
Expand Down
49 changes: 26 additions & 23 deletions src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts
Expand Up @@ -50,7 +50,7 @@ import { ITerminalProfileResolverService } from 'vs/workbench/contrib/terminal/c
import { ITaskSystem, ITaskResolver, ITaskSummary, TaskExecuteKind, TaskError, TaskErrors, TaskTerminateResponse, TaskSystemInfo, ITaskExecuteResult } from 'vs/workbench/contrib/tasks/common/taskSystem';
import {
Task, CustomTask, ConfiguringTask, ContributedTask, InMemoryTask, TaskEvent,
TaskSet, TaskGroup, GroupType, ExecutionEngine, JsonSchemaVersion, TaskSourceKind,
TaskSet, TaskGroup, ExecutionEngine, JsonSchemaVersion, TaskSourceKind,
TaskSorter, TaskIdentifier, KeyedTaskIdentifier, TASK_RUNNING_STATE, TaskRunSource,
KeyedTaskIdentifier as NKeyedTaskIdentifier, TaskDefinition, RuntimeType
} from 'vs/workbench/contrib/tasks/common/tasks';
Expand Down Expand Up @@ -304,11 +304,11 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
this.configurationResolverService.contributeVariable('defaultBuildTask', async (): Promise<string | undefined> => {
let tasks = await this.getTasksForGroup(TaskGroup.Build);
if (tasks.length > 0) {
let { defaults, users } = this.splitPerGroupType(tasks);
let { none, defaults } = this.splitPerGroupType(tasks);
if (defaults.length === 1) {
return defaults[0]._label;
} else if (defaults.length + users.length > 0) {
tasks = defaults.concat(users);
} else if (defaults.length + none.length > 0) {
tasks = defaults.concat(none);
}
}

Expand Down Expand Up @@ -1100,12 +1100,13 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
return Promise.resolve(task);
}

private getTasksForGroup(group: string): Promise<Task[]> {
private getTasksForGroup(group: TaskGroup): Promise<Task[]> {
return this.getGroupedTasks().then((groups) => {
let result: Task[] = [];
groups.forEach((tasks) => {
for (let task of tasks) {
if (task.configurationProperties.group === group) {
let configTaskGroup = TaskGroup.from(task.configurationProperties.group);
if (configTaskGroup?._id === group._id) {
result.push(task);
}
}
Expand Down Expand Up @@ -2600,20 +2601,17 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
});
}

private splitPerGroupType(tasks: Task[]): { none: Task[], defaults: Task[], users: Task[] } {
private splitPerGroupType(tasks: Task[]): { none: Task[], defaults: Task[] } {
let none: Task[] = [];
let defaults: Task[] = [];
let users: Task[] = [];
for (let task of tasks) {
if (task.configurationProperties.groupType === GroupType.default) {
if ((task.configurationProperties.group as TaskGroup).isDefault) {
defaults.push(task);
} else if (task.configurationProperties.groupType === GroupType.user) {
users.push(task);
} else {
none.push(task);
}
}
return { none, defaults, users };
return { none, defaults };
}

private runBuildCommand(): void {
Expand All @@ -2632,9 +2630,12 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
const buildTasks: ConfiguringTask[] = [];
for (const taskSource of tasks) {
for (const task in taskSource[1].configurations?.byIdentifier) {
if ((taskSource[1].configurations?.byIdentifier[task].configurationProperties.group === TaskGroup.Build) &&
(taskSource[1].configurations?.byIdentifier[task].configurationProperties.groupType === GroupType.default)) {
buildTasks.push(taskSource[1].configurations.byIdentifier[task]);
if (taskSource[1].configurations) {
const taskGroup: TaskGroup = taskSource[1].configurations.byIdentifier[task].configurationProperties.group as TaskGroup;

if (taskGroup && taskGroup._id === TaskGroup.Build._id && taskGroup.isDefault) {
buildTasks.push(taskSource[1].configurations.byIdentifier[task]);
}
}
}
}
Expand All @@ -2649,14 +2650,14 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer

return this.getTasksForGroup(TaskGroup.Build).then((tasks) => {
if (tasks.length > 0) {
let { defaults, users } = this.splitPerGroupType(tasks);
let { none, defaults } = this.splitPerGroupType(tasks);
if (defaults.length === 1) {
this.run(defaults[0], undefined, TaskRunSource.User).then(undefined, reason => {
// eat the error, it has already been surfaced to the user and we don't care about it here
});
return;
} else if (defaults.length + users.length > 0) {
tasks = defaults.concat(users);
} else if (defaults.length + none.length > 0) {
tasks = defaults.concat(none);
}
}
this.showIgnoredFoldersMessage().then(() => {
Expand Down Expand Up @@ -2699,14 +2700,14 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
};
let promise = this.getTasksForGroup(TaskGroup.Test).then((tasks) => {
if (tasks.length > 0) {
let { defaults, users } = this.splitPerGroupType(tasks);
let { none, defaults } = this.splitPerGroupType(tasks);
if (defaults.length === 1) {
this.run(defaults[0], undefined, TaskRunSource.User).then(undefined, reason => {
// eat the error, it has already been surfaced to the user and we don't care about it here
});
return;
} else if (defaults.length + users.length > 0) {
tasks = defaults.concat(users);
} else if (defaults.length + none.length > 0) {
tasks = defaults.concat(none);
}
}
this.showIgnoredFoldersMessage().then(() => {
Expand Down Expand Up @@ -3083,7 +3084,8 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
let selectedTask: Task | undefined;
let selectedEntry: TaskQuickPickEntry;
for (let task of tasks) {
if (task.configurationProperties.group === TaskGroup.Build && task.configurationProperties.groupType === GroupType.default) {
let taskGroup: TaskGroup | undefined = TaskGroup.from(task.configurationProperties.group);
if (taskGroup && taskGroup.isDefault && taskGroup._id === TaskGroup.Build._id) {
selectedTask = task;
break;
}
Expand Down Expand Up @@ -3135,7 +3137,8 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
let selectedEntry: TaskQuickPickEntry;

for (let task of tasks) {
if (task.configurationProperties.group === TaskGroup.Test && task.configurationProperties.groupType === GroupType.default) {
let taskGroup: TaskGroup | undefined = TaskGroup.from(task.configurationProperties.group);
if (taskGroup && taskGroup.isDefault && taskGroup._id === TaskGroup.Test._id) {
selectedTask = task;
break;
}
Expand Down