diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index c3f6beac34f81857c93e8ba751569255a3440abf..ae155ae126f756ec51b3cc9450ab3b47f08a4108 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -21,11 +21,12 @@ import { Workspace } from 'vs/platform/workspace/common/workspace'; export class ConfigurationModel implements IConfigurationModel { private isFrozen: boolean = false; + private readonly overrideConfigurations = new Map(); constructor( - private _contents: any = {}, - private _keys: string[] = [], - private _overrides: IOverrides[] = [] + private readonly _contents: any = {}, + private readonly _keys: string[] = [], + private readonly _overrides: IOverrides[] = [] ) { } @@ -66,34 +67,12 @@ export class ConfigurationModel implements IConfigurationModel { } override(identifier: string): ConfigurationModel { - const overrideContents = this.getContentsForOverrideIdentifer(identifier); - - if (!overrideContents || typeof overrideContents !== 'object' || !Object.keys(overrideContents).length) { - // If there are no valid overrides, return self - return this; + let overrideConfigurationModel = this.overrideConfigurations.get(identifier); + if (!overrideConfigurationModel) { + overrideConfigurationModel = this.createOverrideConfigurationModel(identifier); + this.overrideConfigurations.set(identifier, overrideConfigurationModel); } - - let contents: any = {}; - for (const key of arrays.distinct([...Object.keys(this.contents), ...Object.keys(overrideContents)])) { - - let contentsForKey = this.contents[key]; - let overrideContentsForKey = overrideContents[key]; - - // If there are override contents for the key, clone and merge otherwise use base contents - if (overrideContentsForKey) { - // Clone and merge only if base contents and override contents are of type object otherwise just override - if (typeof contentsForKey === 'object' && typeof overrideContentsForKey === 'object') { - contentsForKey = objects.deepClone(contentsForKey); - this.mergeContents(contentsForKey, overrideContentsForKey); - } else { - contentsForKey = overrideContentsForKey; - } - } - - contents[key] = contentsForKey; - } - - return new ConfigurationModel(contents, this.keys, this.overrides); + return overrideConfigurationModel; } merge(...others: ConfigurationModel[]): ConfigurationModel { @@ -126,6 +105,37 @@ export class ConfigurationModel implements IConfigurationModel { return this; } + private createOverrideConfigurationModel(identifier: string): ConfigurationModel { + const overrideContents = this.getContentsForOverrideIdentifer(identifier); + + if (!overrideContents || typeof overrideContents !== 'object' || !Object.keys(overrideContents).length) { + // If there are no valid overrides, return self + return this; + } + + let contents: any = {}; + for (const key of arrays.distinct([...Object.keys(this.contents), ...Object.keys(overrideContents)])) { + + let contentsForKey = this.contents[key]; + let overrideContentsForKey = overrideContents[key]; + + // If there are override contents for the key, clone and merge otherwise use base contents + if (overrideContentsForKey) { + // Clone and merge only if base contents and override contents are of type object otherwise just override + if (typeof contentsForKey === 'object' && typeof overrideContentsForKey === 'object') { + contentsForKey = objects.deepClone(contentsForKey); + this.mergeContents(contentsForKey, overrideContentsForKey); + } else { + contentsForKey = overrideContentsForKey; + } + } + + contents[key] = contentsForKey; + } + + return new ConfigurationModel(contents, this.keys, this.overrides); + } + private mergeContents(source: any, target: any): void { for (const key of Object.keys(target)) { if (key in source) { diff --git a/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts index f7019535b6d1ac1c94546bff88a689adfc922494..287d9dbb65ac4ac0e3083a6941d7626b89a25c49 100644 --- a/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/browser/configurationService.test.ts @@ -668,6 +668,12 @@ suite('WorkspaceConfigurationService - Folder', () => { }, } }); + + configurationRegistry.registerDefaultConfigurations([{ + '[jsonc]': { + 'configurationService.folder.languageSetting': 'languageValue' + } + }]); }); setup(async () => { @@ -1052,6 +1058,13 @@ suite('WorkspaceConfigurationService - Folder', () => { .then(() => assert.ok(target.called)); }); + test('resource language configuration', async () => { + assert.strictEqual(testObject.getValue('configurationService.folder.languageSetting', { resource: workspaceService.getWorkspace().folders[0].uri, overrideIdentifier: 'jsonc' }), 'languageValue'); + await testObject.updateValue('configurationService.folder.languageSetting', 'languageValueUpdated', { resource: workspaceService.getWorkspace().folders[0].uri, overrideIdentifier: 'jsonc' }, ConfigurationTarget.WORKSPACE_FOLDER); + assert.strictEqual(testObject.getValue('configurationService.folder.languageSetting', { resource: workspaceService.getWorkspace().folders[0].uri, overrideIdentifier: 'jsonc' }), 'languageValueUpdated'); + }); + + test('remove setting from all targets', async () => { const key = 'configurationService.folder.testSetting'; await testObject.updateValue(key, 'workspaceValue', ConfigurationTarget.WORKSPACE);