Skip to content

Commit

Permalink
#19733 Default configurations
Browse files Browse the repository at this point in the history
- Define a new extension point `configurationDefaults` for contributing default language specific editor settings
  • Loading branch information
sandy081 committed Feb 8, 2017
1 parent 3ba88b6 commit b68f3b2
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 56 deletions.
6 changes: 6 additions & 0 deletions extensions/vscode-api-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
"default": "get-prop"
}
}
},
"configurationDefaults": {
"[abcLang]": {
"editor.lineNumbers": "off",
"editor.tabSize": 2
}
}
},
"scripts": {
Expand Down
20 changes: 20 additions & 0 deletions extensions/vscode-api-tests/src/configuration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as assert from 'assert';
import * as vscode from 'vscode';

suite('Configuration tests', () => {

test('Default configurations', function () {
const defaultLanguageSettings = vscode.workspace.getConfiguration().get('[abcLang]');

assert.deepEqual(defaultLanguageSettings, {
'editor.lineNumbers': 'off',
'editor.tabSize': 2
});
});

});
85 changes: 48 additions & 37 deletions src/vs/platform/configuration/common/configurationRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ export interface IConfigurationNode {
overridable?: boolean;
}

export interface IConfigurationExtension extends IConfigurationNode {
defaults?: any;
export interface IDefaultConfigurationExtension {
id: string;
name: string;
defaults: { [key: string]: {} };
}

const schemaId = 'vscode://schemas/settings';
Expand Down Expand Up @@ -106,7 +108,6 @@ class ConfigurationRegistry implements IConfigurationRegistry {

public registerConfigurations(configurations: IConfigurationNode[]): void {
configurations.forEach(configuration => {
this.registerDefaultOverrides(configuration); /// fills in default overrides
this.registerProperties(configuration); // fills in defaults
this.configurationContributors.push(configuration);
this.registerJSONConfiguration(configuration);
Expand All @@ -121,25 +122,26 @@ class ConfigurationRegistry implements IConfigurationRegistry {
this.updateOverridePropertyPatternKey();
}

private registerDefaultOverrides(configurationNode: IConfigurationExtension): void {
if (!configurationNode.defaults) {
return;
}

for (const key in configurationNode.defaults) {
const defaultValue = configurationNode.defaults[key];
if (OVERRIDE_PROPERTY_PATTERN.test(key) && typeof defaultValue === 'object') {
if (!configurationNode.properties) {
configurationNode.properties = {};
public registerDefaultConfigurations(defaultConnfigurations: IDefaultConfigurationExtension[]): void {
const configurationNode: IConfigurationNode = {
id: 'defaultOverrides',
title: nls.localize('defaultConfigurations.title', "Default Configuration Overrides"),
properties: {}
};
for (const defaultConfiguration of defaultConnfigurations) {
for (const key in defaultConfiguration.defaults) {
const defaultValue = defaultConfiguration.defaults[key];
if (OVERRIDE_PROPERTY_PATTERN.test(key) && typeof defaultValue === 'object') {
configurationNode.properties[key] = {
type: 'object',
default: defaultValue,
description: nls.localize('overrideSettings.description', "Configure editor settings to be overridden for {0} language.", key),
$ref: editorConfigurationSchemaId
};
}
configurationNode.properties[key] = {
type: 'object',
default: defaultValue,
description: nls.localize('overrideSettings.description', "Configure editor settings to be overridden for {0} language.", key),
$ref: editorConfigurationSchemaId
};
}
}
this.registerConfigurations([configurationNode]);
}

private registerProperties(configuration: IConfigurationNode, overridable: boolean = false) {
Expand Down Expand Up @@ -291,26 +293,15 @@ const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint<IConfigu
}
]
}
},
defaults: {
description: nls.localize('vscode.extension.contributes.configuration.defaults', 'Override default editor settings for a language'),
type: 'object',
patternProperties: {
'\\[.*\\]$': {
type: 'object',
default: {},
$ref: editorConfigurationSchemaId,
}
}
}
}
});

configurationExtPoint.setHandler(extensions => {
const configurations: IConfigurationExtension[] = [];
const configurations: IConfigurationNode[] = [];

for (let i = 0; i < extensions.length; i++) {
const configuration = <IConfigurationExtension>extensions[i].value;
const configuration = <IConfigurationNode>extensions[i].value;
const collector = extensions[i].collector;

if (configuration.type && configuration.type !== 'object') {
Expand All @@ -328,15 +319,35 @@ configurationExtPoint.setHandler(extensions => {
return;
}

if (configuration.defaults && typeof configuration.defaults !== 'object') {
collector.error(nls.localize('invalid.defaults', "'configuration.defaults' must be an object"));
return;
}

const clonedConfiguration = objects.clone(configuration);
clonedConfiguration.id = extensions[i].description.id;
configurations.push(clonedConfiguration);
}

configurationRegistry.registerConfigurations(configurations);
});

const defaultConfigurationExtPoint = ExtensionsRegistry.registerExtensionPoint<IConfigurationNode>('configurationDefaults', [], {
description: nls.localize('vscode.extension.contributes.defaultConfiguration', 'Contributes default editor configuration settings by language.'),
type: 'object',
defaultSnippets: [{ body: {} }],
patternProperties: {
'\\[.*\\]$': {
type: 'object',
default: {},
$ref: editorConfigurationSchemaId,
}
}
});

defaultConfigurationExtPoint.setHandler(extensions => {
const defaultConfigurations: IDefaultConfigurationExtension[] = extensions.map(extension => {
const id = extension.description.id;
const name = extension.description.name;
const defaults = objects.clone(extension.value);
return <IDefaultConfigurationExtension>{
id, name, defaults
};
});
configurationRegistry.registerDefaultConfigurations(defaultConfigurations);
});
21 changes: 2 additions & 19 deletions src/vs/platform/configuration/test/common/model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,17 @@

import * as assert from 'assert';
import * as model from 'vs/platform/configuration/common/model';
import { Extensions, IConfigurationRegistry, IConfigurationExtension } from 'vs/platform/configuration/common/configurationRegistry';
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { Registry } from 'vs/platform/platform';

suite('ConfigurationService - Model', () => {

suiteSetup(() => {
Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfiguration(<IConfigurationExtension>{
Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfiguration({
'id': 'a',
'order': 1,
'title': 'a',
'type': 'object',
'defaults': {
'[b]': {
'a': false
}
},
'properties': {
'a': {
'description': 'a',
Expand Down Expand Up @@ -131,16 +126,4 @@ suite('ConfigurationService - Model', () => {
assert.deepEqual(testObject.keys, []);
});

test('Test default settings', () => {
const testObject = new model.DefaultConfigModel();

assert.equal(testObject.getContentsFor('a'), true);
assert.deepEqual(testObject.getContentsFor('[b]'), { 'a': false });
assert.ok(testObject.keys.indexOf('a') !== -1);
assert.ok(testObject.keys.indexOf('[b]') !== -1);
assert.deepEqual(testObject.overrides, [{
identifiers: ['b'],
contents: { 'a': false }
}]);
});
});

0 comments on commit b68f3b2

Please sign in to comment.