From 802be774a72f0e53a2c96c208a93b7a68df9fe31 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 23 Jan 2018 10:50:09 +0100 Subject: [PATCH] #36967 - Support reading workspace launches in mulit root workspace --- .../common/configurationModels.ts | 43 ++++++++++---- .../configuration/node/configuration.ts | 41 +++++++------ .../node/configurationService.ts | 2 +- .../test/node/configurationService.test.ts | 59 ++++++++++++++++--- 4 files changed, 105 insertions(+), 40 deletions(-) diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 2d9b9a6bd33..27be593edfe 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -14,7 +14,7 @@ import { Workspace } from 'vs/platform/workspace/common/workspace'; import { StrictResourceMap } from 'vs/base/common/map'; import URI from 'vs/base/common/uri'; -export class WorkspaceSettingsModel extends ConfigurationModel { +export class SettingsModel extends ConfigurationModel { private _unsupportedKeys: string[]; @@ -32,30 +32,49 @@ export class WorkspaceSettingsModel extends ConfigurationModel { export class WorkspaceConfigurationModelParser extends ConfigurationModelParser { private _folders: IStoredWorkspaceFolder[] = []; - private _workspaceSettingsModelParser: FolderSettingsModelParser; + private _settingsModelParser: FolderSettingsModelParser; + private _launchModel: ConfigurationModel; constructor(name: string) { super(name); - this._workspaceSettingsModelParser = new FolderSettingsModelParser(name); + this._settingsModelParser = new FolderSettingsModelParser(name); + this._launchModel = new ConfigurationModel(); } get folders(): IStoredWorkspaceFolder[] { return this._folders; } - get workspaceSettingsModel(): WorkspaceSettingsModel { - return this._workspaceSettingsModelParser.folderSettingsModel; + get settingsModel(): SettingsModel { + return this._settingsModelParser.settingsModel; + } + + get launchModel(): ConfigurationModel { + return this._launchModel; } reprocessWorkspaceSettings(): void { - this._workspaceSettingsModelParser.reprocess(); + this._settingsModelParser.reprocess(); } protected parseRaw(raw: any): IConfigurationModel { this._folders = (raw['folders'] || []) as IStoredWorkspaceFolder[]; - this._workspaceSettingsModelParser.parse(raw['settings']); + this._settingsModelParser.parse(raw['settings']); + this._launchModel = this.createConfigurationModelFrom(raw, 'launch'); return super.parseRaw(raw); } + + private createConfigurationModelFrom(raw: any, key: string): ConfigurationModel { + const data = raw[key]; + if (data) { + const contents = toValuesTree(data, message => console.error(`Conflict in settings file ${this._name}: ${message}`)); + const scopedContents = Object.create(null); + scopedContents[key] = contents; + const keys = Object.keys(data).map(k => `${key}.${k}`); + return new ConfigurationModel(scopedContents, keys, []); + } + return new ConfigurationModel(); + } } export class StandaloneConfigurationModelParser extends ConfigurationModelParser { @@ -77,7 +96,7 @@ export class StandaloneConfigurationModelParser extends ConfigurationModelParser export class FolderSettingsModelParser extends ConfigurationModelParser { private _raw: any; - private _workspaceSettingsModel: WorkspaceSettingsModel; + private _settingsModel: SettingsModel; constructor(name: string, private configurationScope?: ConfigurationScope) { super(name); @@ -89,11 +108,11 @@ export class FolderSettingsModelParser extends ConfigurationModelParser { } get configurationModel(): ConfigurationModel { - return this._workspaceSettingsModel || new WorkspaceSettingsModel({}, [], [], []); + return this._settingsModel || new SettingsModel({}, [], [], []); } - get folderSettingsModel(): WorkspaceSettingsModel { - return this.configurationModel; + get settingsModel(): SettingsModel { + return this.configurationModel; } reprocess(): void { @@ -114,7 +133,7 @@ export class FolderSettingsModelParser extends ConfigurationModelParser { } } const configurationModel = this.parseRaw(rawWorkspaceSettings); - this._workspaceSettingsModel = new WorkspaceSettingsModel(configurationModel.contents, configurationModel.keys, configurationModel.overrides, unsupportedKeys); + this._settingsModel = new SettingsModel(configurationModel.contents, configurationModel.keys, configurationModel.overrides, unsupportedKeys); } private getScope(key: string, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema }): ConfigurationScope { diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 983bf2b902f..897e2c0faac 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -16,7 +16,7 @@ import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files import { isLinux } from 'vs/base/common/platform'; import { ConfigWatcher } from 'vs/base/node/config'; import { ConfigurationModel, ConfigurationModelParser } from 'vs/platform/configuration/common/configurationModels'; -import { WorkspaceConfigurationModelParser, FolderSettingsModelParser, StandaloneConfigurationModelParser, WorkspaceSettingsModel } from 'vs/workbench/services/configuration/common/configurationModels'; +import { WorkspaceConfigurationModelParser, FolderSettingsModelParser, StandaloneConfigurationModelParser } from 'vs/workbench/services/configuration/common/configurationModels'; import { WORKSPACE_STANDALONE_CONFIGURATIONS, FOLDER_SETTINGS_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration'; import { IStoredWorkspace, IStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; import * as extfs from 'vs/base/node/extfs'; @@ -82,6 +82,9 @@ export class WorkspaceConfiguration extends Disposable { private _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; + private _workspaceConfigurationModelParser: WorkspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(this._workspaceConfigPath ? this._workspaceConfigPath.fsPath : ''); + private _cache: ConfigurationModel = new ConfigurationModel(); + load(workspaceConfigPath: URI): TPromise { if (this._workspaceConfigPath && this._workspaceConfigPath.fsPath === workspaceConfigPath.fsPath) { return this.reload(); @@ -98,20 +101,17 @@ export class WorkspaceConfiguration extends Disposable { onError: error => errors.onUnexpectedError(error), defaultConfig, parse: (content: string, parseErrors: any[]) => { - const workspaceConfigurationModel = new WorkspaceConfigurationModelParser(this._workspaceConfigPath.fsPath); - workspaceConfigurationModel.parse(content); - parseErrors = [...workspaceConfigurationModel.errors]; - return workspaceConfigurationModel; + this._workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(this._workspaceConfigPath.fsPath); + this._workspaceConfigurationModelParser.parse(content); + parseErrors = [...this._workspaceConfigurationModelParser.errors]; + this.consolidate(); + return this._workspaceConfigurationModelParser; }, initCallback: () => c(null) }); this.listenToWatcher(); }); } - private get workspaceConfigurationModelParser(): WorkspaceConfigurationModelParser { - return this._workspaceConfigurationWatcher ? this._workspaceConfigurationWatcher.getConfig() : new WorkspaceConfigurationModelParser(this._workspaceConfigPath ? this._workspaceConfigPath.fsPath : ''); - } - reload(): TPromise { this.stopListeningToWatcher(); return new TPromise(c => this._workspaceConfigurationWatcher.reload(() => { @@ -121,7 +121,7 @@ export class WorkspaceConfiguration extends Disposable { } getFolders(): IStoredWorkspaceFolder[] { - return this.workspaceConfigurationModelParser.folders; + return this._workspaceConfigurationModelParser.folders; } setFolders(folders: IStoredWorkspaceFolder[], jsonEditingService: JSONEditingService): TPromise { @@ -130,15 +130,16 @@ export class WorkspaceConfiguration extends Disposable { } getConfiguration(): ConfigurationModel { - return this.workspaceConfigurationModelParser.workspaceSettingsModel; + return this._cache; } - getWorkspaceSettings(): WorkspaceSettingsModel { - return this.workspaceConfigurationModelParser.workspaceSettingsModel; + getUnsupportedKeys(): string[] { + return this._workspaceConfigurationModelParser.settingsModel.unsupportedKeys; } reprocessWorkspaceSettings(): ConfigurationModel { - this.workspaceConfigurationModelParser.reprocessWorkspaceSettings(); + this._workspaceConfigurationModelParser.reprocessWorkspaceSettings(); + this.consolidate(); return this.getConfiguration(); } @@ -151,6 +152,10 @@ export class WorkspaceConfiguration extends Disposable { this._workspaceConfigurationWatcherDisposables = dispose(this._workspaceConfigurationWatcherDisposables); } + private consolidate(): void { + this._cache = this._workspaceConfigurationModelParser.settingsModel.merge(this._workspaceConfigurationModelParser.launchModel); + } + dispose(): void { dispose(this._workspaceConfigurationWatcherDisposables); super.dispose(); @@ -190,20 +195,20 @@ export class FolderConfiguration extends Disposable { } reprocess(): ConfigurationModel { - const oldContents = this._folderSettingsModelParser.folderSettingsModel.contents; + const oldContents = this._folderSettingsModelParser.settingsModel.contents; this._folderSettingsModelParser.reprocess(); - if (!equals(oldContents, this._folderSettingsModelParser.folderSettingsModel.contents)) { + if (!equals(oldContents, this._folderSettingsModelParser.settingsModel.contents)) { this.consolidate(); } return this._cache; } getUnsupportedKeys(): string[] { - return this._folderSettingsModelParser.folderSettingsModel.unsupportedKeys; + return this._folderSettingsModelParser.settingsModel.unsupportedKeys; } private consolidate(): void { - this._cache = this._folderSettingsModelParser.folderSettingsModel.merge(...this._standAloneConfigurations); + this._cache = this._folderSettingsModelParser.settingsModel.merge(...this._standAloneConfigurations); } private loadWorkspaceConfigFiles(): TPromise<{ [relativeWorkspacePath: string]: ConfigurationModelParser }> { diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index d5c3af13b8b..4e3b25efb56 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -279,7 +279,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } getUnsupportedWorkspaceKeys(): string[] { - const unsupportedWorkspaceKeys = [...this.workspaceConfiguration.getWorkspaceSettings().unsupportedKeys]; + const unsupportedWorkspaceKeys = [...this.workspaceConfiguration.getUnsupportedKeys()]; for (const folder of this.workspace.folders) { unsupportedWorkspaceKeys.push(...this.cachedFolderConfigs.get(folder.uri).getUnsupportedKeys()); } diff --git a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts index d41ac767a69..1989f5e6baf 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts @@ -1038,6 +1038,56 @@ suite('WorkspaceConfigurationService - Multiroot', () => { }); }); + test('get launch configuration', () => { + const expectedLaunchConfiguration = { + 'version': '0.1.0', + 'configurations': [ + { + 'type': 'node', + 'request': 'launch', + 'name': 'Gulp Build', + 'program': '${workspaceFolder}/node_modules/gulp/bin/gulp.js', + 'stopOnEntry': true, + 'args': [ + 'watch-extension:json-client' + ], + 'cwd': '${workspaceFolder}' + } + ] + }; + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'launch', value: expectedLaunchConfiguration }, true) + .then(() => testObject.reloadConfiguration()) + .then(() => { + const actual = testObject.getValue('launch'); + assert.deepEqual(actual, expectedLaunchConfiguration); + }); + }); + + test('inspect launch configuration', () => { + const expectedLaunchConfiguration = { + 'version': '0.1.0', + 'configurations': [ + { + 'type': 'node', + 'request': 'launch', + 'name': 'Gulp Build', + 'program': '${workspaceFolder}/node_modules/gulp/bin/gulp.js', + 'stopOnEntry': true, + 'args': [ + 'watch-extension:json-client' + ], + 'cwd': '${workspaceFolder}' + } + ] + }; + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'launch', value: expectedLaunchConfiguration }, true) + .then(() => testObject.reloadConfiguration()) + .then(() => { + const actual = testObject.inspect('launch').workspace; + assert.deepEqual(actual, expectedLaunchConfiguration); + }); + }); + test('update user configuration', () => { return testObject.updateValue('configurationService.workspace.testSetting', 'userValue', ConfigurationTarget.USER) .then(() => assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'userValue')); @@ -1102,13 +1152,4 @@ suite('WorkspaceConfigurationService - Multiroot', () => { assert.equal(actual.workspace, void 0); }); }); - - test('launch configurations are not read from workspace', () => { - return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'launch', value: { 'version': '1.0' } }, true) - .then(() => testObject.reloadConfiguration()) - .then(() => { - const actual = testObject.inspect('launch.version'); - assert.equal(actual.workspace, void 0); - }); - }); }); -- GitLab