diff --git a/extensions/gulp/package.json b/extensions/gulp/package.json index 1200766a9088ee5b3e8aab2097070939b3e3ec29..f2eb59ef074345d1d52fcd0594c7f8dd3ca7e44c 100644 --- a/extensions/gulp/package.json +++ b/extensions/gulp/package.json @@ -26,5 +26,23 @@ "onCommand:workbench.action.tasks.runTask", "onCommand:workbench.action.tasks.build", "onCommand:workbench.action.tasks.test" - ] + ], + "contributes": { + "configuration": { + "id": "gulp", + "type": "object", + "title": "Gulp", + "properties": { + "gulp.autoDetect": { + "type": "string", + "enum": [ + "off", + "on" + ], + "default": "on", + "description": "%config.gulp.autoDetect%" + } + } + } + } } \ No newline at end of file diff --git a/extensions/gulp/package.nls.json b/extensions/gulp/package.nls.json new file mode 100644 index 0000000000000000000000000000000000000000..716f83aa90a7a57a5cc51e9e59dfa1f44d7aba65 --- /dev/null +++ b/extensions/gulp/package.nls.json @@ -0,0 +1,3 @@ +{ + "config.gulp.autoDetect": "Controls whether auto detection of gulp tasks in on or off. Default is on." +} \ No newline at end of file diff --git a/extensions/gulp/src/main.ts b/extensions/gulp/src/main.ts index b535ec5375f2cd42049c3573cb5706910dd355d0..e4bbba3b42245933063fcd2fdddc0a445a4a8fda 100644 --- a/extensions/gulp/src/main.ts +++ b/extensions/gulp/src/main.ts @@ -8,93 +8,138 @@ import * as path from 'path'; import * as fs from 'fs'; import * as cp from 'child_process'; import * as vscode from 'vscode'; +import * as nls from 'vscode-nls'; + +const localize = nls.config(process.env.VSCODE_NLS_CONFIG)(); + +type AutoDetect = 'on' | 'off'; +let taskProvider: vscode.Disposable | undefined; export function activate(_context: vscode.ExtensionContext): void { let workspaceRoot = vscode.workspace.rootPath; if (!workspaceRoot) { return; } - let gulpfile = path.join(workspaceRoot, 'gulpfile.js'); - let gulpPromise: Thenable | undefined = undefined; - let fileWatcher = vscode.workspace.createFileSystemWatcher(gulpfile); + let pattern = path.join(workspaceRoot, 'gulpfile{.babel.js,.js}'); + let gulpPromise: Thenable | undefined = undefined; + let fileWatcher = vscode.workspace.createFileSystemWatcher(pattern); fileWatcher.onDidChange(() => gulpPromise = undefined); fileWatcher.onDidCreate(() => gulpPromise = undefined); fileWatcher.onDidDelete(() => gulpPromise = undefined); - vscode.workspace.registerTaskProvider({ - provideTasks: () => { - if (!gulpPromise) { - gulpPromise = getGulpTasks(); - } - return gulpPromise; + function onConfigurationChanged() { + let autoDetect = vscode.workspace.getConfiguration('gulp').get('autoDetect'); + if (taskProvider && autoDetect === 'off') { + gulpPromise = undefined; + taskProvider.dispose(); + taskProvider = undefined; + } else if (!taskProvider && autoDetect === 'on') { + taskProvider = vscode.workspace.registerTaskProvider({ + provideTasks: () => { + if (!gulpPromise) { + gulpPromise = getGulpTasks(); + } + return gulpPromise; + } + }); } + } + vscode.workspace.onDidChangeConfiguration(onConfigurationChanged); + onConfigurationChanged(); +} + +export function deactivate(): void { + if (taskProvider) { + taskProvider.dispose(); + } +} + +function exists(file: string): Promise { + return new Promise((resolve, _reject) => { + fs.exists(file, (value) => { + resolve(value); + }); }); } -function getGulpTasks(): Thenable { - return new Promise((resolve, _reject) => { - let workspaceRoot = vscode.workspace.rootPath; - let emptyTaskSet = { tasks: [] }; - if (!workspaceRoot) { - return resolve(emptyTaskSet); - } - let gulpfile = path.join(workspaceRoot, 'gulpfile.js'); - fs.exists(gulpfile, (value) => { - if (!value) { - resolve(emptyTaskSet); - return; +function exec(command: string, options: cp.ExecOptions): Promise<{ stdout: string; stderr: string }> { + return new Promise<{ stdout: string; stderr: string }>((resolve, reject) => { + cp.exec(command, options, (error, stdout, stderr) => { + if (error) { + reject({ error, stdout, stderr }); } + resolve({ stdout, stderr }); + }); + }); +} - let commandLine: string; - let platform = process.platform; - if (platform === 'win32' && fs.existsSync(path.join(workspaceRoot!, 'node_modules', '.bin', 'gulp.cmd'))) { - commandLine = `${path.join('.', 'node_modules', '.bin', 'gulp.cmd')} --tasks-simple --no-color`; - } else if ((platform === 'linux' || platform === 'darwin') && fs.existsSync(path.join(workspaceRoot!, 'node_modules', '.bin', 'gulp.cmd'))) { - commandLine = `${path.join('.', 'node_modules', '.bin', 'gulp')} --tasks-simple --no-color`; - } else { - commandLine = 'gulp --tasks-simple --no-color'; - } - cp.exec(commandLine, { cwd: workspaceRoot }, (error, stdout, stderr) => { - let channel = vscode.window.createOutputChannel('tasks'); - if (stderr) { - channel.appendLine(stderr); - } - if (error) { - channel.appendLine(`Auto detecting gulp failed with error: ${error ? error.toString() : 'unknown'}`); - resolve(emptyTaskSet); - return; +async function getGulpTasks(): Promise { + let workspaceRoot = vscode.workspace.rootPath; + let emptyTasks: vscode.Task[] = []; + if (!workspaceRoot) { + return emptyTasks; + } + let gulpfile = path.join(workspaceRoot, 'gulpfile.js'); + if (!await exists(gulpfile)) { + gulpfile = path.join(workspaceRoot, 'gulpfile.babel.js'); + if (! await exists(gulpfile)) { + return emptyTasks; + } + } + + let gulpCommand: string; + let platform = process.platform; + if (platform === 'win32' && await exists(path.join(workspaceRoot!, 'node_modules', '.bin', 'gulp.cmd'))) { + gulpCommand = path.join('.', 'node_modules', '.bin', 'gulp.cmd'); + } else if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(workspaceRoot!, 'node_modules', '.bin', 'gulp'))) { + gulpCommand = path.join('.', 'node_modules', '.bin', 'gulp'); + } else { + gulpCommand = 'gulp'; + } + + let commandLine = `${gulpCommand} --tasks-simple --no-color`; + let channel = vscode.window.createOutputChannel('tasks'); + try { + let { stdout, stderr } = await exec(commandLine, { cwd: workspaceRoot }); + if (stderr) { + channel.appendLine(stderr); + } + let result: vscode.Task[] = []; + if (stdout) { + let buildTask: { task: vscode.Task | undefined, rank: number } = { task: undefined, rank: 0 }; + let testTask: { task: vscode.Task | undefined, rank: number } = { task: undefined, rank: 0 }; + let lines = stdout.split(/\r{0,1}\n/); + for (let line of lines) { + if (line.length === 0) { + continue; } - let result: vscode.TaskSet = { tasks: [], buildTasks: [], testTasks: [] }; - if (stdout) { - let buildTask: { id: string | undefined, rank: number } = { id: undefined, rank: 0 }; - let testTask: { id: string | undefined, rank: number } = { id: undefined, rank: 0 }; - let lines = stdout.split(/\r{0,1}\n/); - for (let line of lines) { - if (line.length === 0) { - continue; - } - let task = new vscode.ShellTask(`gulp ${line}`, `gulp ${line}`); - result.tasks.push(task); - let lowerCaseLine = line.toLowerCase(); - if (lowerCaseLine === 'build') { - buildTask = { id: line, rank: 2 }; - } else if (lowerCaseLine.indexOf('build') !== -1 && buildTask.rank < 1) { - buildTask = { id: line, rank: 1 }; - } else if (lowerCaseLine === 'test') { - testTask = { id: line, rank: 2 }; - } else if (lowerCaseLine.indexOf('test') !== -1 && testTask.rank < 1) { - testTask = { id: line, rank: 1 }; - } - } - if (buildTask.id) { - result.buildTasks!.push(buildTask.id); - } - if (testTask.id) { - result.testTasks!.push(testTask.id); - } + let task = new vscode.ShellTask(`gulp: ${line}`, `${gulpCommand} ${line}`); + task.identifier = `gulp.${line}`; + result.push(task); + let lowerCaseLine = line.toLowerCase(); + if (lowerCaseLine === 'build') { + buildTask = { task, rank: 2 }; + } else if (lowerCaseLine.indexOf('build') !== -1 && buildTask.rank < 1) { + buildTask = { task, rank: 1 }; + } else if (lowerCaseLine === 'test') { + testTask = { task, rank: 2 }; + } else if (lowerCaseLine.indexOf('test') !== -1 && testTask.rank < 1) { + testTask = { task, rank: 1 }; } - resolve(result); - }); - }); - }); + } + if (buildTask.task) { + buildTask.task.group = vscode.TaskGroup.Build; + } + if (testTask.task) { + testTask.task.group = vscode.TaskGroup.Test; + } + } + return result; + } catch (err) { + if (err.stderr) { + channel.appendLine(err.stderr); + } + channel.appendLine(localize('execFailed', 'Auto detecting gulp failed with error: {0}', err.error ? err.error.toString() : 'unknown')); + return emptyTasks; + } } \ No newline at end of file diff --git a/extensions/gulp/tsconfig.json b/extensions/gulp/tsconfig.json index fcfc515e5a57a34f28ff64c289e05a389c971317..d815a565579a26ef3ffe059b4f26ebe8b6137016 100644 --- a/extensions/gulp/tsconfig.json +++ b/extensions/gulp/tsconfig.json @@ -3,8 +3,7 @@ "target": "es6", "module": "commonjs", "lib": [ - "es6", - "es2015.promise" + "es2016" ], "outDir": "./out", "strictNullChecks": true, diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 35d532982af73996a6927134a1901efbbd6ffe03..121735849071ef5d0b0cb1ee936ebeac616ec498 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -267,6 +267,30 @@ declare module 'vscode' { env?: { [key: string]: string }; } + export namespace TaskGroup { + /** + * The clean task group + */ + export const Clean: 'clean'; + /** + * The build task group + */ + export const Build: 'build'; + /** + * The rebuild all task group + */ + export const RebuildAll: 'rebuildAll'; + /** + * The test task group + */ + export const Test: 'test'; + } + + /** + * The supported task groups. + */ + export type TaskGroup = 'clean' | 'build' | 'rebuildAll' | 'test'; + /** * A task that starts an external process. */ @@ -328,6 +352,12 @@ declare module 'vscode' { */ args: string[]; + /** + * The task group this tasks belongs to. Defaults to undefined meaning + * that the task doesn't belong to any special group. + */ + group?: TaskGroup; + /** * The process options used when the process is executed. * Defaults to an empty object literal. @@ -374,7 +404,7 @@ declare module 'vscode' { * The current working directory of the executed shell. * If omitted VSCode's current workspace root is used. */ - cwd?: string; + cwd: string; /** * The additional environment of the executed shell. If omitted @@ -382,6 +412,19 @@ declare module 'vscode' { * the parent process' environment. */ env?: { [key: string]: string }; + } | { + /** + * The current working directory of the executed shell. + * If omitted VSCode's current workspace root is used. + */ + cwd?: string; + + /** + * The additional environment of the executed shell. If omitted + * the parent process' environment is used. If provided it is merged with + * the parent process' environment. + */ + env: { [key: string]: string }; }; /** @@ -429,6 +472,12 @@ declare module 'vscode' { */ readonly commandLine: string; + /** + * The task group this tasks belongs to. Defaults to undefined meaning + * that the task doesn't belong to any special group. + */ + group?: TaskGroup; + /** * The shell options used when the shell is executed. Defaults to an * empty object literal. @@ -449,29 +498,6 @@ declare module 'vscode' { export type Task = ProcessTask | ShellTask; - /** - * Result return from a task provider. - */ - export interface TaskSet { - /** - * The actual tasks returned. - */ - tasks: Task[]; - - /** - * The build tasks provided. Tasks must be identified using - * `Task.identifier` - */ - buildTasks?: string[]; - - /** - * The test tasks provided. Tasks must be identified using - * `Task.identifier` - */ - testTasks?: string[]; - } - - /** * A task provider allows to add tasks to the task service. * A task provider is registerd via #workspace.registerTaskProvider. @@ -482,7 +508,7 @@ declare module 'vscode' { * @param token A cancellation token. * @return a #TaskSet */ - provideTasks(token: CancellationToken): ProviderResult; + provideTasks(token: CancellationToken): ProviderResult; } export namespace workspace { diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 548a6168d75656ca398358a9f992d27ae99abe16..df75d66cc0acd6f445db89dc280077dc11a52b3c 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -529,6 +529,7 @@ export function createApiFactory( FileLocationKind: extHostTypes.FileLocationKind, ApplyToKind: extHostTypes.ApplyToKind, RevealKind: extHostTypes.RevealKind, + TaskGroup: extHostTypes.TaskGroup, ShellTask: extHostTypes.ShellTask, ProcessTask: extHostTypes.ProcessTask }; diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index 44c71b83fb1fefffcb2f46f0e152055d53ceb00b..67bcbec00c9e2783fc08b59c71990be1c917c6f7 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -309,6 +309,7 @@ namespace Tasks { _id: uuidMap.getUUID(task.identifier), name: task.name, identifier: task.identifier, + group: types.TaskGroup.is(task.group) ? task.group : undefined, command: command, showOutput: behaviour.showOutput, isBackground: !!task.isBackground, @@ -381,57 +382,6 @@ class UUIDMap { } } -namespace TaskSet { - - const idMaps: Map = new Map(); - - function getUUIDMap(extensionId: string): UUIDMap { - let result = idMaps.get(extensionId); - if (result) { - return result; - } - result = new UUIDMap(); - idMaps.set(extensionId, result); - return result; - } - - export function from(extension: IExtensionDescription, value: vscode.TaskSet): TaskSystem.TaskSet { - if (value === void 0 || value === null || !Array.isArray(value.tasks)) { - return { tasks: Object.create(null) }; - } - - let tasks = Tasks.from(value.tasks, getUUIDMap(extension.id)); - let buildTasks: string[]; - let testTasks: string[]; - if (value.buildTasks || value.testTasks) { - let map: Map = new Map(); - tasks.forEach(task => map.set(task.identifier, task)); - if (Array.isArray(value.buildTasks)) { - buildTasks = []; - for (let elem of value.buildTasks) { - if (typeof elem === 'string' && map.has(elem)) { - buildTasks.push(map.get(elem)._id); - } - } - } - if (Array.isArray(value.testTasks)) { - testTasks = []; - for (let elem of value.testTasks) { - if (typeof elem === 'string' && map.has(elem)) { - testTasks.push(map.get(elem)._id); - } - } - } - } - - return { - tasks, - buildTasks, - testTasks - }; - } -} - interface HandlerData { provider: vscode.TaskProvider; extension: IExtensionDescription; @@ -442,12 +392,14 @@ export class ExtHostTask extends ExtHostTaskShape { private _proxy: MainThreadTaskShape; private _handleCounter: number; private _handlers: Map; + private _idMaps: Map; constructor(threadService: IThreadService) { super(); this._proxy = threadService.get(MainContext.MainThreadTask); this._handleCounter = 0; this._handlers = new Map(); + this._idMaps = new Map(); }; public registerTaskProvider(extension: IExtensionDescription, provider: vscode.TaskProvider): vscode.Disposable { @@ -469,11 +421,24 @@ export class ExtHostTask extends ExtHostTaskShape { return TPromise.wrapError(new Error('no handler found')); } return asWinJsPromise(token => handler.provider.provideTasks(token)).then(value => { - return TaskSet.from(handler.extension, value); + return { + tasks: Tasks.from(value, this.getUUIDMap(handler.extension.id)), + extension: handler.extension + }; }); } private nextHandle(): number { return this._handleCounter++; } + + private getUUIDMap(extensionId: string): UUIDMap { + let result = this._idMaps.get(extensionId); + if (result) { + return result; + } + result = new UUIDMap(); + this._idMaps.set(extensionId, result); + return result; + } } \ No newline at end of file diff --git a/src/vs/workbench/api/node/extHostTypes.ts b/src/vs/workbench/api/node/extHostTypes.ts index 0c5b8147fec8045332e6215dcce54a557e674e69..9fd91ded0c26fe8beb7d1654aa211c44b026d9dd 100644 --- a/src/vs/workbench/api/node/extHostTypes.ts +++ b/src/vs/workbench/api/node/extHostTypes.ts @@ -1033,9 +1033,12 @@ export class BaseTask { } set identifier(value: string) { - if (typeof name !== 'string') { + if (typeof value !== 'string') { throw illegalArgument('identifier'); } + if (value.indexOf(':') !== -1) { + throw illegalArgument('identifier must not contain \':\''); + } this._identifier = value; } @@ -1084,11 +1087,37 @@ namespace ProblemMatcher { } } +export namespace TaskGroup { + /** + * The clean task group + */ + export const Clean: 'clean' = 'clean'; + + /** + * The build task group + */ + export const Build: 'build' = 'build'; + + /** + * The rebuild all task group + */ + export const RebuildAll: 'rebuildAll' = 'rebuildAll'; + + /** + * The test task group + */ + export const Test: 'test' = 'test'; + + export function is(value: string): value is vscode.TaskGroup { + return value === Clean || value === Build || value === RebuildAll || value === Test; + } +} export class ProcessTask extends BaseTask { private _process: string; private _args: string[]; + private _group: vscode.TaskGroup; private _options: vscode.ProcessOptions; private static parseArguments(restArgs: any[]): { args: string[]; options: vscode.ProcessOptions; problemMatchers: vscode.ProblemMatcher[] } { @@ -1145,6 +1174,17 @@ export class ProcessTask extends BaseTask { this._args = value; } + get group(): vscode.TaskGroup { + return this._group; + } + + set group(value: vscode.TaskGroup) { + if (!TaskGroup.is(value)) { + throw illegalArgument('group'); + } + this._group = value; + } + get options(): vscode.ProcessOptions { return this._options; } @@ -1160,6 +1200,7 @@ export class ProcessTask extends BaseTask { export class ShellTask extends BaseTask { private _commandLine: string; + private _group: vscode.TaskGroup; private _options: vscode.ShellOptions; private static parseArguments(restArgs: any[]): { options: vscode.ShellOptions; problemMatchers: vscode.ProblemMatcher[] } { @@ -1197,6 +1238,17 @@ export class ShellTask extends BaseTask { return this._commandLine; } + get group(): vscode.TaskGroup { + return this._group; + } + + set group(value: vscode.TaskGroup) { + if (!TaskGroup.is(value)) { + throw illegalArgument('group'); + } + this._group = value; + } + get options(): vscode.ShellOptions { return this._options; } diff --git a/src/vs/workbench/parts/tasks/common/taskConfiguration.ts b/src/vs/workbench/parts/tasks/common/taskConfiguration.ts index 88b7373f0634aa86b97cf9842cb0893fb33d3591..f16012f0167abf9d966f97b5072749df7813e7b9 100644 --- a/src/vs/workbench/parts/tasks/common/taskConfiguration.ts +++ b/src/vs/workbench/parts/tasks/common/taskConfiguration.ts @@ -286,12 +286,6 @@ function mergeProperty(target: T, source: T, key: K) { } } -function fillProperty(target: T, source: T, key: K) { - if (target[key] === void 0 && source[key] !== void 0) { - target[key] = source[key]; - } -} - interface ParseContext { problemReporter: IProblemReporter; namedProblemMatchers: IStringDictionary; @@ -639,23 +633,13 @@ namespace ProblemMatcherConverter { namespace TaskDescription { - export interface TaskConfiguration { - tasks: Tasks.Task[]; - buildTask?: string; - testTask?: string; - } - - export function isEmpty(value: TaskConfiguration): boolean { - return !value || !value.tasks || Object.keys(value.tasks).length === 0; - } - - export function from(this: void, tasks: TaskDescription[], globals: Globals, context: ParseContext): TaskConfiguration { + export function from(this: void, tasks: TaskDescription[], globals: Globals, context: ParseContext): Tasks.Task[] { if (!tasks) { return undefined; } let parsedTasks: Tasks.Task[] = []; - let defaultBuildTask: { id: string; exact: number; } = { id: null, exact: -1 }; - let defaultTestTask: { id: string; exact: number; } = { id: null, exact: -1 }; + let defaultBuildTask: { task: Tasks.Task; rank: number; } = { task: null, rank: -1 }; + let defaultTestTask: { task: Tasks.Task; rank: number; } = { task: null, rank: -1 }; tasks.forEach((externalTask) => { let taskName = externalTask.taskName; if (!taskName) { @@ -733,68 +717,57 @@ namespace TaskDescription { } if (addTask) { parsedTasks.push(task); - if (!Types.isUndefined(externalTask.isBuildCommand) && externalTask.isBuildCommand && defaultBuildTask.exact < 2) { - defaultBuildTask.id = task._id; - defaultBuildTask.exact = 2; - } else if (taskName === 'build' && defaultBuildTask.exact < 2) { - defaultBuildTask.id = task._id; - defaultBuildTask.exact = 1; + if (!Types.isUndefined(externalTask.isBuildCommand) && externalTask.isBuildCommand && defaultBuildTask.rank < 2) { + defaultBuildTask.task = task; + defaultBuildTask.rank = 2; + } else if (taskName === 'build' && defaultBuildTask.rank < 2) { + defaultBuildTask.task = task; + defaultBuildTask.rank = 1; } - if (!Types.isUndefined(externalTask.isTestCommand) && externalTask.isTestCommand && defaultTestTask.exact < 2) { - defaultTestTask.id = task._id; - defaultTestTask.exact = 2; - } else if (taskName === 'test' && defaultTestTask.exact < 2) { - defaultTestTask.id = task._id; - defaultTestTask.exact = 1; + if (!Types.isUndefined(externalTask.isTestCommand) && externalTask.isTestCommand && defaultTestTask.rank < 2) { + defaultTestTask.task = task; + defaultTestTask.rank = 2; + } else if (taskName === 'test' && defaultTestTask.rank < 2) { + defaultTestTask.task = task; + defaultTestTask.rank = 1; } } }); - let buildTask: string; - if (defaultBuildTask.exact > 0) { - buildTask = defaultBuildTask.id; + if (defaultBuildTask.task) { + defaultBuildTask.task.group = Tasks.TaskGroup.Build; } - let testTask: string; - if (defaultTestTask.exact > 0) { - testTask = defaultTestTask.id; + if (defaultTestTask.task) { + defaultTestTask.task.group = Tasks.TaskGroup.Test; } - let result = { tasks: parsedTasks, buildTask, testTask }; - return isEmpty(result) ? undefined : result; + return parsedTasks.length === 0 ? undefined : parsedTasks; } - export function merge(target: TaskConfiguration, source: TaskConfiguration): TaskConfiguration { - if (isEmpty(source)) { + export function merge(target: Tasks.Task[], source: Tasks.Task[]): Tasks.Task[] { + if (source === void 0 || source.length === 0) { return target; } - if (isEmpty(target)) { + if (target === void 0 || target.length === 0) { return source; } - if (source.tasks) { + if (source) { // Tasks are keyed by ID but we need to merge by name - let targetNames: IStringDictionary = Object.create(null); - Object.keys(target.tasks).forEach(key => { - let task = target.tasks[key]; - targetNames[task.name] = task.id; + let map: IStringDictionary = Object.create(null); + target.forEach((task) => { + map[task.name] = task; }); - let sourceNames: IStringDictionary = Object.create(null); - Object.keys(source.tasks).forEach(key => { - let task = source.tasks[key]; - sourceNames[task.name] = task.id; + source.forEach((task) => { + map[task.name] = task; }); - - Object.keys(sourceNames).forEach(taskName => { - let targetId = targetNames[taskName]; - let sourceId = sourceNames[taskName]; - // Same name exists globally - if (targetId) { - delete target.tasks[targetId]; - } - target.tasks[sourceId] = source.tasks[sourceId]; + let newTarget: Tasks.Task[] = []; + target.forEach(task => { + newTarget.push(map[task.name]); + delete map[task.name]; }); + Object.keys(map).forEach(key => newTarget.push(map[key])); + target = newTarget; } - fillProperty(target, source, 'buildTask'); - fillProperty(target, source, 'testTask'); return target; } @@ -976,7 +949,7 @@ export namespace ExecutionEngine { export interface ParseResult { validationStatus: ValidationStatus; - taskSet: Tasks.TaskSet; + tasks: Tasks.Task[]; engine: Tasks.ExecutionEngine; } @@ -1000,18 +973,18 @@ class ConfigurationParser { let context: ParseContext = { problemReporter: this.problemReporter, namedProblemMatchers: undefined, isTermnial: engine === Tasks.ExecutionEngine.Terminal }; return { validationStatus: this.problemReporter.status, - taskSet: this.createTaskRunnerConfiguration(fileConfig, context), + tasks: this.createTaskRunnerConfiguration(fileConfig, context), engine }; } - private createTaskRunnerConfiguration(fileConfig: ExternalTaskRunnerConfiguration, context: ParseContext): Tasks.TaskSet { + private createTaskRunnerConfiguration(fileConfig: ExternalTaskRunnerConfiguration, context: ParseContext): Tasks.Task[] { let globals = Globals.from(fileConfig, context); if (this.problemReporter.status.isFatal()) { return undefined; } context.namedProblemMatchers = ProblemMatcherConverter.namedFrom(fileConfig.declares, context); - let globalTasks: TaskDescription.TaskConfiguration; + let globalTasks: Tasks.Task[]; if (fileConfig.windows && Platform.platform === Platform.Platform.Windows) { globalTasks = TaskDescription.from(fileConfig.windows.tasks, globals, context); } else if (fileConfig.osx && Platform.platform === Platform.Platform.Mac) { @@ -1020,15 +993,13 @@ class ConfigurationParser { globalTasks = TaskDescription.from(fileConfig.linux.tasks, globals, context); } - let taskConfig: TaskDescription.TaskConfiguration; + let tasks: Tasks.Task[]; if (fileConfig.tasks) { - taskConfig = TaskDescription.from(fileConfig.tasks, globals, context); + tasks = TaskDescription.from(fileConfig.tasks, globals, context); } - taskConfig = TaskDescription.merge(taskConfig, globalTasks); + tasks = TaskDescription.merge(tasks, globalTasks); - if (TaskDescription.isEmpty(taskConfig)) { - let tasks: Tasks.Task[] = []; - let buildTask: string; + if (!tasks || tasks.length === 0) { if (globals.command && globals.command.name) { let matchers: ProblemMatcher[] = ProblemMatcherConverter.from(fileConfig.problemMatcher, context);; let isBackground = fileConfig.isBackground ? !!fileConfig.isBackground : fileConfig.isWatching ? !!fileConfig.isWatching : undefined; @@ -1036,6 +1007,7 @@ class ConfigurationParser { _id: UUID.generateUuid(), name: globals.command.name, identifier: UUID.generateUuid(), + group: Tasks.TaskGroup.Build, command: undefined, isBackground: isBackground, showOutput: undefined, @@ -1044,21 +1016,10 @@ class ConfigurationParser { }; TaskDescription.mergeGlobals(task, globals); TaskDescription.fillDefaults(task); - tasks.push(task); - buildTask = task._id; + tasks = [task]; } - - taskConfig = { - tasks: tasks, - buildTask - }; } - - return { - tasks: taskConfig.tasks, - buildTasks: taskConfig.buildTask ? [taskConfig.buildTask] : [], - testTasks: taskConfig.testTask ? [taskConfig.testTask] : [] - }; + return tasks || []; } } diff --git a/src/vs/workbench/parts/tasks/common/tasks.ts b/src/vs/workbench/parts/tasks/common/tasks.ts index 94b523dc921a3c199305d1daa996e4cdb1e67f50..446ae9ca08c6df4a6fa2700a5fd5c8dc2622604e 100644 --- a/src/vs/workbench/parts/tasks/common/tasks.ts +++ b/src/vs/workbench/parts/tasks/common/tasks.ts @@ -6,6 +6,7 @@ import * as Types from 'vs/base/common/types'; +import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { ProblemMatcher } from 'vs/platform/markers/common/problemMatcher'; export interface CommandOptions { @@ -93,6 +94,22 @@ export namespace ShowOutput { } } +export namespace TaskGroup { + export const Clean: 'clean' = 'clean'; + + export const Build: 'build' = 'build'; + + export const RebuildAll: 'rebuildAll' = 'rebuildAll'; + + export const Test: 'test' = 'test'; + + export function is(value: string): value is TaskGroup { + return value === Clean || value === Build || value === RebuildAll || value === Test; + } +} + +export type TaskGroup = 'clean' | 'build' | 'rebuildAll' | 'test'; + /** * A task description */ @@ -113,6 +130,11 @@ export interface Task { */ identifier: string; + /** + * the task's group; + */ + group?: TaskGroup; + /** * The command configuration */ @@ -156,28 +178,13 @@ export interface Task { problemMatchers?: ProblemMatcher[]; } -/** - * Describes a task set. - */ -export interface TaskSet { - /** - * The inferred build tasks - */ - buildTasks?: string[]; - - /** - * The inferred test tasks; - */ - testTasks?: string[]; - - /** - * The configured tasks - */ - tasks: Task[]; -} - export enum ExecutionEngine { Unknown = 0, Terminal = 1, Process = 2 +} + +export interface TaskSet { + tasks: Task[]; + extension?: IExtensionDescription; } \ No newline at end of file diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 5d7a270ddee36ab0364073028c0d327ba2b82717..36905d02d90d1bd73729e30960b635bf13d752a6 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -69,7 +69,7 @@ import { IOutputService, IOutputChannelRegistry, Extensions as OutputExt, IOutpu import { ITerminalService } from 'vs/workbench/parts/terminal/common/terminal'; import { ITaskSystem, ITaskResolver, ITaskSummary, ITaskExecuteResult, TaskExecuteKind, TaskError, TaskErrors, TaskSystemEvents } from 'vs/workbench/parts/tasks/common/taskSystem'; -import { Task, TaskSet, ExecutionEngine, ShowOutput } from 'vs/workbench/parts/tasks/common/tasks'; +import { Task, TaskSet, TaskGroup, ExecutionEngine, ShowOutput } from 'vs/workbench/parts/tasks/common/tasks'; import { ITaskService, TaskServiceEvents, ITaskProvider } from 'vs/workbench/parts/tasks/common/taskService'; import { templates as taskTemplates } from 'vs/workbench/parts/tasks/common/taskTemplates'; @@ -467,7 +467,7 @@ class ProblemReporter implements TaskConfig.IProblemReporter { } interface WorkspaceTaskResult { - taskSet: TaskSet; + set: TaskSet; hasErrors: boolean; } @@ -646,7 +646,7 @@ class TaskService extends EventEmitter implements ITaskService { public build(): TPromise { return this.getTaskSets().then((values) => { - let runnable = this.createRunnableTask(values, (set) => set.buildTasks); + let runnable = this.createRunnableTask(values, TaskGroup.Build); if (!runnable || !runnable.task) { throw new TaskError(Severity.Info, nls.localize('TaskService.noBuildTask', 'No build task defined. Mark a task with \'isBuildCommand\' in the tasks.json file.'), TaskErrors.NoBuildTask); } @@ -667,7 +667,7 @@ class TaskService extends EventEmitter implements ITaskService { public runTest(): TPromise { return this.getTaskSets().then((values) => { - let runnable = this.createRunnableTask(values, (set) => set.testTasks); + let runnable = this.createRunnableTask(values, TaskGroup.Test); if (!runnable || !runnable.task) { throw new TaskError(Severity.Info, nls.localize('TaskService.noTestTask', 'No test task defined. Mark a task with \'isTestCommand\' in the tasks.json file.'), TaskErrors.NoTestTask); } @@ -701,22 +701,21 @@ class TaskService extends EventEmitter implements ITaskService { }); } - private createRunnableTask(sets: TaskSet[], idFetcher: (set: TaskSet) => string[]): { task: Task; resolver: ITaskResolver } { + private createRunnableTask(sets: TaskSet[], group: TaskGroup): { task: Task; resolver: ITaskResolver } { let uuidMap: IStringDictionary = Object.create(null); let identifierMap: IStringDictionary = Object.create(null); - let taskIds: string[] = []; + let primaryTasks: Task[] = []; sets.forEach((set) => { set.tasks.forEach((task) => { uuidMap[task._id] = task; identifierMap[task.identifier] = task; + if (group && task.group === group) { + primaryTasks.push(task); + } }); - let ids: string[] = idFetcher(set); - if (ids) { - taskIds.push(...ids); - } }); - if (taskIds.length === 0) { + if (primaryTasks.length === 0) { return undefined; } let resolver: ITaskResolver = { @@ -728,15 +727,15 @@ class TaskService extends EventEmitter implements ITaskService { return identifierMap[id]; } }; - if (taskIds.length === 1) { - return { task: resolver.resolve(taskIds[0]), resolver }; + if (primaryTasks.length === 1) { + return { task: primaryTasks[0], resolver }; } else { let id: string = UUID.generateUuid(); let task: Task = { _id: id, name: id, identifier: id, - dependsOn: taskIds, + dependsOn: primaryTasks.map(task => task._id), command: undefined, showOutput: ShowOutput.Never }; @@ -880,7 +879,7 @@ class TaskService extends EventEmitter implements ITaskService { if (this._taskSystem instanceof ProcessTaskSystem) { this._taskSystem.hasErrors(this._configHasErrors); } - return value.taskSet; + return value.set; }); return this._workspaceTasksPromise; } @@ -888,7 +887,7 @@ class TaskService extends EventEmitter implements ITaskService { private updateWorkspaceTasks(): void { this._workspaceTasksPromise = this.computeWorkspaceTasks().then(value => { this._configHasErrors = value.hasErrors; - return value.taskSet; + return value.set; }); } @@ -897,7 +896,7 @@ class TaskService extends EventEmitter implements ITaskService { { let { config, hasParseErrors } = this.getConfiguration(); if (hasParseErrors) { - return TPromise.as({ taskSet: undefined, hasErrors: true }); + return TPromise.as({ set: undefined, hasErrors: true }); } if (config) { let engine = TaskConfig.ExecutionEngine.from(config); @@ -950,7 +949,7 @@ class TaskService extends EventEmitter implements ITaskService { problemReporter.fatal(nls.localize('TaskSystem.configurationErrors', 'Error: the provided task configuration has validation errors and can\'t not be used. Please correct the errors first.')); return { taskSet: undefined, hasErrors }; } - return { taskSet: parseResult.taskSet, hasErrors }; + return { set: { tasks: parseResult.tasks }, hasErrors }; }); }); } diff --git a/src/vs/workbench/parts/tasks/test/node/configuration.test.ts b/src/vs/workbench/parts/tasks/test/node/configuration.test.ts index d0a0dd5390c899fcab97514abe44b492d2dbafe0..fd07989830bf151292085c6bb99744654461b5f1 100644 --- a/src/vs/workbench/parts/tasks/test/node/configuration.test.ts +++ b/src/vs/workbench/parts/tasks/test/node/configuration.test.ts @@ -55,31 +55,17 @@ class ProblemReporter implements IProblemReporter { class ConfiguationBuilder { - public result: Tasks.TaskSet; + public result: Tasks.Task[]; constructor() { - this.result = { - tasks: [], - buildTasks: [], - testTasks: [] - }; + this.result = []; } public task(name: string, command: string): TaskBuilder { let builder = new TaskBuilder(this, name, command); - this.result.tasks.push(builder.result); + this.result.push(builder.result); return builder; } - - public buildTask(id: string): ConfiguationBuilder { - this.result.buildTasks.push(id); - return this; - } - - public testTask(id: string): ConfiguationBuilder { - this.result.testTasks.push(id); - return this; - } } class CommandConfigurationBuilder { @@ -153,6 +139,11 @@ class TaskBuilder { return this; } + public group(value: Tasks.TaskGroup): TaskBuilder { + this.result.group = value; + return this; + } + public args(value: string[]): TaskBuilder { this.result.args = value; return this; @@ -308,12 +299,10 @@ function testDefaultProblemMatcher(external: ExternalTaskRunnerConfiguration, re let reporter = new ProblemReporter(); let result = parse(external, reporter); assert.ok(!reporter.receivedMessage); - let taskSet = result.taskSet; - assert.strictEqual(taskSet.tasks.length, 1); - let task = taskSet.tasks[0]; + assert.strictEqual(result.tasks.length, 1); + let task = result.tasks[0]; assert.ok(task); assert.strictEqual(task.problemMatchers.length, resolved); - } function testConfiguration(external: ExternalTaskRunnerConfiguration, builder: ConfiguationBuilder): void { @@ -325,52 +314,86 @@ function testConfiguration(external: ExternalTaskRunnerConfiguration, builder: C assertConfiguration(result, builder.result); } -function assertConfiguration(result: ParseResult, expected: Tasks.TaskSet) { - assert.ok(result.validationStatus.isOK()); - let actual = result.taskSet; - assert.strictEqual(typeof actual.tasks, typeof expected.tasks); - let actualBuildTasks: string[] = []; - let actualTestTasks: string[] = []; - if (actual.tasks && expected.tasks) { - // We can't compare Ids since the parser uses UUID which are random - // So create a new map using the name. - let actualTasks: { [key: string]: Tasks.Task; } = Object.create(null); - let actualId2Name: { [key: string]: string; } = Object.create(null); - actual.tasks.forEach(task => { - assert.ok(!actualTasks[task.name]); - actualTasks[task.name] = task; - actualId2Name[task._id] = task.name; - }); - let expectedTasks: { [key: string]: Tasks.Task; } = Object.create(null); - expected.tasks.forEach(task => { - assert.ok(!expectedTasks[task.name]); - expectedTasks[task.name] = task; - }); - let actualKeys = Object.keys(actualTasks); - assert.strictEqual(actualKeys.length, Object.keys(expected.tasks).length); +class TaskGroupMap { + private _store: { [key: string]: Tasks.Task[] }; + + constructor() { + this._store = Object.create(null); + } + + public add(group: string, task: Tasks.Task): void { + let tasks = this._store[group]; + if (!tasks) { + tasks = []; + this._store[group] = tasks; + } + tasks.push(task); + } + + public static assert(actual: TaskGroupMap, expected: TaskGroupMap): void { + let actualKeys = Object.keys(actual._store); + let expectedKeys = Object.keys(expected._store); + if (actualKeys.length === 0 && expectedKeys.length === 0) { + return; + } + assert.strictEqual(actualKeys.length, expectedKeys.length); + actualKeys.forEach(key => assert.ok(expected._store[key])); + expectedKeys.forEach(key => actual._store[key]); actualKeys.forEach((key) => { - let actualTask = actualTasks[key]; - let expectedTask = expectedTasks[key]; - assert.ok(expectedTask); - assertTask(actualTask, expectedTask); - }); - actual.buildTasks.forEach((id) => { - actualBuildTasks.push(actualId2Name[id]); - }); - actual.testTasks.forEach((id) => { - actualTestTasks.push(actualId2Name[id]); + let actualTasks = actual._store[key]; + let expectedTasks = expected._store[key]; + assert.strictEqual(actualTasks.length, expectedTasks.length); + if (actualTasks.length === 1) { + assert.strictEqual(actualTasks[0].name, expectedTasks[0].name); + return; + } + let expectedTaskMap: { [key: string]: boolean } = Object.create(null); + expectedTasks.forEach(task => expectedTaskMap[task.name] = true); + actualTasks.forEach(task => delete expectedTaskMap[task.name]); + assert.strictEqual(Object.keys(expectedTaskMap).length, 0); }); } - assertTaskConfig(actualBuildTasks, expected.buildTasks); - assertTaskConfig(actualTestTasks, expected.testTasks); } -function assertTaskConfig(actual: string[], expected: string[]): void { +function assertConfiguration(result: ParseResult, expected: Tasks.Task[]): void { + assert.ok(result.validationStatus.isOK()); + let actual = result.tasks; assert.strictEqual(typeof actual, typeof expected); - if (actual && expected) { - assert.strictEqual(actual.length, expected.length); - assert.deepEqual(actual, expected); + if (!actual) { + return; } + + // We can't compare Ids since the parser uses UUID which are random + // So create a new map using the name. + let actualTasks: { [key: string]: Tasks.Task; } = Object.create(null); + let actualId2Name: { [key: string]: string; } = Object.create(null); + let actualTaskGroups = new TaskGroupMap(); + actual.forEach(task => { + assert.ok(!actualTasks[task.name]); + actualTasks[task.name] = task; + actualId2Name[task._id] = task.name; + if (task.group) { + actualTaskGroups.add(task.group, task); + } + }); + let expectedTasks: { [key: string]: Tasks.Task; } = Object.create(null); + let expectedTaskGroup = new TaskGroupMap(); + expected.forEach(task => { + assert.ok(!expectedTasks[task.name]); + expectedTasks[task.name] = task; + if (task.group) { + expectedTaskGroup.add(task.group, task); + } + }); + let actualKeys = Object.keys(actualTasks); + assert.strictEqual(actualKeys.length, expected.length); + actualKeys.forEach((key) => { + let actualTask = actualTasks[key]; + let expectedTask = expectedTasks[key]; + assert.ok(expectedTask); + assertTask(actualTask, expectedTask); + }); + TaskGroupMap.assert(actualTaskGroups, expectedTaskGroup); } function assertTask(actual: Tasks.Task, expected: Tasks.Task) { @@ -461,8 +484,9 @@ function assertProblemPattern(actual: ProblemPattern, expected: ProblemPattern) suite('Tasks Configuration parsing tests', () => { test('tasks: all default', () => { - let builder = new ConfiguationBuilder().buildTask('tsc'); + let builder = new ConfiguationBuilder(); builder.task('tsc', 'tsc'). + group(Tasks.TaskGroup.Build). suppressTaskName(true); testConfiguration( { @@ -472,8 +496,9 @@ suite('Tasks Configuration parsing tests', () => { }); test('tasks: global isShellCommand', () => { - let builder = new ConfiguationBuilder().buildTask('tsc'); + let builder = new ConfiguationBuilder(); builder.task('tsc', 'tsc'). + group(Tasks.TaskGroup.Build). suppressTaskName(true). command(). shell(true); @@ -487,9 +512,10 @@ suite('Tasks Configuration parsing tests', () => { }); test('tasks: global show output silent', () => { - let builder = new ConfiguationBuilder().buildTask('tsc'); + let builder = new ConfiguationBuilder(); builder. task('tsc', 'tsc'). + group(Tasks.TaskGroup.Build). suppressTaskName(true). showOutput(Tasks.ShowOutput.Silent); testConfiguration( @@ -503,8 +529,9 @@ suite('Tasks Configuration parsing tests', () => { }); test('tasks: global promptOnClose default', () => { - let builder = new ConfiguationBuilder().buildTask('tsc'); + let builder = new ConfiguationBuilder(); builder.task('tsc', 'tsc'). + group(Tasks.TaskGroup.Build). suppressTaskName(true); testConfiguration( { @@ -517,9 +544,10 @@ suite('Tasks Configuration parsing tests', () => { }); test('tasks: global promptOnClose', () => { - let builder = new ConfiguationBuilder().buildTask('tsc'); + let builder = new ConfiguationBuilder(); builder.task('tsc', 'tsc'). suppressTaskName(true). + group(Tasks.TaskGroup.Build). promptOnClose(false); testConfiguration( { @@ -532,9 +560,10 @@ suite('Tasks Configuration parsing tests', () => { }); test('tasks: global promptOnClose default watching', () => { - let builder = new ConfiguationBuilder().buildTask('tsc'); + let builder = new ConfiguationBuilder(); builder.task('tsc', 'tsc'). suppressTaskName(true). + group(Tasks.TaskGroup.Build). isBackground(true). promptOnClose(false); testConfiguration( @@ -548,9 +577,10 @@ suite('Tasks Configuration parsing tests', () => { }); test('tasks: global show output never', () => { - let builder = new ConfiguationBuilder().buildTask('tsc'); + let builder = new ConfiguationBuilder(); builder. task('tsc', 'tsc'). + group(Tasks.TaskGroup.Build). suppressTaskName(true). showOutput(Tasks.ShowOutput.Never); testConfiguration( @@ -564,9 +594,10 @@ suite('Tasks Configuration parsing tests', () => { }); test('tasks: global echo Command', () => { - let builder = new ConfiguationBuilder().buildTask('tsc'); + let builder = new ConfiguationBuilder(); builder. task('tsc', 'tsc'). + group(Tasks.TaskGroup.Build). suppressTaskName(true). command(). echo(true); @@ -581,9 +612,10 @@ suite('Tasks Configuration parsing tests', () => { }); test('tasks: global args', () => { - let builder = new ConfiguationBuilder().buildTask('tsc'); + let builder = new ConfiguationBuilder(); builder. task('tsc', 'tsc'). + group(Tasks.TaskGroup.Build). suppressTaskName(true). command(). args(['--p']); @@ -600,9 +632,10 @@ suite('Tasks Configuration parsing tests', () => { }); test('tasks: options - cwd', () => { - let builder = new ConfiguationBuilder().buildTask('tsc'); + let builder = new ConfiguationBuilder(); builder. task('tsc', 'tsc'). + group(Tasks.TaskGroup.Build). suppressTaskName(true). command(). options({ @@ -621,9 +654,10 @@ suite('Tasks Configuration parsing tests', () => { }); test('tasks: options - env', () => { - let builder = new ConfiguationBuilder().buildTask('tsc'); + let builder = new ConfiguationBuilder(); builder. task('tsc', 'tsc'). + group(Tasks.TaskGroup.Build). suppressTaskName(true). command(). options({ cwd: '${workspaceRoot}', env: { key: 'value' } }); @@ -643,9 +677,10 @@ suite('Tasks Configuration parsing tests', () => { test('tasks: os windows', () => { let name: string = Platform.isWindows ? 'tsc.win' : 'tsc'; - let builder = new ConfiguationBuilder().buildTask(name); + let builder = new ConfiguationBuilder(); builder. task(name, name). + group(Tasks.TaskGroup.Build). suppressTaskName(true); let external: ExternalTaskRunnerConfiguration = { version: '0.1.0', @@ -659,9 +694,10 @@ suite('Tasks Configuration parsing tests', () => { test('tasks: os windows & global isShellCommand', () => { let name: string = Platform.isWindows ? 'tsc.win' : 'tsc'; - let builder = new ConfiguationBuilder().buildTask(name); + let builder = new ConfiguationBuilder(); builder. task(name, name). + group(Tasks.TaskGroup.Build). suppressTaskName(true). command(). shell(true); @@ -678,9 +714,10 @@ suite('Tasks Configuration parsing tests', () => { test('tasks: os mac', () => { let name: string = Platform.isMacintosh ? 'tsc.osx' : 'tsc'; - let builder = new ConfiguationBuilder().buildTask(name); + let builder = new ConfiguationBuilder(); builder. task(name, name). + group(Tasks.TaskGroup.Build). suppressTaskName(true); let external: ExternalTaskRunnerConfiguration = { version: '0.1.0', @@ -694,9 +731,10 @@ suite('Tasks Configuration parsing tests', () => { test('tasks: os linux', () => { let name: string = Platform.isLinux ? 'tsc.linux' : 'tsc'; - let builder = new ConfiguationBuilder().buildTask(name); + let builder = new ConfiguationBuilder(); builder. task(name, name). + group(Tasks.TaskGroup.Build). suppressTaskName(true); let external: ExternalTaskRunnerConfiguration = { version: '0.1.0', @@ -709,9 +747,10 @@ suite('Tasks Configuration parsing tests', () => { }); test('tasks: overwrite showOutput', () => { - let builder = new ConfiguationBuilder().buildTask('tsc'); + let builder = new ConfiguationBuilder(); builder. task('tsc', 'tsc'). + group(Tasks.TaskGroup.Build). showOutput(Platform.isWindows ? Tasks.ShowOutput.Always : Tasks.ShowOutput.Never). suppressTaskName(true); let external: ExternalTaskRunnerConfiguration = { @@ -726,9 +765,10 @@ suite('Tasks Configuration parsing tests', () => { }); test('tasks: overwrite echo Command', () => { - let builder = new ConfiguationBuilder().buildTask('tsc'); + let builder = new ConfiguationBuilder(); builder. task('tsc', 'tsc'). + group(Tasks.TaskGroup.Build). suppressTaskName(true). command(). echo(Platform.isWindows ? false : true); @@ -787,8 +827,8 @@ suite('Tasks Configuration parsing tests', () => { } ] }; - let builder = new ConfiguationBuilder().buildTask('taskName'); - builder.task('taskName', 'tsc'); + let builder = new ConfiguationBuilder(); + builder.task('taskName', 'tsc').group(Tasks.TaskGroup.Build); testConfiguration(external, builder); }); @@ -802,8 +842,8 @@ suite('Tasks Configuration parsing tests', () => { } ] }; - let builder = new ConfiguationBuilder().buildTask('build'); - builder.task('build', 'tsc'); + let builder = new ConfiguationBuilder(); + builder.task('build', 'tsc').group(Tasks.TaskGroup.Build); testConfiguration(external, builder); }); @@ -818,8 +858,8 @@ suite('Tasks Configuration parsing tests', () => { } ] }; - let builder = new ConfiguationBuilder().testTask('taskName'); - builder.task('taskName', 'tsc'); + let builder = new ConfiguationBuilder(); + builder.task('taskName', 'tsc').group(Tasks.TaskGroup.Test); testConfiguration(external, builder); }); @@ -833,8 +873,8 @@ suite('Tasks Configuration parsing tests', () => { } ] }; - let builder = new ConfiguationBuilder().testTask('test'); - builder.task('test', 'tsc'); + let builder = new ConfiguationBuilder(); + builder.task('test', 'tsc').group(Tasks.TaskGroup.Test); testConfiguration(external, builder); }); @@ -852,8 +892,9 @@ suite('Tasks Configuration parsing tests', () => { } ] }; - let builder = new ConfiguationBuilder().testTask('test'); + let builder = new ConfiguationBuilder(); builder.task('test', 'tsc'). + group(Tasks.TaskGroup.Test). showOutput(Tasks.ShowOutput.Never). args(['--p']). isBackground(true). @@ -876,8 +917,9 @@ suite('Tasks Configuration parsing tests', () => { } ] }; - let builder = new ConfiguationBuilder().testTask('test'); + let builder = new ConfiguationBuilder(); builder.task('test', 'tsc'). + group(Tasks.TaskGroup.Test). showOutput(Tasks.ShowOutput.Never). command(). echo(true);