From b1b9e42e2c5d6a22e6ec152ce07df0c09c0edd74 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 17 Oct 2019 16:52:45 +0200 Subject: [PATCH] Add tasks config in workspace file (#81417) Add tasks config in workspace file Add tests and allow editing api for tasks --- .../api/common/configurationExtensionPoint.ts | 8 ++- .../tasks/browser/task.contribution.ts | 4 +- .../configuration/browser/configuration.ts | 4 +- .../common/configurationEditingService.ts | 5 -- .../common/configurationModels.ts | 7 ++ .../configurationService.test.ts | 65 +++++++++++++++---- 6 files changed, 70 insertions(+), 23 deletions(-) diff --git a/src/vs/workbench/api/common/configurationExtensionPoint.ts b/src/vs/workbench/api/common/configurationExtensionPoint.ts index 871ae0f28ff..65e5d6cf070 100644 --- a/src/vs/workbench/api/common/configurationExtensionPoint.ts +++ b/src/vs/workbench/api/common/configurationExtensionPoint.ts @@ -10,7 +10,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { ExtensionsRegistry, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import { IConfigurationNode, IConfigurationRegistry, Extensions, editorConfigurationSchemaId, IDefaultConfigurationExtension, validateProperty, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; -import { workspaceSettingsSchemaId, launchSchemaId } from 'vs/workbench/services/configuration/common/configuration'; +import { workspaceSettingsSchemaId, launchSchemaId, tasksSchemaId } from 'vs/workbench/services/configuration/common/configuration'; import { isObject } from 'vs/base/common/types'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; @@ -296,6 +296,12 @@ jsonRegistry.registerSchema('vscode://schemas/workspaceConfig', { description: nls.localize('workspaceConfig.launch.description', "Workspace launch configurations"), $ref: launchSchemaId }, + 'tasks': { + type: 'object', + default: { version: '2.0.0', tasks: [] }, + description: nls.localize('workspaceConfig.tasks.description', "Workspace task configurations"), + $ref: tasksSchemaId + }, 'extensions': { type: 'object', default: {}, diff --git a/src/vs/workbench/contrib/tasks/browser/task.contribution.ts b/src/vs/workbench/contrib/tasks/browser/task.contribution.ts index 96136e89d0b..f12650f7d19 100644 --- a/src/vs/workbench/contrib/tasks/browser/task.contribution.ts +++ b/src/vs/workbench/contrib/tasks/browser/task.contribution.ts @@ -39,7 +39,7 @@ import schemaVersion1 from '../common/jsonSchema_v1'; import schemaVersion2, { updateProblemMatchers } from '../common/jsonSchema_v2'; import { AbstractTaskService, ConfigureTaskAction } from 'vs/workbench/contrib/tasks/browser/abstractTaskService'; import { tasksSchemaId } from 'vs/workbench/services/configuration/common/configuration'; -import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; +import { Extensions as ConfigurationExtensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; let tasksCategory = nls.localize('tasksCategory', "Tasks"); @@ -307,7 +307,7 @@ ProblemMatcherRegistry.onMatcherChanged(() => { jsonRegistry.notifySchemaChanged(tasksSchemaId); }); -const configurationRegistry = Registry.as(Extensions.Configuration); +const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); configurationRegistry.registerConfiguration({ id: 'task', order: 100, diff --git a/src/vs/workbench/services/configuration/browser/configuration.ts b/src/vs/workbench/services/configuration/browser/configuration.ts index 589d4fa7fc5..d3af9e42aee 100644 --- a/src/vs/workbench/services/configuration/browser/configuration.ts +++ b/src/vs/workbench/services/configuration/browser/configuration.ts @@ -465,7 +465,7 @@ class FileServiceBasedWorkspaceConfiguration extends Disposable implements IWork } private consolidate(): void { - this.workspaceSettings = this.workspaceConfigurationModelParser.settingsModel.merge(this.workspaceConfigurationModelParser.launchModel); + this.workspaceSettings = this.workspaceConfigurationModelParser.settingsModel.merge(this.workspaceConfigurationModelParser.launchModel, this.workspaceConfigurationModelParser.tasksModel); } private watchWorkspaceConfigurationFile(): IDisposable { @@ -509,7 +509,7 @@ class CachedWorkspaceConfiguration extends Disposable implements IWorkspaceConfi const contents = await this.configurationCache.read(key); this.workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(key.key); this.workspaceConfigurationModelParser.parseContent(contents); - this.workspaceSettings = this.workspaceConfigurationModelParser.settingsModel.merge(this.workspaceConfigurationModelParser.launchModel); + this.workspaceSettings = this.workspaceConfigurationModelParser.settingsModel.merge(this.workspaceConfigurationModelParser.launchModel, this.workspaceConfigurationModelParser.tasksModel); } catch (e) { } } diff --git a/src/vs/workbench/services/configuration/common/configurationEditingService.ts b/src/vs/workbench/services/configuration/common/configurationEditingService.ts index d0458c430a5..854b8c2402f 100644 --- a/src/vs/workbench/services/configuration/common/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/common/configurationEditingService.ts @@ -428,11 +428,6 @@ export class ConfigurationEditingService { if (target === EditableConfigurationTarget.USER_LOCAL || target === EditableConfigurationTarget.USER_REMOTE) { return this.reject(ConfigurationEditingErrorCode.ERROR_INVALID_USER_TARGET, target, operation); } - - // Workspace tasks are not supported - if (operation.workspaceStandAloneConfigurationKey === TASKS_CONFIGURATION_KEY && this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE && operation.target === EditableConfigurationTarget.WORKSPACE) { - return this.reject(ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_TARGET, target, operation); - } } // Target cannot be workspace or folder if no workspace opened diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 7a30ad06477..9d2f6ad88df 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -17,11 +17,13 @@ export class WorkspaceConfigurationModelParser extends ConfigurationModelParser private _folders: IStoredWorkspaceFolder[] = []; private _settingsModelParser: ConfigurationModelParser; private _launchModel: ConfigurationModel; + private _tasksModel: ConfigurationModel; constructor(name: string) { super(name); this._settingsModelParser = new ConfigurationModelParser(name, WORKSPACE_SCOPES); this._launchModel = new ConfigurationModel(); + this._tasksModel = new ConfigurationModel(); } get folders(): IStoredWorkspaceFolder[] { @@ -36,6 +38,10 @@ export class WorkspaceConfigurationModelParser extends ConfigurationModelParser return this._launchModel; } + get tasksModel(): ConfigurationModel { + return this._tasksModel; + } + reprocessWorkspaceSettings(): void { this._settingsModelParser.parse(); } @@ -44,6 +50,7 @@ export class WorkspaceConfigurationModelParser extends ConfigurationModelParser this._folders = (raw['folders'] || []) as IStoredWorkspaceFolder[]; this._settingsModelParser.parseRaw(raw['settings']); this._launchModel = this.createConfigurationModelFrom(raw, 'launch'); + this._tasksModel = this.createConfigurationModelFrom(raw, 'tasks'); return super.doParseRaw(raw); } diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 0cb78f87376..78e32e11d0e 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -1406,6 +1406,53 @@ suite('WorkspaceConfigurationService-Multiroot', () => { }); }); + + test('get tasks configuration', () => { + const expectedTasksConfiguration = { + 'version': '2.0.0', + 'tasks': [ + { + 'label': 'Run Dev', + 'type': 'shell', + 'command': './scripts/code.sh', + 'windows': { + 'command': '.\\scripts\\code.bat' + }, + 'problemMatcher': [] + } + ] + }; + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ key: 'tasks', value: expectedTasksConfiguration }], true) + .then(() => testObject.reloadConfiguration()) + .then(() => { + const actual = testObject.getValue('tasks'); + assert.deepEqual(actual, expectedTasksConfiguration); + }); + }); + + test('inspect tasks configuration', () => { + const expectedTasksConfiguration = { + 'version': '2.0.0', + 'tasks': [ + { + 'label': 'Run Dev', + 'type': 'shell', + 'command': './scripts/code.sh', + 'windows': { + 'command': '.\\scripts\\code.bat' + }, + 'problemMatcher': [] + } + ] + }; + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ key: 'tasks', value: expectedTasksConfiguration }], true) + .then(() => testObject.reloadConfiguration()) + .then(() => { + const actual = testObject.inspect('tasks').workspace; + assert.deepEqual(actual, expectedTasksConfiguration); + }); + }); + test('update user configuration', () => { return testObject.updateValue('configurationService.workspace.testSetting', 'userValue', ConfigurationTarget.USER) .then(() => assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'userValue')); @@ -1483,25 +1530,17 @@ suite('WorkspaceConfigurationService-Multiroot', () => { .then(() => assert.deepEqual(testObject.getValue('tasks', { resource: workspace.folders[0].uri }), { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] })); }); - test('update tasks configuration in a workspace is not supported', () => { - const workspace = workspaceContextService.getWorkspace(); - return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE, true) - .then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_TARGET)); - }); - test('update launch configuration in a workspace', () => { const workspace = workspaceContextService.getWorkspace(); return testObject.updateValue('launch', { 'version': '1.0.0', configurations: [{ 'name': 'myLaunch' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE, true) .then(() => assert.deepEqual(testObject.getValue('launch'), { 'version': '1.0.0', configurations: [{ 'name': 'myLaunch' }] })); }); - test('task configurations are not read from workspace', () => { - return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, [{ key: 'tasks', value: { 'version': '1.0' } }], true) - .then(() => testObject.reloadConfiguration()) - .then(() => { - const actual = testObject.inspect('tasks.version'); - assert.equal(actual.workspace, undefined); - }); + test('update tasks configuration in a workspace', () => { + const workspace = workspaceContextService.getWorkspace(); + const tasks = { 'version': '2.0.0', tasks: [{ 'label': 'myTask' }] }; + return testObject.updateValue('tasks', tasks, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE, true) + .then(() => assert.deepEqual(testObject.getValue('tasks'), tasks)); }); test('configuration of newly added folder is available on configuration change event', async () => {