Re-add task default API with fixes (#129397)

Part of #79188
This commit is contained in:
Alex Ross 2021-07-26 15:30:46 +02:00 committed by GitHub
parent a707e282ea
commit 3d5b13265d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 176 additions and 110 deletions

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as assert from 'assert'; 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'; import { assertNoRpc } from '../utils';
// Disable tasks tests: // Disable tasks tests:
@ -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', []);
});
});
}); });
}); });
}); });

View file

@ -1001,6 +1001,20 @@ declare module 'vscode' {
} }
//#endregion //#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 //#region Custom editor move https://github.com/microsoft/vscode/issues/86146
// TODO: Also for custom editor // TODO: Also for custom editor

View file

@ -17,7 +17,7 @@ import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder } from 'vs/platf
import { import {
ContributedTask, ConfiguringTask, KeyedTaskIdentifier, TaskExecution, Task, TaskEvent, TaskEventKind, ContributedTask, ConfiguringTask, KeyedTaskIdentifier, TaskExecution, Task, TaskEvent, TaskEventKind,
PresentationOptions, CommandOptions, CommandConfiguration, RuntimeType, CustomTask, TaskScope, TaskSource, 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'; } from 'vs/workbench/contrib/tasks/common/tasks';
@ -320,9 +320,8 @@ namespace TaskDTO {
hasDefinedMatchers: ContributedTask.is(task) ? task.hasDefinedMatchers : false, hasDefinedMatchers: ContributedTask.is(task) ? task.hasDefinedMatchers : false,
runOptions: RunOptionsDTO.from(task.runOptions), runOptions: RunOptionsDTO.from(task.runOptions),
}; };
if (task.configurationProperties.group) { result.group = TaskGroup.from(task.configurationProperties.group);
result.group = task.configurationProperties.group;
}
if (task.configurationProperties.detail) { if (task.configurationProperties.detail) {
result.detail = task.configurationProperties.detail; result.detail = task.configurationProperties.detail;
} }

View file

@ -1227,7 +1227,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
SymbolKind: extHostTypes.SymbolKind, SymbolKind: extHostTypes.SymbolKind,
SymbolTag: extHostTypes.SymbolTag, SymbolTag: extHostTypes.SymbolTag,
Task: extHostTypes.Task, Task: extHostTypes.Task,
Task2: extHostTypes.Task,
TaskGroup: extHostTypes.TaskGroup, TaskGroup: extHostTypes.TaskGroup,
TaskGroup2: extHostTypes.TaskGroup,
TaskPanelKind: extHostTypes.TaskPanelKind, TaskPanelKind: extHostTypes.TaskPanelKind,
TaskRevealKind: extHostTypes.TaskRevealKind, TaskRevealKind: extHostTypes.TaskRevealKind,
TaskScope: extHostTypes.TaskScope, TaskScope: extHostTypes.TaskScope,

View file

@ -8,7 +8,7 @@ import { asPromise } from 'vs/base/common/async';
import { Event, Emitter } from 'vs/base/common/event'; import { Event, Emitter } from 'vs/base/common/event';
import { MainContext, MainThreadTaskShape, ExtHostTaskShape } from 'vs/workbench/api/common/extHost.protocol'; 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 * as types from 'vs/workbench/api/common/extHostTypes';
import { IExtHostWorkspaceProvider, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; import { IExtHostWorkspaceProvider, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import type * as vscode from 'vscode'; import type * as vscode from 'vscode';
@ -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 namespace TaskDTO {
export function fromMany(tasks: vscode.Task[], extension: IExtensionDescription): tasks.TaskDTO[] { export function fromMany(tasks: vscode.Task[], extension: IExtensionDescription): tasks.TaskDTO[] {
@ -257,7 +265,6 @@ export namespace TaskDTO {
if (!definition || !scope) { if (!definition || !scope) {
return undefined; return undefined;
} }
const group = (value.group as types.TaskGroup) ? (value.group as types.TaskGroup).id : undefined;
const result: tasks.TaskDTO = { const result: tasks.TaskDTO = {
_id: (value as types.Task)._id!, _id: (value as types.Task)._id!,
definition, definition,
@ -269,7 +276,7 @@ export namespace TaskDTO {
}, },
execution: execution!, execution: execution!,
isBackground: value.isBackground, isBackground: value.isBackground,
group: group, group: TaskGroupDTO.from(value.group as vscode.TaskGroup2),
presentationOptions: TaskPresentationOptionsDTO.from(value.presentationOptions), presentationOptions: TaskPresentationOptionsDTO.from(value.presentationOptions),
problemMatchers: value.problemMatchers, problemMatchers: value.problemMatchers,
hasDefinedMatchers: (value as types.Task).hasDefinedMatchers, hasDefinedMatchers: (value as types.Task).hasDefinedMatchers,
@ -311,7 +318,13 @@ export namespace TaskDTO {
result.isBackground = value.isBackground; result.isBackground = value.isBackground;
} }
if (value.group !== undefined) { 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) { if (value.presentationOptions) {
result.presentationOptions = TaskPresentationOptionsDTO.to(value.presentationOptions)!; result.presentationOptions = TaskPresentationOptionsDTO.to(value.presentationOptions)!;

View file

@ -1762,8 +1762,9 @@ export enum TaskPanelKind {
} }
@es5ClassCompat @es5ClassCompat
export class TaskGroup implements vscode.TaskGroup { export class TaskGroup implements vscode.TaskGroup2 {
isDefault?: boolean;
private _id: string; private _id: string;
public static Clean: TaskGroup = new TaskGroup('clean', 'Clean'); public static Clean: TaskGroup = new TaskGroup('clean', 'Clean');

View file

@ -82,6 +82,11 @@ export interface TaskHandleDTO {
workspaceFolder: UriComponents | string; workspaceFolder: UriComponents | string;
} }
export interface TaskGroupDTO {
isDefault?: boolean;
_id: string;
}
export interface TaskDTO { export interface TaskDTO {
_id: string; _id: string;
name?: string; name?: string;
@ -89,7 +94,7 @@ export interface TaskDTO {
definition: TaskDefinitionDTO; definition: TaskDefinitionDTO;
isBackground?: boolean; isBackground?: boolean;
source: TaskSourceDTO; source: TaskSourceDTO;
group?: string; group?: TaskGroupDTO;
detail?: string; detail?: string;
presentationOptions?: TaskPresentationOptionsDTO; presentationOptions?: TaskPresentationOptionsDTO;
problemMatchers: string[]; problemMatchers: string[];

View file

@ -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 { ITaskSystem, ITaskResolver, ITaskSummary, TaskExecuteKind, TaskError, TaskErrors, TaskTerminateResponse, TaskSystemInfo, ITaskExecuteResult } from 'vs/workbench/contrib/tasks/common/taskSystem';
import { import {
Task, CustomTask, ConfiguringTask, ContributedTask, InMemoryTask, TaskEvent, Task, CustomTask, ConfiguringTask, ContributedTask, InMemoryTask, TaskEvent,
TaskSet, TaskGroup, GroupType, ExecutionEngine, JsonSchemaVersion, TaskSourceKind, TaskSet, TaskGroup, ExecutionEngine, JsonSchemaVersion, TaskSourceKind,
TaskSorter, TaskIdentifier, KeyedTaskIdentifier, TASK_RUNNING_STATE, TaskRunSource, TaskSorter, TaskIdentifier, KeyedTaskIdentifier, TASK_RUNNING_STATE, TaskRunSource,
KeyedTaskIdentifier as NKeyedTaskIdentifier, TaskDefinition, RuntimeType KeyedTaskIdentifier as NKeyedTaskIdentifier, TaskDefinition, RuntimeType
} from 'vs/workbench/contrib/tasks/common/tasks'; } from 'vs/workbench/contrib/tasks/common/tasks';
@ -304,11 +304,11 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
this.configurationResolverService.contributeVariable('defaultBuildTask', async (): Promise<string | undefined> => { this.configurationResolverService.contributeVariable('defaultBuildTask', async (): Promise<string | undefined> => {
let tasks = await this.getTasksForGroup(TaskGroup.Build); let tasks = await this.getTasksForGroup(TaskGroup.Build);
if (tasks.length > 0) { if (tasks.length > 0) {
let { defaults, users } = this.splitPerGroupType(tasks); let { none, defaults } = this.splitPerGroupType(tasks);
if (defaults.length === 1) { if (defaults.length === 1) {
return defaults[0]._label; return defaults[0]._label;
} else if (defaults.length + users.length > 0) { } else if (defaults.length + none.length > 0) {
tasks = defaults.concat(users); tasks = defaults.concat(none);
} }
} }
@ -1100,12 +1100,13 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
return Promise.resolve(task); return Promise.resolve(task);
} }
private getTasksForGroup(group: string): Promise<Task[]> { private getTasksForGroup(group: TaskGroup): Promise<Task[]> {
return this.getGroupedTasks().then((groups) => { return this.getGroupedTasks().then((groups) => {
let result: Task[] = []; let result: Task[] = [];
groups.forEach((tasks) => { groups.forEach((tasks) => {
for (let task of 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); result.push(task);
} }
} }
@ -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 none: Task[] = [];
let defaults: Task[] = []; let defaults: Task[] = [];
let users: Task[] = [];
for (let task of tasks) { for (let task of tasks) {
if (task.configurationProperties.groupType === GroupType.default) { if ((task.configurationProperties.group as TaskGroup).isDefault) {
defaults.push(task); defaults.push(task);
} else if (task.configurationProperties.groupType === GroupType.user) {
users.push(task);
} else { } else {
none.push(task); none.push(task);
} }
} }
return { none, defaults, users }; return { none, defaults };
} }
private runBuildCommand(): void { private runBuildCommand(): void {
@ -2632,9 +2630,12 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
const buildTasks: ConfiguringTask[] = []; const buildTasks: ConfiguringTask[] = [];
for (const taskSource of tasks) { for (const taskSource of tasks) {
for (const task in taskSource[1].configurations?.byIdentifier) { for (const task in taskSource[1].configurations?.byIdentifier) {
if ((taskSource[1].configurations?.byIdentifier[task].configurationProperties.group === TaskGroup.Build) && if (taskSource[1].configurations) {
(taskSource[1].configurations?.byIdentifier[task].configurationProperties.groupType === GroupType.default)) { const taskGroup: TaskGroup = taskSource[1].configurations.byIdentifier[task].configurationProperties.group as TaskGroup;
buildTasks.push(taskSource[1].configurations.byIdentifier[task]);
if (taskGroup && taskGroup._id === TaskGroup.Build._id && taskGroup.isDefault) {
buildTasks.push(taskSource[1].configurations.byIdentifier[task]);
}
} }
} }
} }
@ -2649,14 +2650,14 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
return this.getTasksForGroup(TaskGroup.Build).then((tasks) => { return this.getTasksForGroup(TaskGroup.Build).then((tasks) => {
if (tasks.length > 0) { if (tasks.length > 0) {
let { defaults, users } = this.splitPerGroupType(tasks); let { none, defaults } = this.splitPerGroupType(tasks);
if (defaults.length === 1) { if (defaults.length === 1) {
this.run(defaults[0], undefined, TaskRunSource.User).then(undefined, reason => { 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 // eat the error, it has already been surfaced to the user and we don't care about it here
}); });
return; return;
} else if (defaults.length + users.length > 0) { } else if (defaults.length + none.length > 0) {
tasks = defaults.concat(users); tasks = defaults.concat(none);
} }
} }
this.showIgnoredFoldersMessage().then(() => { this.showIgnoredFoldersMessage().then(() => {
@ -2699,14 +2700,14 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}; };
let promise = this.getTasksForGroup(TaskGroup.Test).then((tasks) => { let promise = this.getTasksForGroup(TaskGroup.Test).then((tasks) => {
if (tasks.length > 0) { if (tasks.length > 0) {
let { defaults, users } = this.splitPerGroupType(tasks); let { none, defaults } = this.splitPerGroupType(tasks);
if (defaults.length === 1) { if (defaults.length === 1) {
this.run(defaults[0], undefined, TaskRunSource.User).then(undefined, reason => { 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 // eat the error, it has already been surfaced to the user and we don't care about it here
}); });
return; return;
} else if (defaults.length + users.length > 0) { } else if (defaults.length + none.length > 0) {
tasks = defaults.concat(users); tasks = defaults.concat(none);
} }
} }
this.showIgnoredFoldersMessage().then(() => { this.showIgnoredFoldersMessage().then(() => {
@ -3083,7 +3084,8 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
let selectedTask: Task | undefined; let selectedTask: Task | undefined;
let selectedEntry: TaskQuickPickEntry; let selectedEntry: TaskQuickPickEntry;
for (let task of tasks) { 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; selectedTask = task;
break; break;
} }
@ -3135,7 +3137,8 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
let selectedEntry: TaskQuickPickEntry; let selectedEntry: TaskQuickPickEntry;
for (let task of tasks) { 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; selectedTask = task;
break; break;
} }

View file

@ -425,6 +425,7 @@ export interface BaseTaskRunnerConfiguration {
* The group * The group
*/ */
group?: string | GroupKind; group?: string | GroupKind;
/** /**
* Controls the behavior of the used terminal * Controls the behavior of the used terminal
*/ */
@ -1230,24 +1231,18 @@ const partialSource: Partial<Tasks.TaskSource> = {
}; };
namespace GroupKind { namespace GroupKind {
export function from(this: void, external: string | GroupKind | undefined): [string, Tasks.GroupType] | undefined { export function from(this: void, external: string | GroupKind | undefined): Tasks.TaskGroup | undefined {
if (external === undefined) { if (external === undefined) {
return undefined; return undefined;
} } else if (Types.isString(external) && Tasks.TaskGroup.is(external)) {
if (Types.isString(external)) { return { _id: external, isDefault: false };
if (Tasks.TaskGroup.is(external)) { } else if (Types.isString(external.kind) && Tasks.TaskGroup.is(external.kind)) {
return [external, Tasks.GroupType.user]; let group: string = external.kind;
} else { let isDefault: boolean = !!external.isDefault;
return undefined;
}
}
if (!Types.isString(external.kind) || !Tasks.TaskGroup.is(external.kind)) {
return undefined;
}
let group: string = external.kind;
let isDefault: boolean = !!external.isDefault;
return [group, isDefault ? Tasks.GroupType.default : Tasks.GroupType.user]; return { _id: group, isDefault };
}
return undefined;
} }
} }
@ -1325,18 +1320,7 @@ namespace ConfigurationProperties {
if (external.promptOnClose !== undefined) { if (external.promptOnClose !== undefined) {
result.promptOnClose = !!external.promptOnClose; result.promptOnClose = !!external.promptOnClose;
} }
if (external.group !== undefined) { result.group = GroupKind.from(external.group);
if (Types.isString(external.group) && Tasks.TaskGroup.is(external.group)) {
result.group = external.group;
result.groupType = Tasks.GroupType.user;
} else {
let values = GroupKind.from(external.group);
if (values) {
result.group = values[0];
result.groupType = values[1];
}
}
}
if (external.dependsOn !== undefined) { if (external.dependsOn !== undefined) {
if (Types.isArray(external.dependsOn)) { if (Types.isArray(external.dependsOn)) {
result.dependsOn = external.dependsOn.reduce((dependencies: Tasks.TaskDependency[], item): Tasks.TaskDependency[] => { result.dependsOn = external.dependsOn.reduce((dependencies: Tasks.TaskDependency[], item): Tasks.TaskDependency[] => {
@ -1598,9 +1582,6 @@ namespace CustomTask {
if (task.configurationProperties.problemMatchers === undefined) { if (task.configurationProperties.problemMatchers === undefined) {
task.configurationProperties.problemMatchers = EMPTY_ARRAY; task.configurationProperties.problemMatchers = EMPTY_ARRAY;
} }
if (task.configurationProperties.group !== undefined && task.configurationProperties.groupType === undefined) {
task.configurationProperties.groupType = Tasks.GroupType.user;
}
} }
export function createCustomTask(contributedTask: Tasks.ContributedTask, configuredProps: Tasks.ConfiguringTask | Tasks.CustomTask): Tasks.CustomTask { export function createCustomTask(contributedTask: Tasks.ContributedTask, configuredProps: Tasks.ConfiguringTask | Tasks.CustomTask): Tasks.CustomTask {
@ -1621,7 +1602,6 @@ namespace CustomTask {
let resultConfigProps: Tasks.ConfigurationProperties = result.configurationProperties; let resultConfigProps: Tasks.ConfigurationProperties = result.configurationProperties;
assignProperty(resultConfigProps, configuredProps.configurationProperties, 'group'); assignProperty(resultConfigProps, configuredProps.configurationProperties, 'group');
assignProperty(resultConfigProps, configuredProps.configurationProperties, 'groupType');
assignProperty(resultConfigProps, configuredProps.configurationProperties, 'isBackground'); assignProperty(resultConfigProps, configuredProps.configurationProperties, 'isBackground');
assignProperty(resultConfigProps, configuredProps.configurationProperties, 'dependsOn'); assignProperty(resultConfigProps, configuredProps.configurationProperties, 'dependsOn');
assignProperty(resultConfigProps, configuredProps.configurationProperties, 'problemMatchers'); assignProperty(resultConfigProps, configuredProps.configurationProperties, 'problemMatchers');
@ -1634,7 +1614,6 @@ namespace CustomTask {
let contributedConfigProps: Tasks.ConfigurationProperties = contributedTask.configurationProperties; let contributedConfigProps: Tasks.ConfigurationProperties = contributedTask.configurationProperties;
fillProperty(resultConfigProps, contributedConfigProps, 'group'); fillProperty(resultConfigProps, contributedConfigProps, 'group');
fillProperty(resultConfigProps, contributedConfigProps, 'groupType');
fillProperty(resultConfigProps, contributedConfigProps, 'isBackground'); fillProperty(resultConfigProps, contributedConfigProps, 'isBackground');
fillProperty(resultConfigProps, contributedConfigProps, 'dependsOn'); fillProperty(resultConfigProps, contributedConfigProps, 'dependsOn');
fillProperty(resultConfigProps, contributedConfigProps, 'problemMatchers'); fillProperty(resultConfigProps, contributedConfigProps, 'problemMatchers');
@ -1752,10 +1731,8 @@ namespace TaskParser {
} }
if ((defaultBuildTask.rank > -1) && (defaultBuildTask.rank < 2) && defaultBuildTask.task) { if ((defaultBuildTask.rank > -1) && (defaultBuildTask.rank < 2) && defaultBuildTask.task) {
defaultBuildTask.task.configurationProperties.group = Tasks.TaskGroup.Build; defaultBuildTask.task.configurationProperties.group = Tasks.TaskGroup.Build;
defaultBuildTask.task.configurationProperties.groupType = Tasks.GroupType.user;
} else if ((defaultTestTask.rank > -1) && (defaultTestTask.rank < 2) && defaultTestTask.task) { } else if ((defaultTestTask.rank > -1) && (defaultTestTask.rank < 2) && defaultTestTask.task) {
defaultTestTask.task.configurationProperties.group = Tasks.TaskGroup.Test; defaultTestTask.task.configurationProperties.group = Tasks.TaskGroup.Test;
defaultTestTask.task.configurationProperties.groupType = Tasks.GroupType.user;
} }
return result; return result;
@ -2099,10 +2076,9 @@ class ConfigurationParser {
problemMatchers: matchers, problemMatchers: matchers,
} }
); );
let value = GroupKind.from(fileConfig.group); let taskGroupKind = GroupKind.from(fileConfig.group);
if (value) { if (taskGroupKind !== undefined) {
task.configurationProperties.group = value[0]; task.configurationProperties.group = taskGroupKind;
task.configurationProperties.groupType = value[1];
} else if (fileConfig.group === 'none') { } else if (fileConfig.group === 'none') {
task.configurationProperties.group = undefined; task.configurationProperties.group = undefined;
} }

View file

@ -365,21 +365,36 @@ export interface CommandConfiguration {
} }
export namespace TaskGroup { export namespace TaskGroup {
export const Clean: 'clean' = 'clean'; export const Clean: TaskGroup = { _id: 'clean', isDefault: false };
export const Build: 'build' = 'build'; export const Build: TaskGroup = { _id: 'build', isDefault: false };
export const Rebuild: 'rebuild' = 'rebuild'; export const Rebuild: TaskGroup = { _id: 'rebuild', isDefault: false };
export const Test: 'test' = 'test'; export const Test: TaskGroup = { _id: 'test', isDefault: false };
export function is(value: string): value is string { export function is(value: any): value is string {
return value === Clean || value === Build || value === Rebuild || value === Test; return value === Clean._id || value === Build._id || value === Rebuild._id || value === Test._id;
}
export function from(value: string | TaskGroup | undefined): TaskGroup | undefined {
if (value === undefined) {
return undefined;
} else if (Types.isString(value)) {
if (is(value)) {
return { _id: value, isDefault: false };
}
return undefined;
} else {
return value;
}
} }
} }
export type TaskGroup = 'clean' | 'build' | 'rebuild' | 'test'; export interface TaskGroup {
_id: string;
isDefault?: boolean;
}
export const enum TaskScope { export const enum TaskScope {
Global = 1, Global = 1,
@ -466,11 +481,6 @@ export interface TaskDependency {
task: string | KeyedTaskIdentifier | undefined; task: string | KeyedTaskIdentifier | undefined;
} }
export const enum GroupType {
default = 'default',
user = 'user'
}
export const enum DependsOrder { export const enum DependsOrder {
parallel = 'parallel', parallel = 'parallel',
sequence = 'sequence' sequence = 'sequence'
@ -489,14 +499,9 @@ export interface ConfigurationProperties {
identifier?: string; identifier?: string;
/** /**
* the task's group; * The task's group;
*/ */
group?: string; group?: string | TaskGroup;
/**
* The group type
*/
groupType?: GroupType;
/** /**
* The presentation options * The presentation options
@ -1076,7 +1081,7 @@ export interface TaskEvent {
taskId?: string; taskId?: string;
taskName?: string; taskName?: string;
runType?: TaskRunType; runType?: TaskRunType;
group?: string; group?: string | TaskGroup;
processId?: number; processId?: number;
exitCode?: number; exitCode?: number;
terminalId?: number; terminalId?: number;

View file

@ -7,6 +7,7 @@ import * as assert from 'assert';
import Severity from 'vs/base/common/severity'; import Severity from 'vs/base/common/severity';
import * as UUID from 'vs/base/common/uuid'; import * as UUID from 'vs/base/common/uuid';
import * as Types from 'vs/base/common/types';
import * as Platform from 'vs/base/common/platform'; import * as Platform from 'vs/base/common/platform';
import { ValidationStatus } from 'vs/base/common/parsers'; import { ValidationStatus } from 'vs/base/common/parsers';
import { ProblemMatcher, FileLocationKind, ProblemPattern, ApplyToKind } from 'vs/workbench/contrib/tasks/common/problemMatcher'; import { ProblemMatcher, FileLocationKind, ProblemPattern, ApplyToKind } from 'vs/workbench/contrib/tasks/common/problemMatcher';
@ -214,14 +215,8 @@ class CustomTaskBuilder {
return this; return this;
} }
public group(value: Tasks.TaskGroup): CustomTaskBuilder { public group(value: string | Tasks.TaskGroup): CustomTaskBuilder {
this.result.configurationProperties.group = value; this.result.configurationProperties.group = value;
this.result.configurationProperties.groupType = Tasks.GroupType.user;
return this;
}
public groupType(value: Tasks.GroupType): CustomTaskBuilder {
this.result.configurationProperties.groupType = value;
return this; return this;
} }
@ -453,8 +448,10 @@ function assertConfiguration(result: ParseResult, expected: Tasks.Task[]): void
assert.ok(!actualTasks[task.configurationProperties.name!]); assert.ok(!actualTasks[task.configurationProperties.name!]);
actualTasks[task.configurationProperties.name!] = task; actualTasks[task.configurationProperties.name!] = task;
actualId2Name[task._id] = task.configurationProperties.name!; actualId2Name[task._id] = task.configurationProperties.name!;
if (task.configurationProperties.group) {
actualTaskGroups.add(task.configurationProperties.group, task); let taskId = Tasks.TaskGroup.from(task.configurationProperties.group)?._id;
if (taskId) {
actualTaskGroups.add(taskId, task);
} }
}); });
let expectedTasks: { [key: string]: Tasks.Task; } = Object.create(null); let expectedTasks: { [key: string]: Tasks.Task; } = Object.create(null);
@ -462,8 +459,9 @@ function assertConfiguration(result: ParseResult, expected: Tasks.Task[]): void
expected.forEach(task => { expected.forEach(task => {
assert.ok(!expectedTasks[task.configurationProperties.name!]); assert.ok(!expectedTasks[task.configurationProperties.name!]);
expectedTasks[task.configurationProperties.name!] = task; expectedTasks[task.configurationProperties.name!] = task;
if (task.configurationProperties.group) { let taskId = Tasks.TaskGroup.from(task.configurationProperties.group)?._id;
expectedTaskGroup.add(task.configurationProperties.group, task); if (taskId) {
expectedTaskGroup.add(taskId, task);
} }
}); });
let actualKeys = Object.keys(actualTasks); let actualKeys = Object.keys(actualTasks);
@ -486,14 +484,22 @@ function assertTask(actual: Tasks.Task, expected: Tasks.Task) {
assert.strictEqual(actual.configurationProperties.isBackground, expected.configurationProperties.isBackground, 'isBackground'); assert.strictEqual(actual.configurationProperties.isBackground, expected.configurationProperties.isBackground, 'isBackground');
assert.strictEqual(typeof actual.configurationProperties.problemMatchers, typeof expected.configurationProperties.problemMatchers); assert.strictEqual(typeof actual.configurationProperties.problemMatchers, typeof expected.configurationProperties.problemMatchers);
assert.strictEqual(actual.configurationProperties.promptOnClose, expected.configurationProperties.promptOnClose, 'promptOnClose'); assert.strictEqual(actual.configurationProperties.promptOnClose, expected.configurationProperties.promptOnClose, 'promptOnClose');
assert.strictEqual(actual.configurationProperties.group, expected.configurationProperties.group, 'group'); assert.strictEqual(typeof actual.configurationProperties.group, typeof expected.configurationProperties.group, `group types unequal`);
assert.strictEqual(actual.configurationProperties.groupType, expected.configurationProperties.groupType, 'groupType');
if (actual.configurationProperties.problemMatchers && expected.configurationProperties.problemMatchers) { if (actual.configurationProperties.problemMatchers && expected.configurationProperties.problemMatchers) {
assert.strictEqual(actual.configurationProperties.problemMatchers.length, expected.configurationProperties.problemMatchers.length); assert.strictEqual(actual.configurationProperties.problemMatchers.length, expected.configurationProperties.problemMatchers.length);
for (let i = 0; i < actual.configurationProperties.problemMatchers.length; i++) { for (let i = 0; i < actual.configurationProperties.problemMatchers.length; i++) {
assertProblemMatcher(actual.configurationProperties.problemMatchers[i], expected.configurationProperties.problemMatchers[i]); assertProblemMatcher(actual.configurationProperties.problemMatchers[i], expected.configurationProperties.problemMatchers[i]);
} }
} }
if (actual.configurationProperties.group && expected.configurationProperties.group) {
if (Types.isString(actual.configurationProperties.group)) {
assert.strictEqual(actual.configurationProperties.group, expected.configurationProperties.group);
} else {
assertGroup(actual.configurationProperties.group as Tasks.TaskGroup, expected.configurationProperties.group as Tasks.TaskGroup);
}
}
} }
function assertCommandConfiguration(actual: Tasks.CommandConfiguration, expected: Tasks.CommandConfiguration) { function assertCommandConfiguration(actual: Tasks.CommandConfiguration, expected: Tasks.CommandConfiguration) {
@ -516,6 +522,14 @@ function assertCommandConfiguration(actual: Tasks.CommandConfiguration, expected
} }
} }
function assertGroup(actual: Tasks.TaskGroup, expected: Tasks.TaskGroup) {
assert.strictEqual(typeof actual, typeof expected);
if (actual && expected) {
assert.strictEqual(actual._id, expected._id, `group ids unequal. actual: ${actual._id} expected ${expected._id}`);
assert.strictEqual(actual.isDefault, expected.isDefault, `group defaults unequal. actual: ${actual.isDefault} expected ${expected.isDefault}`);
}
}
function assertPresentation(actual: Tasks.PresentationOptions, expected: Tasks.PresentationOptions) { function assertPresentation(actual: Tasks.PresentationOptions, expected: Tasks.PresentationOptions) {
assert.strictEqual(typeof actual, typeof expected); assert.strictEqual(typeof actual, typeof expected);
if (actual && expected) { if (actual && expected) {
@ -1534,9 +1548,10 @@ suite('Tasks version 2.0.0', () => {
group: { kind: 'build', isDefault: true } group: { kind: 'build', isDefault: true }
}; };
let builder = new ConfiguationBuilder(); let builder = new ConfiguationBuilder();
let taskGroup = Tasks.TaskGroup.Build;
taskGroup.isDefault = true;
builder.task('dir', 'dir'). builder.task('dir', 'dir').
group(Tasks.TaskGroup.Build). group(taskGroup).
groupType(Tasks.GroupType.default).
command().suppressTaskName(true). command().suppressTaskName(true).
runtime(Tasks.RuntimeType.Shell). runtime(Tasks.RuntimeType.Shell).
presentation().echo(true); presentation().echo(true);
@ -1594,9 +1609,10 @@ suite('Tasks version 2.0.0', () => {
] ]
}; };
let builder = new ConfiguationBuilder(); let builder = new ConfiguationBuilder();
let taskGroup = Tasks.TaskGroup.Build;
taskGroup.isDefault = true;
builder.task('dir', 'dir'). builder.task('dir', 'dir').
group(Tasks.TaskGroup.Build). group(taskGroup).
groupType(Tasks.GroupType.default).
command().suppressTaskName(true). command().suppressTaskName(true).
runtime(Tasks.RuntimeType.Shell). runtime(Tasks.RuntimeType.Shell).
presentation().echo(true); presentation().echo(true);