From 56e8b2350b7970fac470ee146509f430f7e5ce3c Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Thu, 21 Mar 2019 17:03:25 +0000 Subject: [PATCH] fix #4651: apply default configuration overrides properly Signed-off-by: Anton Kosyakov --- .../preferences/preference-contribution.ts | 26 ++++++++-- .../src/browser/preference-service.spec.ts | 51 +++++++++++++++++-- 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/packages/core/src/browser/preferences/preference-contribution.ts b/packages/core/src/browser/preferences/preference-contribution.ts index 487b3750f7bf3..bb2d587b3193f 100644 --- a/packages/core/src/browser/preferences/preference-contribution.ts +++ b/packages/core/src/browser/preferences/preference-contribution.ts @@ -134,14 +134,30 @@ export class PreferenceSchemaProvider extends PreferenceProvider { if (schemaProps.overridable) { this.overridePatternProperties.properties[preferenceName] = schemaProps; } - const newValue = schemaProps.default = this.getDefaultValue(schemaProps); this.combinedSchema.properties[preferenceName] = schemaProps; - this.preferences[preferenceName] = newValue; - changes.push({ preferenceName, newValue, scope, domain }); + + const value = schemaProps.default = this.getDefaultValue(schemaProps); + if (this.testOverrideValue(preferenceName, value)) { + for (const overridenPreferenceName in value) { + const overrideValue = value[overridenPreferenceName]; + const overridePreferenceName = `${preferenceName}.${overridenPreferenceName}`; + changes.push(this.doSetPreferenceValue(overridePreferenceName, overrideValue, { scope, domain })); + } + } else { + changes.push(this.doSetPreferenceValue(preferenceName, value, { scope, domain })); + } } } return changes; } + protected doSetPreferenceValue(preferenceName: string, newValue: any, { scope, domain }: { + scope: PreferenceScope, + domain: string[] + }): PreferenceProviderDataChange { + const oldValue = this.preferences[preferenceName]; + this.preferences[preferenceName] = newValue; + return { preferenceName, oldValue, newValue, scope, domain }; + } protected getDefaultValue(property: PreferenceItem): any { if (property.default) { @@ -243,7 +259,7 @@ export class PreferenceSchemaProvider extends PreferenceProvider { return { preferenceName, overrideIdentifier }; } - testOverrideValue(name: string, value: any): boolean { - return typeof value === 'object' && OVERRIDE_PROPERTY_PATTERN.test(name); + testOverrideValue(name: string, value: any): value is PreferenceSchemaProperties { + return PreferenceSchemaProperties.is(value) && OVERRIDE_PROPERTY_PATTERN.test(name); } } diff --git a/packages/preferences/src/browser/preference-service.spec.ts b/packages/preferences/src/browser/preference-service.spec.ts index eb6dde85c0a11..c85cfbfc49983 100644 --- a/packages/preferences/src/browser/preference-service.spec.ts +++ b/packages/preferences/src/browser/preference-service.spec.ts @@ -29,7 +29,7 @@ import * as temp from 'temp'; import { Emitter } from '@theia/core/lib/common'; import { PreferenceService, PreferenceScope, PreferenceProviderDataChanges, - PreferenceSchemaProvider, PreferenceProviderProvider, PreferenceServiceImpl, bindPreferenceSchemaProvider, PreferenceChange + PreferenceSchemaProvider, PreferenceProviderProvider, PreferenceServiceImpl, bindPreferenceSchemaProvider, PreferenceChange, PreferenceSchema } from '@theia/core/lib/browser/preferences'; import { FileSystem, FileShouldOverwrite, FileStat } from '@theia/filesystem/lib/common/'; import { FileSystemWatcher } from '@theia/filesystem/lib/browser/filesystem-watcher'; @@ -623,14 +623,59 @@ describe('Preference Service', () => { }))); }); - function prepareServices() { + it('defaultOverrides [go].editor.formatOnSave', () => { + const { preferences, schema } = prepareServices({ + schema: { + properties: { + 'editor.insertSpaces': { + type: 'boolean', + default: true, + overridable: true + }, + 'editor.formatOnSave': { + type: 'boolean', + default: false, + overridable: true + } + } + } + }); + + assert.equal(true, preferences.get('editor.insertSpaces')); + assert.equal(undefined, preferences.get('[go].editor.insertSpaces')); + assert.equal(false, preferences.get('editor.formatOnSave')); + assert.equal(undefined, preferences.get('[go].editor.formatOnSave')); + + schema.registerOverrideIdentifier('go'); + schema.setSchema({ + id: 'defaultOverrides', + title: 'Default Configuration Overrides', + properties: { + '[go]': { + type: 'object', + default: { + 'editor.insertSpaces': false, + 'editor.formatOnSave': true + }, + description: 'Configure editor settings to be overridden for go language.' + } + } + }); + + assert.equal(true, preferences.get('editor.insertSpaces')); + assert.equal(false, preferences.get('[go].editor.insertSpaces')); + assert.equal(false, preferences.get('editor.formatOnSave')); + assert.equal(true, preferences.get('[go].editor.formatOnSave')); + }); + + function prepareServices(options?: { schema: PreferenceSchema }) { const container = new Container(); bindPreferenceSchemaProvider(container.bind.bind(container)); container.bind(PreferenceProviderProvider).toFactory(() => () => new MockPreferenceProvider()); container.bind(PreferenceServiceImpl).toSelf().inSingletonScope(); const schema = container.get(PreferenceSchemaProvider); - schema.setSchema({ + schema.setSchema(options && options.schema || { properties: { 'editor.tabSize': { type: 'number',