diff --git a/packages/core/src/browser/preferences/preference-contribution.ts b/packages/core/src/browser/preferences/preference-contribution.ts index d3a329cabac9b..a86e3e9236f0e 100644 --- a/packages/core/src/browser/preferences/preference-contribution.ts +++ b/packages/core/src/browser/preferences/preference-contribution.ts @@ -34,6 +34,8 @@ import { JSONValue } from '@phosphor/coreutils'; export const PreferenceContribution = Symbol('PreferenceContribution'); +export const DefaultOverridesPreferenceSchemaId = 'defaultOverrides'; + /** * A {@link PreferenceContribution} allows adding additional custom preferences. * For this, the {@link PreferenceContribution} has to provide a valid JSON Schema specifying which preferences @@ -202,34 +204,44 @@ export class PreferenceSchemaProvider extends PreferenceProvider { const defaultScope = PreferenceSchema.getDefaultScope(schema); const overridable = schema.overridable || false; for (const [preferenceName, rawSchemaProps] of Object.entries(schema.properties)) { - if (this.combinedSchema.properties[preferenceName]) { + if (this.combinedSchema.properties[preferenceName] && DefaultOverridesPreferenceSchemaId !== schema.id) { console.error('Preference name collision detected in the schema for property: ' + preferenceName); - } else if (!rawSchemaProps.hasOwnProperty('included') || rawSchemaProps.included) { - const schemaProps = PreferenceDataProperty.fromPreferenceSchemaProperty(rawSchemaProps, defaultScope); - if (typeof schemaProps.overridable !== 'boolean' && overridable) { - schemaProps.overridable = true; - } - if (schemaProps.overridable) { - this.overridePatternProperties.properties[preferenceName] = schemaProps; + } else { + let schemaProps; + if (this.combinedSchema.properties[preferenceName] && DefaultOverridesPreferenceSchemaId === schema.id) { + // update existing default value in schema + schemaProps = PreferenceDataProperty.fromPreferenceSchemaProperty(rawSchemaProps, defaultScope); + this.updateSchemaPropsDefault(preferenceName, schemaProps); + } else if (!rawSchemaProps.hasOwnProperty('included') || rawSchemaProps.included) { + // add overrides for languages + schemaProps = PreferenceDataProperty.fromPreferenceSchemaProperty(rawSchemaProps, defaultScope); + if (typeof schemaProps.overridable !== 'boolean' && overridable) { + schemaProps.overridable = true; + } + if (schemaProps.overridable) { + this.overridePatternProperties.properties[preferenceName] = schemaProps; + } + this.updateSchemaProps(preferenceName, schemaProps); } - this.updateSchemaProps(preferenceName, schemaProps); - - const schemaDefault = this.getDefaultValue(schemaProps); - const configuredDefault = this.getConfiguredDefault(preferenceName); - if (this.preferenceOverrideService.testOverrideValue(preferenceName, schemaDefault)) { - schemaProps.defaultValue = PreferenceSchemaProperties.is(configuredDefault) - ? PreferenceProvider.merge(schemaDefault, configuredDefault) - : schemaDefault; - if (schemaProps.defaultValue && PreferenceSchemaProperties.is(schemaProps.defaultValue)) { - for (const overriddenPreferenceName in schemaProps.defaultValue) { - const overrideValue = schemaDefault[overriddenPreferenceName]; - const overridePreferenceName = `${preferenceName}.${overriddenPreferenceName}`; - changes.push(this.doSetPreferenceValue(overridePreferenceName, overrideValue, { scope, domain })); + + if (schemaProps !== undefined) { + const schemaDefault = this.getDefaultValue(schemaProps); + const configuredDefault = this.getConfiguredDefault(preferenceName); + if (this.preferenceOverrideService.testOverrideValue(preferenceName, schemaDefault)) { + schemaProps.defaultValue = PreferenceSchemaProperties.is(configuredDefault) + ? PreferenceProvider.merge(schemaDefault, configuredDefault) + : schemaDefault; + if (schemaProps.defaultValue && PreferenceSchemaProperties.is(schemaProps.defaultValue)) { + for (const overriddenPreferenceName in schemaProps.defaultValue) { + const overrideValue = schemaDefault[overriddenPreferenceName]; + const overridePreferenceName = `${preferenceName}.${overriddenPreferenceName}`; + changes.push(this.doSetPreferenceValue(overridePreferenceName, overrideValue, { scope, domain })); + } } + } else { + schemaProps.defaultValue = configuredDefault === undefined ? schemaDefault : configuredDefault; + changes.push(this.doSetPreferenceValue(preferenceName, schemaProps.defaultValue, { scope, domain })); } - } else { - schemaProps.defaultValue = configuredDefault === undefined ? schemaDefault : configuredDefault; - changes.push(this.doSetPreferenceValue(preferenceName, schemaProps.defaultValue, { scope, domain })); } } } @@ -383,6 +395,19 @@ export class PreferenceSchemaProvider extends PreferenceProvider { } } + protected updateSchemaPropsDefault(key: string, property: PreferenceDataProperty): void { + this.combinedSchema.properties[key].default = property.default; + this.combinedSchema.properties[key].defaultValue = property.defaultValue; + if (this.workspaceSchema.properties[key]) { + this.workspaceSchema.properties[key].default = property.default; + this.workspaceSchema.properties[key].defaultValue = property.defaultValue; + } + if (this.folderSchema.properties[key]) { + this.folderSchema.properties[key].default = property.default; + this.folderSchema.properties[key].defaultValue = property.defaultValue; + } + } + protected removePropFromSchemas(key: string): void { // If we remove a key from combined, it should also be removed from all narrower scopes. delete this.combinedSchema.properties[key]; diff --git a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts index fe671d99b6dd3..50075206eb8dd 100644 --- a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts +++ b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts @@ -27,7 +27,7 @@ import { LabelProviderContribution, PreferenceSchemaProvider } from '@theia/core/lib/browser'; -import { PreferenceLanguageOverrideService, PreferenceSchema, PreferenceSchemaProperties } from '@theia/core/lib/browser/preferences'; +import { DefaultOverridesPreferenceSchemaId, PreferenceLanguageOverrideService, PreferenceSchema, PreferenceSchemaProperties } from '@theia/core/lib/browser/preferences'; import { KeybindingsContributionPointHandler } from './keybindings/keybindings-contribution-handler'; import { MonacoSnippetSuggestProvider } from '@theia/monaco/lib/browser/monaco-snippet-suggest-provider'; import { PluginSharedStyle } from './plugin-shared-style'; @@ -487,7 +487,7 @@ export class PluginContributionHandler { protected updateDefaultOverridesSchema(configurationDefaults: PreferenceSchemaProperties): Disposable { const defaultOverrides: PreferenceSchema = { - id: 'defaultOverrides', + id: DefaultOverridesPreferenceSchemaId, title: 'Default Configuration Overrides', properties: {} }; @@ -495,11 +495,18 @@ export class PluginContributionHandler { for (const key in configurationDefaults) { const defaultValue = configurationDefaults[key]; if (this.preferenceOverrideService.testOverrideValue(key, defaultValue)) { + // language specific override defaultOverrides.properties[key] = { type: 'object', default: defaultValue, description: `Configure editor settings to be overridden for ${key} language.` }; + } else { + // regular configuration override + defaultOverrides.properties[key] = { + default: defaultValue, + description: `Configure default setting for ${key}.` + }; } } if (Object.keys(defaultOverrides.properties).length) { diff --git a/packages/preferences/src/browser/views/components/preference-select-input.ts b/packages/preferences/src/browser/views/components/preference-select-input.ts index 62e7cf8291754..81a806a2f7bc0 100644 --- a/packages/preferences/src/browser/views/components/preference-select-input.ts +++ b/packages/preferences/src/browser/views/components/preference-select-input.ts @@ -30,12 +30,14 @@ export class PreferenceSelectInputRenderer extends PreferenceLeafNodeRenderer(); + protected selectOptions: SelectOption[] = []; + protected get enumValues(): JSONValue[] { return this.preferenceNode.preference.data.enum!; } - protected get selectOptions(): SelectOption[] { - const items: SelectOption[] = []; + protected updateSelectOptions(): void { + const updatedSelectOptions: SelectOption[] = []; const values = this.enumValues; const preferenceData = this.preferenceNode.preference.data; const defaultValue = preferenceData.default; @@ -51,7 +53,7 @@ export class PreferenceSelectInputRenderer extends PreferenceLeafNodeRenderer